[英]MVC 4 Validation with a partial view
我正在使用MVC 4和Entity Framework来开发一个Web应用程序。 我正在使用加载了javascript的部分视图。 其中之一是包含验证的创建视图。 这就是我的问题:验证。 我有一个自定义验证逻辑,例如,如果用户在某个字段(如“名称”)中输入某些数字,则会显示错误。
在这里,使用部分视图,它将我的部分视图重定向到显示的错误,但我想要做的是保持在我的主视图(索引视图)并保留显示错误的部分视图。
编辑:
这是我的部分观点:
@model BuSIMaterial.Models.Person
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
<div class="editor-label">
First name :
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.FirstName, new { maxlength = 50 })
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
Last name :
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.LastName, new { maxlength = 50 })
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
National number :
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.NumNat, new { maxlength = 11 })
@Html.ValidationMessageFor(model => model.NumNat)
</div>
<div class="editor-label">
Start date :
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.StartDate, new {@class = "datepicker", @placeholder="yyyy/mm/dd"})
@Html.ValidationMessageFor(model => model.StartDate)
</div>
<div class="editor-label">
End date :
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.EndDate, new { @class = "datepicker", @placeholder = "yyyy/mm/dd" })
@Html.ValidationMessageFor(model => model.EndDate)
</div>
<div class="editor-label">
Distance House - Work (km) :
</div>
<div class="editor-field">
@Html.EditorFor(model => model.HouseToWorkKilometers)
@Html.ValidationMessageFor(model => model.HouseToWorkKilometers)
</div>
<div class="editor-label">
Category :
</div>
<div class="editor-field">
@Html.DropDownList("Id_ProductPackageCategory", "Choose one ...")
@Html.ValidationMessageFor(model => model.Id_ProductPackageCategory) <a href = "../ProductPackageCategory/Create">Add a new category?</a>
</div>
<div class="editor-label">
Upgrade? :
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Upgrade)
@Html.ValidationMessageFor(model => model.Upgrade)
</div>
<br />
<div class="form-actions">
<button type="submit" class="btn btn-primary">Create</button>
</div>
</fieldset>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/jqueryui")
@Styles.Render("~/Content/themes/base/css")
}
在我看来,索引,我有这个:
<div class="form-actions"><button type="button" id="create" class="btn btn-primary">Create</button> </div>
<div id ="create_person"></div>
以及我加载部分视图的方式:
$("#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);
}
});
除了不显眼的验证,动态内容也无法轻松完成。 在动态添加的局部视图上检查链接不显眼的验证(不工作)
我遇到了这种情况,我的主View使用Ajax帖子来检索PartialViews并将PartialView的标记传递到我的View中。 我使用jQuery验证框架来实现客户端不显眼的验证。 当我尝试验证通过Ajax调用加载到页面中的表单时,验证似乎没有起作用,我的表单只是发布了。 事实证明,不显眼的jQuery验证器库在完成页面上所有验证规则的加载后解析页面的标记。 结果是,jQuery不知道动态添加的标记有任何验证规则,导致在帖子上没有抛出验证错误。
解
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中创建它们并重新验证页面。 希望,嘿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<KeyValuePair<string, string>>
AllErrors(ModelStateDictionary modelState)
{
var result = new List<KeyValuePair<string, string>>();
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<string, string>(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的默认行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.