Jquery 自定义服务器端模型验证标记帮助程序不通过ViewComponent中的unobtrusiveJS显示
我为位于ViewComponent内部的一组复选框创建了一个自定义验证属性。在我将其移动到ViewComponent之前,不引人注目的验证消息在asp验证中非常有效,但是现在消息没有出现在那里 同时,我正在收集服务器端验证错误并将其传递回视图,这正如预期的那样工作:因此,我通过自定义属性获取错误消息,它只是没有在视图中显示该消息 这是代码(我正在尽可能简化它,如果您需要更多信息,请告诉我。如果我遗漏了一些内容,我很抱歉。): 控制器:Jquery 自定义服务器端模型验证标记帮助程序不通过ViewComponent中的unobtrusiveJS显示,jquery,asp.net-mvc,asp.net-core,asp.net-core-tag-helpers,asp.net-core-viewcomponent,Jquery,Asp.net Mvc,Asp.net Core,Asp.net Core Tag Helpers,Asp.net Core Viewcomponent,我为位于ViewComponent内部的一组复选框创建了一个自定义验证属性。在我将其移动到ViewComponent之前,不引人注目的验证消息在asp验证中非常有效,但是现在消息没有出现在那里 同时,我正在收集服务器端验证错误并将其传递回视图,这正如预期的那样工作:因此,我通过自定义属性获取错误消息,它只是没有在视图中显示该消息 这是代码(我正在尽可能简化它,如果您需要更多信息,请告诉我。如果我遗漏了一些内容,我很抱歉。): 控制器: public IActionResult Enrollmen
public IActionResult Enrollment(EnrollmentViewModel enrollmentVM)
{
return View("~/Enrollment.cshtml", enrollmentVM);
}
public EnrollmentViewModel SetModelListItems(EnrollmentViewModel enrollmentVM)
{
if (enrollmentVM.Preferences == null)
{
var preferencesList = preferences.GetAll().ToList();
enrollmentVM.Preferences = preferences.Select(x => new SelectListItem
{
Text = x.PreferencesName,
Value = x.PreferenceseId.ToString()
}).ToList();
return enrollmentVM;
}
public class EnrollmentController : Controller
{
public IActionResult Enrollment(EnrollmentViewModel enrollmentVM)
{
return View("Enrollment", enrollmentVM);
}
[HttpPost]
public IActionResult Enroll(EnrollmentViewModel enrollmentVM)
{
if (!ModelState.IsValid)
{
return View("Enrollment", enrollmentVM);
}
else
{
//SaveForm
return View("Enrollment", enrollmentVM);
}
}
}
带属性的视图模型:
public class EnrollmentViewModel
{
[ListItemSelected(ErrorMessage = "Please select at least one Preference option.")]
public List<SelectListItem> Preferences { get; set; }
}
public class ListItemSelectedAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
if ((value as List<SelectListItem>).Count(x => x.Selected) == 0)
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
公共类注册视图模型
{
[ListItemSelected(ErrorMessage=“请至少选择一个首选项选项。”)]
公共列表首选项{get;set;}
}
公共类ListItemSelectedAttribute:ValidationAttribute
{
受保护的重写ValidationResult有效(对象值,ValidationContext ValidationContext)
{
if(值!=null)
{
if((值作为列表).Count(x=>x.Selected)==0)
返回新的ValidationResult(ErrorMessage);
}
返回ValidationResult.Success;
}
}
我觉得这是很多代码,但希望大部分代码都能解释我的问题。。。我把它削减了很多。jquery、验证和不引人注目的脚本位于_Layout.cshtml中。非常感谢你
编辑:
我在ViewComponent和主视图文件中放置了一个断点,在这两个文件中,在Locals选项卡中,ViewContext显示ModelState无效,ValidationMessageElement=“span”!我想那不是它应该是的??我发现一篇帖子建议添加ViewContext.FormContext=new FormContext();在顶部,但有或没有FormContext项是相同的。我测试了您的代码,但提交按钮没有启动。另外,在Html.begin中设置时,我没有看到
Enroll
操作
@using (Html.BeginForm("Enroll", "Enrollment", FormMethod.Post, new { enctype = "multipart/form-data", id = "EnrollForm" }))
我根据您的代码制作了一个示例,它似乎如您所期望的那样工作
主视图(Enrollment.cshtml)
项目结构:
结果:
当然,您是否尝试过在ViewComponent的视图文件中放置断点以检查其
模型状态
?其中应该有验证错误,否则标记帮助程序无法对进行asp验证。顺便说一句,我有点怀疑这个asp for=“@Model.Preferences[I].Selected”
是否会呈现Selected
的相应名称。您是否可以检查您的网页(使用浏览器的inspector工具)以查看为您的输入生成的实际名称?的asp验证看起来很正确。@KingKing我不知道该怎么做(谢谢)。我这样做了,ModelState无效,ValidationMessageElement=“span”!我想那不是它应该是的??我在谷歌搜索了一下,发现一篇帖子建议添加ViewContext.FormContext=newformcontext()
位于顶部,但有或没有它,FormContext项在Locals选项卡中都是相同的。您可以检查ModelState
深入到每个ModelStateEntry
的错误列表,这里的ModelState是一个IReadOnlyDictionary
。您好!我修正了问题中的错误。我认为最主要的区别在于,因为我在虚拟机中使用了一个自定义属性,所以它只是服务器端验证,而且验证消息不会返回,尽管ModelState是。(我用更多信息更新了我的问题)。非常感谢你!
public IActionResult EnrollClient(EnrollmentViewModel viewModel)
{
try
{
if (!ModelState.IsValid)
{
viewModel = SetModelListItems(viewModel);
viewModel.HasErrors = true;
viewModel.SubmitErrors = ModelState.Values
.SelectMany(state => state.Errors)
.Select(error => error.ErrorMessage);
return View("~/Enrollment.cshtml", viewModel);
}
SaveForm();
}
//....
}
public class EnrollmentViewModel
{
[ListItemSelected(ErrorMessage = "Please select at least one Preference option.")]
public List<SelectListItem> Preferences { get; set; }
}
public class ListItemSelectedAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
if ((value as List<SelectListItem>).Count(x => x.Selected) == 0)
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
@using (Html.BeginForm("Enroll", "Enrollment", FormMethod.Post, new { enctype = "multipart/form-data", id = "EnrollForm" }))
@model EnrollmentViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Enrollment</h1>
<div>
@await Component.InvokeAsync("EnrollClient", new { enrollmentVM = @Model })
</div>
@model EnrollmentViewModel
@{
var x = Model;
}
@using (Html.BeginForm("Enroll", "Enrollment", FormMethod.Post, new { enctype = "multipart/form-data", id = "EnrollForm" }))
{
<fieldset>
<legend>Preferences (select all that apply)</legend>
@for (var i = 0; i < Model.Preferences.Count(); i++)
{
<div>
<input type="checkbox" asp-for="@Model.Preferences[i].Selected">
<label>@Model.Preferences[i].Text</label>
<input type="hidden" asp-for="@Model.Preferences[i].Value" />
<input type="hidden" asp-for="@Model.Preferences[i].Text" />
</div>
}
<button type="submit" id="EnrollForm" form="EnrollForm">
<span>Save</span>
</button>
<span asp-validation-for="Preferences" class="text-danger"></span>
</fieldset>
}
public class EnrollClientViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(EnrollmentViewModel enrollmentVM)
{
enrollmentVM = SetModelListItems(enrollmentVM);
return new ViewViewComponentResult()
{
ViewData = new ViewDataDictionary<EnrollmentViewModel>(ViewData, enrollmentVM)
};
}
public EnrollmentViewModel SetModelListItems(EnrollmentViewModel enrollmentVM)
{
enrollmentVM.Preferences = new List<SelectListItem>
{
new SelectListItem{ Text = "A", Value = "1"},
new SelectListItem{ Text = "B", Value = "2"},
new SelectListItem{ Text = "C", Value = "3"},
};
return enrollmentVM;
}
}
public class EnrollmentController : Controller
{
public IActionResult Enrollment(EnrollmentViewModel enrollmentVM)
{
return View("Enrollment", enrollmentVM);
}
[HttpPost]
public IActionResult Enroll(EnrollmentViewModel enrollmentVM)
{
if (!ModelState.IsValid)
{
return View("Enrollment", enrollmentVM);
}
else
{
//SaveForm
return View("Enrollment", enrollmentVM);
}
}
}