【问题标题】:ModelState.IsValid is always false for RegularExpression ValidationAttribute in MVC 4对于 MVC 4 中的 RegularExpression ValidationAttribute,ModelState.IsValid 始终为 false
【发布时间】:2013-03-12 19:05:07
【问题描述】:

在我的课堂上,我有一个文件附件的属性,像这样......

public class Certificate {
    [Required]
    // TODO:  Wow looks like there's a problem with using regex in MVC 4, this does not work!
    [RegularExpression(@"^.*\.(xlsx|xls|XLSX|XLS)$", ErrorMessage = "Only Excel files (*.xls, *.xlsx) files are accepted")]
    public string AttachmentTrace { get; set; }
}

我看不出我的正则表达式有什么问题,但我总是得到 ModelState.IsValid 错误。这似乎非常简单和简单的正则表达式,我错过了什么吗?我需要编写自己的自定义验证吗?

我正在通过文件类型的常规输入填充 AttachmentTrace:

<div class="editor-label">
    @Html.LabelFor(model => model.AttachmentTrace)
</div>
<div class="editor-field">
    @Html.TextBoxFor(model => model.AttachmentTrace, new { type = "file" })
    @Html.ValidationMessageFor(model => model.AttachmentTrace)
</div>

action 方法只是一个常规动作:

public ActionResult Create(Certificate certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail)
    {
        if (ModelState.IsValid)
        {
            // code ...
        }
        return View(certificate);
    }

【问题讨论】:

  • 如何填充 AttachmentTrace?
  • 四十二,我通过文件类型的常规输入来填充它(只是在上面添加了一些代码)。谢谢。
  • 好吧,你这样做的方式我猜 AttachmentTrace 的值不是你所期望的(文件名),而是类似于“System.Web.HttpPostedFileWrapper”的东西。
  • 你的 Action 方法是什么样的?
  • 您可以将该扩展位简化为[xX][lL][sS][xX]?,或者更好的是,使用内联不区分大小写的修饰符:(?i)^.*\.xlsx?$

标签: regex asp.net-mvc-4 automapper model-validation custom-validators


【解决方案1】:

好的,这是我找到的解决方案。我敢肯定还有其他解决方案。首先介绍一下背景,因为我的应用程序使用 EF 代码优先迁移,在我的模型中指定 HttpPostedFileBase 属性类型,在添加迁移时会产生此错误:

在模型生成过程中检测到一个或多个验证错误: System.Data.Entity.Edm.EdmEntityType: : EntityType 'HttpPostedFileBase' 没有定义键。为此定义密钥 实体类型。 \tSystem.Data.Entity.Edm.EdmEntitySet:实体类型: EntitySet 'HttpPostedFileBases' 基于类型 'HttpPostedFileBase' 没有定义键。

所以我真的必须坚持对 AttachmentTrace 属性使用字符串类型。

解决方案是使用这样的 ViewModel 类:

public class CertificateViewModel {
    // .. other properties
    [Required]
    [FileTypes("xls,xlsx")]
    public HttpPostedFileBase AttachmentTrace { get; set; }
}

然后像这样创建一个 FileTypesAttribute,我从this excellent post 借用了这段代码。

public class FileTypesAttribute : ValidationAttribute {
    private readonly List<string> _types;

    public FileTypesAttribute(string types) {
        _types = types.Split(',').ToList();
    }

    public override bool IsValid(object value) {
        if (value == null) return true;
        var postedFile = value as HttpPostedFileBase;
        var fileExt = System.IO.Path.GetExtension(postedFile.FileName).Substring(1);
        return _types.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    public override string FormatErrorMessage(string name) {
        return string.Format("Invalid file type. Only {0} are supported.", String.Join(", ", _types));
    }
}

在控制器 Action 中,我需要进行更改以改用 ViewModel,然后使用 AutoMapper 将其映射回我的实体(顺便说一句,这非常好):

public ActionResult Create(CertificateViewModel certificate, HttpPostedFileBase attachmentTrace, HttpPostedFileBase attachmentEmail) {
        if (ModelState.IsValid) {
            // Let's use AutoMapper to map the ViewModel back to our Certificate Entity
            // We also need to create a converter for type HttpPostedFileBase -> string
            Mapper.CreateMap<HttpPostedFileBase, string>().ConvertUsing(new HttpPostedFileBaseTypeConverter());
            Mapper.CreateMap<CreateCertificateViewModel, Certificate>();
            Certificate myCert = Mapper.Map<CreateCertificateViewModel, Certificate>(certificate);
            // other code ...
        }
        return View(myCert);
    }

对于 AutoMapper,我为 HttpPostedFileBase 创建了自己的 TypeConverter,如下所示:

public class HttpPostedFileBaseTypeConverter : ITypeConverter<HttpPostedFileBase, string> {

    public string Convert(ResolutionContext context) {
        var fileBase = context.SourceValue as HttpPostedFileBase;
        if (fileBase != null) {
            return fileBase.FileName;
        }
        return null;
    }
}

就是这样。希望这对可能遇到同样问题的其他人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    相关资源
    最近更新 更多