Den här artikeln handlar om formulär i ASP.NET Core, hur man validerar dem och hur man skickar in datan. Syftet med ett formulär är att samla in data, validera denna data och spara datan i en databas.
För att skapa och sända ett formulär i ASP.NET Core behöver du en vy, en controller och en modell. Du kan skicka formuläret direkt till controllern eller använda ajax/javascript för att skicka formuläret till en controller. Formvalidering görs vanligtvis genom en kombination av javascript och metoder i en controller.
Kodning av formulärdata
Formulärdata kan kodas på 3 olika sätt, den typ som används är specificerad i attributet enctype i formtaggen.
application/x-www-form-urlencoded: Data skickas som nyckelvärdespar och alla data är kodade.
multipart/form-data: Data skickas som sektioner och ingen data kodas. Denna typ måste användas om du har en filuppladdningskontroll i ditt formulär.
text/plain: Data skickas som den är, ingen kodning. Kan användas för att skicka ett JSON-dokument eller ett XML-dokument.
Bibliotek
Vi behöver några jquery/javascript-bibliotek för vårt formulär. Dessa bibliotek importeras i vår layoutvy, det är smidigt att importera alla bibliotek på ett ställe. Jquery används för att posta formuläret med ajax och används vid validering. Toastr används för att skicka små meddelanden till användaren och Font Awesome används för att få snygga ikoner.
Jquery validation och Jquery validate unobtrusive används för att validera formuläret.
<environment names="Development">
<link href="@this.tools.GetFilePath("/css/toastr.css")" rel="stylesheet" />
<script src="/js/jquery/v3.3.1/jquery.js"></script>
<script src="/js/jquery-validation/v1.17.0/jquery.validate.js"></script>
<script src="/js/jquery-validation-unobtrusive/v3.2.8/jquery.validate.unobtrusive.js"></script>
<script src="/js/toastr/v2.1.4/toastr.js"></script>
<script src="/js/js-cookie/v2.2.0/js.cookie.js"></script>
<script src="/js/font-awesome/v5.3.1/all.js"></script>
</environment>
<environment names="Staging,Production">
<link href="@this.tools.GetFilePath("/css/toastr.min.css")" rel="stylesheet" />
<script src="/js/jquery/v3.3.1/jquery.min.js"></script>
<script src="/js/jquery-validation/v1.17.0/jquery.validate.min.js"></script>
<script src="/js/jquery-validation-unobtrusive/v3.2.8/jquery.validate.unobtrusive.min.js"></script>
<script src="/js/toastr/v2.1.4/toastr.min.js"></script>
<script src="/js/js-cookie/v2.2.0/js.cookie.min.js"></script>
<script src="/js/font-awesome/v5.3.1/all.min.js"></script>
</environment>
Modeller
Huvudmodellerna för vårt formulär är ResponseData, StaticPageDocument och StaticPageDetail. ResponseData används för att skicka meddelanden till användaren och de andra två modellerna är viktiga för att visa och spara data i formuläret.
public class ResponseData
{
#region variables
public bool success { get; set; }
public string id { get; set; }
public string message { get; set; }
public string url { get; set; }
#endregion
#region Constructors
public ResponseData()
{
// Set values for instance variables
this.success = false;
this.id = "";
this.message = "";
this.url = "";
} // End of the constructor
public ResponseData(bool success, string id, string message)
{
// Set values for instance variables
this.success = success;
this.id = id;
this.message = message;
this.url = "";
} // End of the constructor
public ResponseData(bool success, string id, string message, string url)
{
// Set values for instance variables
this.success = success;
this.id = id;
this.message = message;
this.url = url;
} // End of the constructor
#endregion
} // End of the class
public class StaticPageDocument
{
#region Variables
public string id { get; set; }
public string model_type { get; set; }
public Int32 connection_id { get; set; }
public string meta_robots { get; set; }
public Int32 show_as_page { get; set; }
public string page_name { get; set; }
public DateTime date_updated { get; set; }
public string main_image { get; set; }
public IList<string> images { get; set; }
public IList<string> keywords { get; set; }
public IDictionary<string, StaticPageDetail> translations { get; set; }
#endregion
#region Constructors
public StaticPageDocument()
{
// Set values for instance variables
this.id = Guid.NewGuid().ToString();
this.model_type = "static_page";
this.connection_id = 0;
this.meta_robots = "";
this.show_as_page = 0;
this.page_name = "";
this.date_updated = DateTime.UtcNow;
this.main_image = "";
this.images = new List<string>();
this.keywords = new List<string>();
this.translations = new Dictionary<string, StaticPageDetail>();
} // End of the constructor
#endregion
#region Get methods
public StaticPageDetail GetTranslation(string key)
{
// Create the string to return
StaticPageDetail translation = new StaticPageDetail();
// Check if the dictionary contains the key
if (this.translations.ContainsKey(key))
{
translation = this.translations[key];
}
// Return the value
return translation;
} // End of the GetTranslation method
#endregion
} // End of the class
public class StaticPageDetail
{
#region Variables
public string link_name { get; set; }
public string title { get; set; }
public string text_html { get; set; }
public string meta_description { get; set; }
public string meta_keywords { get; set; }
#endregion
#region Constructors
public StaticPageDetail()
{
// Set values for instance variables
this.link_name = "";
this.title = "";
this.text_html = "";
this.meta_description = "";
this.meta_keywords = "";
} // End of the constructor
#endregion
} // End of the class
Controller
Denna controller innehåller metoder som vi behöver för att administrera statiska sidor, denna klass utgör länken mellan vyer och arkivklasser. Denna controller ska returnera vyer och hantera postningar av formulär.
public class admin_static_pagesController : BaseController
{
#region Variables
private readonly IStaticPageRepository static_page_repository;
private readonly ILanguageRepository language_repository;
private readonly IWebDomainRepository web_domain_repository;
private readonly IStaticTextRepository static_text_repository;
private readonly IAdministratorRepository administrator_repository;
private readonly IBlobStorageRepository blob_storage_repository;
#endregion
#region Constructors
public admin_static_pagesController(IRazorViewEngine view_engine, IStaticPageRepository static_page_repository, ILanguageRepository language_repository,
IWebDomainRepository web_domain_repository, IStaticTextRepository static_text_repository, IAdministratorRepository administrator_repository,
IBlobStorageRepository blob_storage_repository) : base(view_engine)
{
// Set values for instance variables
this.static_page_repository = static_page_repository;
this.language_repository = language_repository;
this.web_domain_repository = web_domain_repository;
this.static_text_repository = static_text_repository;
this.administrator_repository = administrator_repository;
this.blob_storage_repository = blob_storage_repository;
} // End of the constructor
#endregion
#region View methods
[HttpGet]
[Authorize(Roles = "Administrator,Editor,Translator")]
public async Task<IActionResult> index()
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get keywords
string kw = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("kw") == true)
{
kw = ControllerContext.HttpContext.Request.Query["kw"];
}
// Get the sort field
string sf = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("sf") == true)
{
sf = ControllerContext.HttpContext.Request.Query["sf"];
}
// Get the sort order
string so = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("so") == true)
{
so = ControllerContext.HttpContext.Request.Query["so"];
}
// Get the page size
Int32 pz = 10;
if (ControllerContext.HttpContext.Request.Query.ContainsKey("pz") == true)
{
Int32.TryParse(ControllerContext.HttpContext.Request.Query["pz"], out pz);
}
// Add data to the view
ViewBag.CurrentDomain = current_domain;
ViewBag.TranslatedTexts = tt;
ViewBag.AuthorizationLevel = this.administrator_repository.GetAuthorizationLevel(ControllerContext.HttpContext.User);
ViewBag.Keywords = kw;
ViewBag.SortField = sf;
ViewBag.SortOrder = so;
ViewBag.PageSize = pz;
// Return the view
return View();
} // End of the index method
[HttpGet]
[Authorize(Roles = "Administrator,Editor")]
public async Task<IActionResult> edit(string id = "")
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get keywords
string kw = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("kw") == true)
{
kw = ControllerContext.HttpContext.Request.Query["kw"];
}
// Get the sort field
string sf = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("sf") == true)
{
sf = ControllerContext.HttpContext.Request.Query["sf"];
}
// Get the sort order
string so = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("so") == true)
{
so = ControllerContext.HttpContext.Request.Query["so"];
}
// Get the page size
Int32 pz = 10;
if (ControllerContext.HttpContext.Request.Query.ContainsKey("pz") == true)
{
Int32.TryParse(ControllerContext.HttpContext.Request.Query["pz"], out pz);
}
// Get items
ModelItem<StaticPageDocument> static_page_model = await this.static_page_repository.GetById(id);
// Add data to the view
ViewBag.CurrentDomain = current_domain;
ViewBag.TranslatedTexts = tt;
ViewBag.AuthorizationLevel = this.administrator_repository.GetAuthorizationLevel(ControllerContext.HttpContext.User);
ViewBag.Post = static_page_model.item != null ? static_page_model.item : new StaticPageDocument();
ViewBag.Keywords = kw;
ViewBag.SortField = sf;
ViewBag.SortOrder = so;
ViewBag.PageSize = pz;
// Return the edit view
return View("edit");
} // End of the edit method
[HttpGet]
[Authorize(Roles = "Administrator,Editor,Translator")]
public async Task<IActionResult> translate(string id = "", string lang = "")
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get keywords
string kw = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("kw") == true)
{
kw = ControllerContext.HttpContext.Request.Query["kw"];
}
// Get the sort field
string sf = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("sf") == true)
{
sf = ControllerContext.HttpContext.Request.Query["sf"];
}
// Get the sort order
string so = "";
if (ControllerContext.HttpContext.Request.Query.ContainsKey("so") == true)
{
so = ControllerContext.HttpContext.Request.Query["so"];
}
// Get the page size
Int32 pz = 10;
if (ControllerContext.HttpContext.Request.Query.ContainsKey("pz") == true)
{
Int32.TryParse(ControllerContext.HttpContext.Request.Query["pz"], out pz);
}
// Get items
ModelItem<LanguagesDocument> languages_model = await this.language_repository.GetByType();
ModelItem<StaticPageDocument> static_page_model = await this.static_page_repository.GetById(id);
// Add data to the view
ViewBag.CurrentDomain = current_domain;
ViewBag.TranslatedTexts = tt;
ViewBag.AuthorizationLevel = this.administrator_repository.GetAuthorizationLevel(ControllerContext.HttpContext.User);
ViewBag.Post = static_page_model.item;
ViewBag.LanguageCode = lang;
ViewBag.Languages = languages_model.item;
ViewBag.Keywords = kw;
ViewBag.SortField = sf;
ViewBag.SortOrder = so;
ViewBag.PageSize = pz;
// Redirect the user if the post is null
if (ViewBag.Post == null)
{
// Redirect the user to the list
return Redirect("/admin_static_pages");
}
// Return the view
return View();
} // End of the translate method
#endregion
#region Post methods
[HttpPost]
public IActionResult search(IFormCollection collection)
{
// Get the search data
string keywordString = collection["txtSearch"];
string sort_field = collection["selectSortField"];
string sort_order = collection["selectSortOrder"];
string page_size = collection["selectPageSize"];
// Return the url with search parameters
return Redirect("/admin_static_pages?kw=" + WebUtility.UrlEncode(keywordString) + "&sf=" + sort_field + "&so=" + sort_order + "&pz=" + page_size);
} // End of the search method
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Administrator,Editor")]
public async Task<IActionResult> edit(IFormCollection collection)
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get the id
string id = collection["txtId"].ToString();
// Get the static page document
ModelItem<StaticPageDocument> static_page_model = await this.static_page_repository.GetById(id);
StaticPageDocument post = static_page_model.item;
// Make sure that the post not is null
if (post == null)
{
post = new StaticPageDocument();
post.id = id;
}
// Update values
post.connection_id = DataValidation.ParseInt32(collection["selectConnection"].ToString(), 0);
post.meta_robots = collection["selectMetaRobots"].ToString();
post.show_as_page = DataValidation.ParseInt32(collection["cbShowAsPage"], 0);
post.date_updated = DateTime.UtcNow;
post.page_name = collection["txtPageName"].ToString();
post.main_image = collection["txtMainImage"].ToString();
post.keywords = collection["txtKeywords"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries);
// Make sure that keywords is lowercase and trimmed
for (int i = 0; i < post.keywords.Count; i++)
{
post.keywords[i] = post.keywords[i].ToLower().Trim();
}
if (post.translations.ContainsKey(current_domain.back_end_language_code) == true)
{
// Get the detail post
StaticPageDetail dp = post.translations[current_domain.back_end_language_code];
dp.link_name = collection["txtLinkName"].ToString();
dp.meta_description = collection["txtMetaDescription"].ToString();
dp.meta_keywords = collection["txtMetaKeywords"].ToString();
dp.text_html = collection["txtTextHtml"].ToString();
dp.title = collection["txtTitle"].ToString();
}
else
{
// Create a new detail post
StaticPageDetail dp = new StaticPageDetail();
dp.link_name = collection["txtLinkName"].ToString();
dp.meta_description = collection["txtMetaDescription"].ToString();
dp.meta_keywords = collection["txtMetaKeywords"].ToString();
dp.text_html = collection["txtTextHtml"].ToString();
dp.title = collection["txtTitle"].ToString();
// Add the detail post
post.translations.Add(current_domain.back_end_language_code, dp);
}
// Verify the page name
ResponseData data = await verify_page_name(tt, post.id, post.page_name);
// Return an error response
if (data.success == false)
{
return Json(data: data);
}
// Add or update the post
await this.static_page_repository.Upsert(post);
// Return a success response
return Json(data: new ResponseData(true, "", String.Format(tt.Get("success_post_updated"), tt.Get("static_page") + " (" + post.id + ")")));
} // End of the edit method
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Administrator,Editor,Translator")]
public async Task<IActionResult> translate(IFormCollection collection)
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get the id
string id = collection["txtId"].ToString();
string language_code = collection["selectLanguage"].ToString();
// Get the static page document
ModelItem<StaticPageDocument> static_page_model = await this.static_page_repository.GetById(id);
StaticPageDocument post = static_page_model.item;
// Make sure that the post not is null
if (post == null)
{
// Return an error response
return Json(data: new ResponseData(false, "", String.Format(tt.Get("error-field-invalid"), tt.Get("id") + ": " + post.id)));
}
// Update values
if (post.translations.ContainsKey(language_code) == true)
{
// Update the detail post
StaticPageDetail dp = post.translations[language_code];
dp.link_name = collection["txtTranslatedLinkName"].ToString();
dp.meta_description = collection["txtTranslatedMetaDescription"].ToString();
dp.meta_keywords = collection["txtTranslatedMetaKeywords"].ToString();
dp.text_html = collection["txtTranslatedTextHtml"].ToString();
dp.title = collection["txtTranslatedTitle"].ToString();
}
else
{
// Create a new detail post
StaticPageDetail dp = new StaticPageDetail();
dp.link_name = collection["txtTranslatedLinkName"].ToString();
dp.meta_description = collection["txtTranslatedMetaDescription"].ToString();
dp.meta_keywords = collection["txtTranslatedMetaKeywords"].ToString();
dp.text_html = collection["txtTranslatedTextHtml"].ToString();
dp.title = collection["txtTranslatedTitle"].ToString();
// Add the detail post
post.translations.Add(language_code, dp);
}
// Update the post
await this.static_page_repository.Update(post);
// Return a success response
return Json(data: new ResponseData(true, "", String.Format(tt.Get("success_post_updated"), tt.Get("static_page") + " (" + post.id + ")")));
} // End of the translate method
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Administrator,Editor,Translator")]
public async Task<IActionResult> images(IFormCollection collection)
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get the id
string id = collection["txtId"].ToString();
// Get the static page document
ModelItem<StaticPageDocument> static_page_model = await this.static_page_repository.GetById(id);
StaticPageDocument post = static_page_model.item;
// Make sure that the post not is null
if (post == null)
{
// Return an error response
return Json(data: new ResponseData(false, "", String.Format(tt.Get("error_no_post_found"), id)));
}
// Check for images to delete
IList<string> images = collection["txtImageSrc"].ToArray();
foreach(string src in post.images)
{
if(images.Contains(src) == false)
{
// Delete the image
await this.blob_storage_repository.Delete("media", src);
}
}
// Set images
post.images = new List<string>();
foreach (string img in images)
{
post.images.Add(img);
}
// Get files
IFormFileCollection files = collection.Files;
for (int i = 0; i < files.Count; i++)
{
// Just continue if the file is empty
if (files[i].Length == 0)
continue;
// Get the filename
string filename = Guid.NewGuid().ToString() + Path.GetExtension(files[i].FileName);
// Add the blob
await this.blob_storage_repository.UploadFromStream("media", filename, files[i].OpenReadStream());
// Add the image src to the list
post.images.Add(filename);
}
// Add or update the post
await this.static_page_repository.Upsert(post);
// Return a success response
return Json(data: new ResponseData(true, string.Join("|", post.images), String.Format(tt.Get("success_post_updated"), tt.Get("static_page") + " (" + post.id + ")")));
} // End of the images method
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> delete(IFormCollection collection)
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Get translated texts
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get the id
string id = collection["id"].ToString();
// Get the post
ModelItem<StaticPageDocument> page_model = await this.static_page_repository.GetById(id);
// Remove images
foreach(string src in page_model.item.images)
{
// Delete the image
await this.blob_storage_repository.Delete("media", src);
}
// Try to delete a post
bool success = await this.static_page_repository.DeleteOnId(id);
// Return an error response
if (success == false)
{
return Json(data: new ResponseData(false, "", String.Format(tt.Get("error_delete_post"), tt.Get("static_page") + " (" + id + ")")));
}
// Return a success response
return Json(data: new ResponseData(true, id.ToString(), String.Format(tt.Get("success_delete_post"), tt.Get("static_page") + " (" + id + ")")));
} // End of the delete method
#endregion
#region Validation
public async Task<ResponseData> verify_page_name(KeyStringList tt, string id = "", string page_name = "")
{
// Get the current domain
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
// Make sure that there is a page_name
if (page_name == "")
{
return new ResponseData(false, "", String.Format(tt.Get("error_field_required"), tt.Get("page_name")));
}
// Check for invalid characters
if (DataValidation.CheckPageNameCharacters(page_name) == false)
{
return new ResponseData(false, "", String.Format(tt.Get("error_field_bad_chars"), tt.Get("page_name")));
}
// Get a static page on page name
ModelItem<StaticPagePost> page_name_model = await this.static_page_repository.GetByPageName(page_name, current_domain.back_end_language_code);
// Check if the page name exists already
if (page_name_model.item != null && id != page_name_model.item.id)
{
return new ResponseData(false, "", String.Format(tt.Get("error_field_unique"), tt.Get("page_name")));
}
// Return a success response
return new ResponseData(true, id, "");
} // End of the verify_page_name method
#endregion
#region Ajax methods
[HttpPost]
public async Task<IActionResult> index_list(IFormCollection collection)
{
// Get objects
WebDomain current_domain = await this.web_domain_repository.GetCurrentDomain(ControllerContext.HttpContext);
KeyStringList tt = await this.static_text_repository.GetFromCache(current_domain.back_end_language_code);
// Get the form data
string kw = collection["kw"].ToString();
string sf = collection["sf"].ToString();
string so = collection["so"].ToString();
Int32 pz = Convert.ToInt32(collection["pz"].ToString());
string ct = collection["ct"].ToString();
// Get posts by keywords in a search
ModelPage<StaticPageMeta> static_pages_page = await this.static_page_repository.GetBySearch(kw, current_domain.back_end_language_code, sf, so, pz, ct);
// Add data to the form
ViewBag.CurrentDomain = current_domain;
ViewBag.TranslatedTexts = tt;
ViewBag.CultureInfo = Tools.GetCultureInfo(current_domain.back_end_language_code, current_domain.country_code);
ViewBag.Items = static_pages_page.items;
ViewBag.Continuation = static_pages_page.ct;
// Return the partial view
return PartialView("/Views/admin_static_pages/_index_list.cshtml");
} // End of the index_list method
#endregion
} // End of the class
Vy
Den här vyn används för att lägga till och uppdatera statiska sidor. Formuläret skickas med ajax, ersätt knappkontrollen (button) med en inlämningskontroll (submit) om du vill skicka formuläret direkt till controllern. Formulär skickas till webbadressen i action-attributet.
@{
// Set the layout for the page
Layout = "/Views/shared_admin/_standard_layout.cshtml";
// Get form data
WebDomain current_domain = ViewBag.CurrentDomain;
KeyStringList tt = ViewBag.TranslatedTexts;
Int32 authorizationLevel = ViewBag.AuthorizationLevel;
StaticPageDocument post = ViewBag.Post;
StaticPageDetail spd = post.GetTranslation(current_domain.back_end_language_code);
// Set texts
string static_page_tt = tt.Get("static_page");
string new_tt = tt.Get("new");
string edit_tt = tt.Get("edit");
string id_tt = tt.Get("id");
string connection_tt = tt.Get("connection");
string no_connection_tt = tt.Get("no_connection");
string start_page_tt = tt.Get("start_page");
string error_tt = tt.Get("error");
string terms_of_service_tt = tt.Get("terms_of_service");
string privacy_policy_tt = tt.Get("privacy_policy");
string about_us_tt = tt.Get("about_us");
string contact_us_tt = tt.Get("contact_us");
string api_tt = tt.Get("api");
string standards_tt = tt.Get("standards");
string editor_tt = tt.Get("editor");
string blog_tt = tt.Get("blog");
string validate_tt = tt.Get("validate");
string show_as_page_tt = tt.Get("show_as_page");
string keywords_tt = tt.Get("keywords");
string page_name_tt = tt.Get("page_name");
string linkname_tt = tt.Get("linkname");
string title_tt = tt.Get("title");
string text_html_tt = tt.Get("text_html");
string meta_description_tt = tt.Get("meta_description");
string meta_keywords_tt = tt.Get("meta_keywords");
string meta_robots_tt = tt.Get("meta_robots");
string save_tt = tt.Get("save");
string cancel_tt = tt.Get("cancel");
string main_image_tt = tt.Get("main_image");
string images_tt = tt.Get("images");
string upload_tt = tt.Get("upload");
string delete_tt = tt.Get("delete");
// Set the title for the page
if (post.translations.Count == 0)
{
ViewBag.Title = static_page_tt + " - " + new_tt.ToLower();
}
else
{
ViewBag.Title = static_page_tt + " - " + edit_tt.ToLower();
}
}
@*Title*@
<h1>@ViewBag.Title</h1>
@*Menu*@
@await Html.PartialAsync("/Views/admin_static_pages/_form_menu.cshtml")
@*Main form*@
<form id="inputForm" action="/admin_static_pages/edit" method="post" enctype="multipart/form-data">
@*Hidden data*@
<input id="authorizationLevel" type="hidden" value="@authorizationLevel.ToString()" />
<input id="errorNotUnique" type="hidden" value="@tt.Get("error_field_unique")" />
<input id="errorNotAuthorized" type="hidden" value="@tt.Get("error_not_authorized")" />
@Html.AntiForgeryToken()
@*Input form*@
<div class="annytab-form-label">@id_tt</div>
<input id="txtId" name="txtId" type="text" class="annytab-form-control" tabindex="-1" readonly value="@post.id" />
<div class="annytab-form-label">@connection_tt</div>
<select id="selectConnection" name="selectConnection" class="annytab-form-control">
<!option value="0" @(post.connection_id == 0 ? "selected" : "")>@no_connection_tt</!option>
<!option value="1" @(post.connection_id == 1 ? "selected" : "")>@start_page_tt</!option>
<!option value="2" @(post.connection_id == 2 ? "selected" : "")>@error_tt</!option>
<!option value="3" @(post.connection_id == 3 ? "selected" : "")>@terms_of_service_tt</!option>
<!option value="4" @(post.connection_id == 4 ? "selected" : "")>@privacy_policy_tt</!option>
<!option value="5" @(post.connection_id == 5 ? "selected" : "")>@about_us_tt</!option>
<!option value="6" @(post.connection_id == 6 ? "selected" : "")>@contact_us_tt</!option>
<!option value="7" @(post.connection_id == 7 ? "selected" : "")>@api_tt</!option>
<!option value="8" @(post.connection_id == 8 ? "selected" : "")>@standards_tt</!option>
<!option value="9" @(post.connection_id == 9 ? "selected" : "")>@editor_tt</!option>
<!option value="10" @(post.connection_id == 10 ? "selected" : "")>@blog_tt</!option>
<!option value="11" @(post.connection_id == 11 ? "selected" : "")>@validate_tt</!option>
</select>
<div class="annytab-form-label">@meta_robots_tt</div>
<select name="selectMetaRobots" class="annytab-form-control">
<!option value="index, follow" @(post.meta_robots == "index, follow" ? "selected" : "")>index, follow</!option>
<!option value="index, nofollow" @(post.meta_robots == "index, nofollow" ? "selected" : "")>index, nofollow</!option>
<!option value="noindex, follow" @(post.meta_robots == "noindex, follow" ? "selected" : "")>noindex, follow</!option>
<!option value="noindex, nofollow" @(post.meta_robots == "noindex, nofollow" ? "selected" : "")>noindex, nofollow</!option>
</select>
<div class="annytab-form-label">@show_as_page_tt</div>
<div class="annytab-input-group">
<div class="input-group-cell" style="width:40px;border-right:1px solid #d9d9d9;">
<input name="cbShowAsPage" type="checkbox" class="annytab-form-checkbox" value="1" @(post != null && post.show_as_page == 1 ? "checked" : "") />
</div>
<div class="input-group-cell" style="width:1200px;text-align:left;padding-left:5px;">
<div class="input-group-control">@show_as_page_tt</div>
</div>
</div>
<div class="annytab-form-label">@page_name_tt</div>
<input name="txtPageName" type="text" class="annytab-form-control" value="@post.page_name" data-val="true" data-val-required="@String.Format(tt.Get("error_field_required"), page_name_tt)" />
<div class="field-validation-valid" data-valmsg-for="txtPageName" data-valmsg-replace="true"></div>
<div class="annytab-form-label">@main_image_tt</div>
<input name="txtMainImage" type="text" class="annytab-form-control" value="@post.main_image" />
<div class="annytab-form-label">@keywords_tt</div>
<textarea name="txtKeywords" class="annytab-form-control" rows="3">@string.Join(",", post.keywords)</textarea>
<div class="field-validation-valid" data-valmsg-for="txtKeywords" data-valmsg-replace="true"></div>
<div class="annytab-form-label">@linkname_tt</div>
<input name="txtLinkName" type="text" class="annytab-form-control" value="@spd.link_name" data-val="true" data-val-required="@String.Format(tt.Get("error_field_required"), linkname_tt)" />
<div class="field-validation-valid" data-valmsg-for="txtLinkName" data-valmsg-replace="true"></div>
<div class="annytab-form-label">@title_tt</div>
<input name="txtTitle" type="text" class="annytab-form-control" value="@spd.title" data-val="true" data-val-required="@String.Format(tt.Get("error_field_required"), title_tt)" />
<div class="field-validation-valid" data-valmsg-for="txtTitle" data-valmsg-replace="true"></div>
<div class="annytab-form-label">@text_html_tt</div>
<textarea name="txtTextHtml" class="annytab-form-control" rows="10">@spd.text_html</textarea>
<div class="field-validation-valid" data-valmsg-for="txtTextHtml" data-valmsg-replace="true"></div>
<div class="annytab-form-label">@meta_description_tt</div>
<textarea name="txtMetaDescription" class="annytab-form-control" rows="5">@spd.meta_description</textarea>
<div class="field-validation-valid" data-valmsg-for="txtMetaDescription" data-valmsg-replace="true"></div>
<div class="annytab-form-label">@meta_keywords_tt</div>
<textarea name="txtMetaKeywords" class="annytab-form-control" rows="5">@spd.meta_keywords</textarea>
<div class="field-validation-valid" data-valmsg-for="txtMetaKeywords" data-valmsg-replace="true"></div>
<div class="annytab-basic-space"></div>
@*Button panel*@
<div class="annytab-form-button-container">
<input type="button" class="annytab-form-button" value="@save_tt" onclick="submitForm($('#inputForm'))" />
<a href="/admin_static_pages" class="annytab-form-button">@cancel_tt</a>
</div>
</form>
<form id="imageForm" action="/admin_static_pages/images" method="post" enctype="multipart/form-data">
@*Hidden data*@
<input name="txtId" type="hidden" value="@post.id" />
@Html.AntiForgeryToken()
@*Input form*@
<div class="annytab-form-label">@images_tt</div>
<input id="fuImages" name="fuImages" type="file" class="annytab-form-control" multiple />
<div id="imageContainer">
@foreach (string src in post.images)
{
<div style="margin-top:20px;">
<img src="@("https://mysite.blob.core.windows.net/media/" + src)" class="annytab-form-image" /><br />
<span class="annytab-basic-bread-text">@("https://mysite.blob.core.windows.net/media/" + src) - <i class="far fa-trash-alt annytab-basic-link remove-image"></i></span>
<input name="txtImageSrc" type="hidden" value="@src" />
</div>
}
</div>
<div class="annytab-basic-space"></div>
@*Button panel*@
<div class="annytab-form-button-container">
<input type="button" class="annytab-form-button" value="@save_tt" onclick="uploadImages($('#imageForm'))" />
</div>
</form>
@section scripts {
<script type="text/javascript">
// Set default focus
$("#selectConnection").focus();
$(document).on('click', '.remove-image', function () {
$(this).parent().parent().remove();
});
// Submit the form
function uploadImages(form)
{
// Get form data
var form_data = new FormData(form[0]);
$.ajax({
type: 'POST',
url: form.attr('action'),
dataType: 'json',
data: form_data,
processData: false,
contentType: false,
success: function (data) {
if (data.success === true) {
$('#imageContainer').html('');
var images = data.id != "" ? data.id.split('|') : null;
for (var i in images)
{
$('#imageContainer').append('<div style="margin-top:20px;"><img src="https://mysite.blob.core.windows.net/media/'
+ images[i] + '" class="annytab-form-image" /><br /><span class="annytab-basic-bread-text">https://mysite.blob.core.windows.net/media/'
+ images[i] + ' - <i class="far fa-trash-alt annytab-basic-link remove-image"></i></span><input name="txtImageSrc" type="hidden" value="'
+ images[i] + '" /></div>');
}
toastr['success'](data.message);
}
else
{
toastr['error'](data.message);
}
$('#fuImages').val('');
}
});
} // End of the uploadImages method
</script>
}
Skicka formulär utan ajax
För att skicka in ett formulär utan ajax/javascript måste du ha en inlämningsknapp (submit) i formuläret. Formuläret skickas till den url som anges i attributet action.
<input type="submit" class="form-button" value="Save" />
Skicka formulär med ajax
För att skicka in ett formulär med ajax behöver vi en knapp med en onclick-händelse och en metod för att skicka formuläret till angiven url. Du kan avaktivera knappen efter ett klick om du vill förhindra att formuläret skickas in flera gånger.
<input type="button" class="annytab-form-button" value="Save" onclick="submitForm($('#inputForm'))" />
function submitForm(form)
{
// Make sure that the form is valid
if (form.valid() === false) { return false; }
// Get form data
var form_data = new FormData(form[0]);
$.ajax({
type: 'POST',
url: form.attr('action'),
dataType: 'json',
data: form_data,
processData: false,
contentType: false,
success: function (data) {
if (data.success === true) {
if (data.url !== "") {
location.href = data.url;
}
else {
toastr['success'](data.message);
}
}
else {
toastr['error'](data.message);
}
}
});
} // End of the submitForm method