如何在 Html.ValidationSummary 中指定数据注释错误的顺序

发布于 2024-09-27 05:51:26 字数 640 浏览 7 评论 0原文

我使用“

<%= 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.

I'm displaying errors on my form with the use of

<%= Html.ValidationSummary("Please review the errors below") %>

My domain object inherits from a base class and I am finding that the base class data annotation properties are being displayed at the bottom of the list. This goes against the order in which they appear in my form.

Is there any way of specifying what order the errors should be displayed?

Example:

public class ClassA { [Required]public string AProperty; }
public class ClassB : ClassA { [Required]public string BProperty; }

My form (strongly typed view of ClassB):

AProperty: <%= Html.TextBoxFor(m => m.AProperty) %>
BProperty: <%= Html.TextBoxFor(m => m.BProperty) %>

Validation errors appear as:

The BProperty is required.
The AProperty is required.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

清晰传感 2024-10-04 05:51:26

我为此编写了一个扩展:

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" });

I've written an extension for this:

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);
}

Which you can use by:

ModelState.OrderByKeys(new[] { "AProperty", "BProperty" });
伴我心暖 2024-10-04 05:51:26

没有。反射用于获取所有 DataAnnotations,并且它们始终按照调用 typeof(MagicSocks).GetTYpe().GetProperties() 时属性出现的顺序出现。在您的情况下,我非常确定派生类属性将始终出现在基类型属性之前。

您必须编写自己的帮助程序和我们自己的属性,才能按照您选择的顺序显示验证错误。

Nope. Reflection is used to get all the DataAnnotations and they always appear in the order the properties would appear with a call to typeof(MagicSocks).GetTYpe().GetProperties(). In your case I'm pretty sure derived class properties will always appear before base type properties.

You have to write your own helper and our own attributes to display the validation errors in the order you choose.

爱已欠费 2024-10-04 05:51:26

我不确定我的答案是对还是错,你可以试试这个方法。

   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 

    }

i am not sure my answer is right or wrong, you can try this way.

   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 

    }
爱她像谁 2024-10-04 05:51:26

尝试这个过滤器属性,它根据请求的表单键对模型状态进行排序。

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());

Try this filter attribute which orders the model state according to the request's form keys.

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)
        {
        }
    }
}

Use the following code to add the filter to all Actions:
filters.Add(new OrderedModelStateAttribute());

你在看孤独的风景 2024-10-04 05:51:26

我遇到了同样的问题,并且创建新的视图模型是不可行的 - 另外,如果您有自定义模型绑定器,则无论如何这些都会出现在验证摘要的末尾。我扩展了 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)

I had this same problem and it wasn't feasible to create a new view model - also if you have custom model binders, these will appear at the end of the validation summary regardless. I expanded on Aphize answer, rather than pass it a list of property names you can pass it the form keys - this will ensure the order is the same as they appear in the form e.g.

ModelState.OrderByKeys(Request.Form.AllKeys);

This worked for me and I created an attribute to do this.. ( I had to do some tweaking to deal with the custom binders but here it is without that):

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);
        }
    }

And then on the controller action method:

    [ForceValidationErrorOrder]
    public ActionResult Apply(ApplicationViewModel viewModel)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文