我正在使用[在我的表单上显示错误
<%= Html.ValidationSummary("Please review the errors below") %>
我的域对象继承自基类,并且我发现基类数据注释属性显示在列表的底部。这违反了它们在我的表单中出现的顺序。
是否可以指定显示错误的顺序?
示例:
public class ClassA { [Required]public string AProperty; }
public class ClassB : ClassA { [Required]public string BProperty; }
我的表单(ClassB的强类型视图):
AProperty: <%= Html.TextBoxFor(m => m.AProperty) %>
BProperty: <%= Html.TextBoxFor(m => m.BProperty) %>
验证错误显示为:
The BProperty is required.
The AProperty is required.
不。反射用于获取所有DataAnnotation,并且它们始终以调用typeof(MagicSocks).GetTYpe().GetProperties()
时属性出现的顺序出现。对于您的情况,我很确定派生类属性将始终出现在基本类型属性之前。
您必须编写自己的帮助程序和我们自己的属性,才能按照您选择的顺序显示验证错误。
我为此写了扩展名:
public static void OrderByKeys(this ModelStateDictionary modelStateDictionary, IEnumerable<string> keys)
{
ModelStateDictionary result = new ModelStateDictionary();
foreach (string key in keys)
{
if (modelStateDictionary.ContainsKey(key) && !result.ContainsKey(key))
{
result.Add(key, modelStateDictionary[key]);
}
}
foreach (string key in modelStateDictionary.Keys)
{
if (!result.ContainsKey(key))
{
result.Add(key, modelStateDictionary[key]);
}
}
modelStateDictionary.Clear();
modelStateDictionary.Merge(result);
}
您可以通过以下方式使用:
ModelState.OrderByKeys(new[] { "AProperty", "BProperty" });
我不确定我的回答是对还是错,可以尝试这种方式。
public ActionResult yourAction(your params)
{
if (!ModelState.IsValid)
{
var errs = from er in tmpErrs
orderby er.Key
select er;
ModelState.Clear();
foreach (var err in errs)
{
ModelState.Add(err);
}
}
// your code
}
尝试使用此过滤器属性,该属性根据请求的表单键对模型状态进行排序。
using System.Linq;
using System.Web.Mvc;
namespace
{
public class OrderedModelStateAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
var modelState = filterContext.Controller.ViewData.ModelState;
var orderedModelState = new ModelStateDictionary();
foreach (var key in filterContext.HttpContext.Request.Form.Keys.Cast<string>()
.Where(
key =>
modelState.ContainsKey(key) && !orderedModelState.ContainsKey(key)))
{
orderedModelState.Add(key, modelState[key]);
}
foreach (var key in modelState.Keys.Where(key => !orderedModelState.ContainsKey(key)))
{
orderedModelState.Add(key, modelState[key]);
}
modelState.Clear();
modelState.Merge(orderedModelState);
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
}
使用以下代码将过滤器添加到所有操作:filters.Add(new OrderedModelStateAttribute());
我也遇到了同样的问题,创建新的视图模型是不可行的-同样,如果您具有自定义模型绑定程序,无论如何它们都将出现在验证摘要的末尾。我在Aphize答案上进行了扩展,而不是将属性名称列表传递给它,而可以通过表单键传递给它-这将确保顺序与表单中显示的顺序相同,例如
ModelState.OrderByKeys(Request.Form.AllKeys);
这对我有用,我创建了一个属性来执行此操作。(我不得不做一些调整来处理自定义活页夹,但这里没有,):
public class ForceValidationErrorOrderAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var allFormKeys = filterContext.HttpContext.Request.Form.AllKeys;
var modelStateDictionary = filterContext.Controller.ViewData.ModelState;
ModelStateDictionary result = new ModelStateDictionary();
foreach (string key in allFormKeys)
{
if (modelStateDictionary.ContainsKey(processedKey) && !result.ContainsKey(processedKey))
{
result.Add(key, modelStateDictionary[key]);
}
}
foreach (string key in modelStateDictionary.Keys)
{
if (!result.ContainsKey(key))
{
result.Add(key, modelStateDictionary[key]);
}
}
modelStateDictionary.Clear();
modelStateDictionary.Merge(result);
}
}
然后在控制器上执行动作方法:
[ForceValidationErrorOrder]
public ActionResult Apply(ApplicationViewModel viewModel)