MVC 4使用局部视图进行validation
我正在使用MVC 4和Entity Framework来开发一个Web应用程序。 我正在使用加载了javascript的部分视图。 其中之一是包含validation的创建视图。 这就是我的问题:validation。 我有一个自定义validation逻辑,例如,如果用户在某个字段(如“名称”)中输入了某些数字,则会显示错误。
在这里,使用部分视图,它将我的部分视图重定向到显示的错误,但我想要做的是留在我的主视图(索引视图)并保留显示错误的部分视图。
编辑:
这是我的部分观点:
@model BuSIMaterial.Models.Person @using (Html.BeginForm()) { @Html.ValidationSummary(true) } @section Scripts { @Scripts.Render("~/bundles/jqueryval") @Scripts.Render("~/bundles/jqueryui") @Styles.Render("~/Content/themes/base/css") }
在我看来,索引,我有这个:
以及我加载Partial View的方式:
$("#create").click(function () { var form = $("#create_person").closest("form"); form.removeData('validator'); form.removeData('unobtrusiveValidation'); $.validator.unobtrusive.parse(form); $.ajax({ url: "/Person/CreateOrUpdate", type: "POST", data: $("#create_person").serialize(), cache: false }); // var url = '/Person/CreatePerson'; // $("#create_person").load(url); });
行动 :
[HttpGet] public ActionResult CreateOrUpdate() { ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name"); return View(); } [HttpPost] public JsonResult CreateOrUpdate(Person person) { ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory); try { if (!ModelState.IsValid) { string messages = string.Join("; ", ModelState.Values .SelectMany(x => x.Errors) .Select(x => x.ErrorMessage)); throw new Exception("Please correct the following errors: " + Environment.NewLine + messages); } db.Persons.AddObject(person); db.SaveChanges(); return Json(new { Result = "OK" }); } catch (Exception ex) { return Json(new { Result = "ERROR", Message = ex.Message }); } }
如果您发布页面,它将不会返回到动态加载的局部视图。 尝试对/ Person / CreatePerson进行ajax调用。 您的CreatePerson看起来类似于
[HttpPost] public JsonResult CreatePerson(Person person) { ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory); try { if (!ModelState.IsValid) { string messages = string.Join("; ", ModelState.Values .SelectMany(x => x.Errors) .Select(x => x.ErrorMessage)); throw new Exception("Please correct the following errors: " + Environment.NewLine + messages); } db.Persons.AddObject(person); db.SaveChanges(); return Json(new { Result = "OK" }); } catch (Exception ex) { return Json(new { Result = "ERROR", Message = ex.Message }); } } `
对/ Person / CreatePerson的ajax调用看起来类似于
`
$.ajax({ url: '/Person/CreatePerson', type: "POST", data: $("#form").serialize(), success: function (responce) { alert(responce.Message); }, error: function (xhr, textStatus) { alert(xhr.status + " " + xhr.statusText); } });
除了不显眼的validation,动态内容也无法轻松完成。 在动态添加的局部视图上检查链接不显眼的validation(不工作)
我遇到了这种情况,我的主View使用Ajaxpost来检索PartialViews并将PartialView的标记传递到我的View中。 我使用jQueryvalidation框架来实现客户端不显眼的validation。 当我尝试validation通过Ajax调用加载到页面中的表单时,validation似乎没有起作用,我的表单只是发布了。 事实certificate,不显眼的jQueryvalidation器库在完成页面上所有validation规则的加载后解析页面的标记。 结果是,jQuery不知道动态添加的标记有任何validation规则,导致在post上没有抛出validation错误。
解
Traffy有一个可以在不显眼的jQuery库中公开访问的方法,你可以调用它,这会强制解析器扫描你刚刚加载的标记。 为此,您需要将以下代码添加到PartialView(或其他动态加载的内容)
//this code goes in your partial view $(function(){ //allow the validation framework to re-prase the DOM jQuery.validator.unobtrusive.parse(); //or to give the parser some context, supply it with a selector //jQuery validator will parse all child elements (deep) starting //from the selector element supplied jQuery.validator.unobtrusive.parse("#formId"); });
然后在您的父页面中,您可以处理表单提交并检查表单是否有效;
//then in your parent page handle the form submission $(function(){ $("#SubmitButton").click(function(){ if (!$("#Form1").valid()){ return false; } }); });
就是这样!! (信用:戴夫的编码)
我为此开发了一个不错的解决方法。 部分页面不会在回发时显示服务器错误。 首先,我们得到错误,将它们发送回页面,然后在javascript中创建它们并重新validation页面。 希望,嘿presto!
在你的控制器中:
if (ModelState.IsValid) { //... whatever code you need in here } var list = ModelStateHelper.AllErrors(ModelState); TempData["shepherdErrors"] = list;
我将它放在TempData中,因此可以从部分中轻松检索。 是的,我称之为shepherdErrors,这是我的想法所以我可以把这个概念称为我想要的愚蠢名字! 将错误代码应用到它们应该存在的位置或者是一般的想法。
在辅助类中:
public class ModelStateHelper { public static IEnumerable> AllErrors(ModelStateDictionary modelState) { var result = new List>(); var erroneousFields = modelState.Where(ms => ms.Value.Errors.Any()) .Select(x => new { x.Key, x.Value.Errors }); foreach (var erroneousField in erroneousFields) { var fieldKey = erroneousField.Key; var fieldErrors = erroneousField.Errors .Select(error => new KeyValuePair(fieldKey, error.ErrorMessage)); //Error(fieldKey, error.ErrorMessage)); result.AddRange(fieldErrors); } return result; } }
然后在jquery加载后的某个地方的html页面上:
function displayShepherdErrors() { var shepherdErrors = JSON.parse('@(Newtonsoft.Json.JsonConvert.SerializeObject(TempData["shepherdErrors"]))'.replace(/"/g, '"')); var frm; var isShepherdErrors = (shepherdErrors && shepherdErrors.length > 0); if (isShepherdErrors) { errObj = {}; for (var i = 0; i < shepherdErrors.length; i++) { var errorKey = shepherdErrors[i].Key; //also the id of the field var errorMsg = shepherdErrors[i].Value; var reg = new RegExp('^' + errorKey + '$', 'gi'); //find the selector - we use filter so we can find it case insensitive var control = $('input').filter(function () { if ($(this).attr('id')) return $(this).attr('id').match(reg); }); if (control && control.length) { control = control[0]; var controlId = $(control).attr('name'); errObj[controlId] = errorMsg; //get the containing form of the first input element if (!frm) frm = control.form; } } var validator = $(frm).validate(); validator.showErrors(errObj); } return isShepherdErrors; } var isShepherdErrors = displayShepherdErrors();
这应该是开箱即用的一般MVC开发提供的,生成的文本框是基于变量名称 - 这是MVC的默认行为。