我使用
在表单上显示错误<%= 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.
答案 0 :(得分:1)
我为此写了一个扩展名:
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" });
答案 1 :(得分:0)
我不确定我的答案是对还是错,你可以这样试试。
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
}
答案 2 :(得分:0)
尝试使用此过滤器属性,该属性根据请求的表单键对模型状态进行排序。
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());
答案 3 :(得分:0)
我遇到了同样的问题,创建一个新的视图模型是不可行的-同样,如果您有自定义模型绑定程序,无论如何它们都将出现在验证摘要的末尾。我在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(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);
}
}
然后在控制器上执行操作方法:
[ForceValidationErrorOrder]
public ActionResult Apply(ApplicationViewModel viewModel)
答案 4 :(得分:-1)
不。反射用于获取所有DataAnnotations,它们始终按照调用typeof(MagicSocks).GetTYpe().GetProperties()
时属性显示的顺序显示。在您的情况下,我非常确定派生类属性将始终出现在基类型属性之前。
您必须编写自己的帮助程序和我们自己的属性,以按您选择的顺序显示验证错误。