验证多个属性

时间:2011-10-11 18:19:25

标签: c# asp.net-mvc-2

我正在为本地艺术家建立一个在线商店,其中一个要求是添加一个与给定产品相关联的图像。对于图像,有多个元素需要验证;特别是尺寸,文件大小和类型。

目前,我有以下设置来验证图像:

[LocalizedDisplayName(typeof(StoreManagementRes), "Image")]
[ImageSize(typeof(BesLogicSharedRes),"ValidationImageFileSizeMustBeLessThan20kb")]
[ImageDimension(typeof(BesLogicSharedRes), "ValidationImageDimensionMustBeLessThan640x480")]
[ImageType(typeof(BesLogicSharedRes), "ValidationImageTypeMustBeJpgOrPng")]
public int ImageFileId { get; set; }

上传的文件确实得到了正确验证,但是,每次运行应用程序时,它们不一定以相同的顺序调用。最后,如果验证在多个属性上失败,则只显示一条错误消息。同样,不一定是第一次失败的验证,也不一定是最后一次。我想一次显示所有错误,以免挫败用户。

如果这是相关的,则所有三个图像验证类都归入ValidationAttribute

1 个答案:

答案 0 :(得分:1)

值得庆幸的是,模型会保留所有错误而不是其中一个错误,只是显示第一个错误的HtmlHelper。

ValidationSummary实际上应该显示模型上的所有错误,但我怀疑你想要一个单独属性的等价物。

不幸的是,一些有用的方法是私有的而不是受保护的,所以它们必须从ValidationExtensions.cs复制并粘贴。我用一个略微减少的版本做了这个(没有使用资源文件的错误消息,通过获取原始版本的GetUserErrorMessageOrDefault很容易,但你也必须检查从类中获取相关的方法和字段) 。我也只做过一次函数调用,但如果需要,它很容易实现重载。

public static MvcHtmlString ValidationSummaryForSubModel(this HtmlHelper html, bool excludePropertyErrors, string message, IDictionary<string, object> htmlAttributes)
    {
        string prefix = html.ViewData.TemplateInfo.HtmlFieldPrefix;
        var props = html.ViewData.ModelState.Where(x => x.Key.StartsWith(prefix));
        var errorprops = props.Where(x => x.Value.Errors.Any()).SelectMany(x=>x.Value.Errors);

        if (html == null) {
            throw new ArgumentNullException("html");
        }
        FormContext formContext = (html.ViewContext.ClientValidationEnabled) ? html.ViewContext.FormContext : null;
        if (formContext == null && html.ValidForSubModel())
        {
            return null;
        }

        string messageSpan;
        if (!String.IsNullOrEmpty(message)) {
            TagBuilder spanTag = new TagBuilder("span");
            spanTag.SetInnerText(message);
            messageSpan = spanTag.ToString(TagRenderMode.Normal) + Environment.NewLine;
        }
        else {
            messageSpan = null;
        }

        StringBuilder htmlSummary = new StringBuilder();
        TagBuilder unorderedList = new TagBuilder("ul");


        foreach (ModelError modelError in errorprops) {
            string errorText = GetUserErrorMessageOrDefault(html.ViewContext.HttpContext, modelError, null /* modelState */);
            if (!String.IsNullOrEmpty(errorText)) {
                TagBuilder listItem = new TagBuilder("li");
                listItem.SetInnerText(errorText);
                htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal));
            }
        }


        if (htmlSummary.Length == 0) {
            htmlSummary.AppendLine(_hiddenListItem);
        }

        unorderedList.InnerHtml = htmlSummary.ToString();

        TagBuilder divBuilder = new TagBuilder("div");
        divBuilder.MergeAttributes(htmlAttributes);
        divBuilder.AddCssClass((html.ViewData.ModelState.IsValid) ? HtmlHelper.ValidationSummaryValidCssClassName : HtmlHelper.ValidationSummaryCssClassName);
        divBuilder.InnerHtml = messageSpan + unorderedList.ToString(TagRenderMode.Normal);

        if (formContext != null) {
            // client val summaries need an ID
            divBuilder.GenerateId("validationSummary");
            formContext.ValidationSummaryId = divBuilder.Attributes["id"];
            formContext.ReplaceValidationSummary = !excludePropertyErrors;
        }
        return MvcHtmlString.Create(divBuilder.ToString(TagRenderMode.Normal));
    }

    private static string GetUserErrorMessageOrDefault(HttpContextBase httpContext, ModelError error, ModelState modelState)
    {
        if (!String.IsNullOrEmpty(error.ErrorMessage))
        {
            return error.ErrorMessage;
        }
        if (modelState == null)
        {
            return null;
        }

        string attemptedValue = (modelState.Value != null) ? modelState.Value.AttemptedValue : null;
        //return String.Format(CultureInfo.CurrentCulture, GetInvalidPropertyValueResource(httpContext), attemptedValue);
        return "Error";
    }