【问题标题】:FileExtensions attribute of DataAnnotations not working in MVCDataAnnotations 的 FileExtensions 属性在 MVC 中不起作用
【发布时间】:2015-09-30 16:57:27
【问题描述】:

我正在尝试使用 MVC 中的 HTML FileUpload 控件上传文件。我想验证文件以仅接受特定的扩展名。我尝试使用 DataAnnotations 命名空间的 FileExtensions 属性,但它不起作用。请参阅下面的代码 -

public class FileUploadModel
    {
        [Required, FileExtensions(Extensions = (".xlsx,.xls"), ErrorMessage = "Please select an Excel file.")]
        public HttpPostedFileBase File { get; set; }
    }

在控制器中,我正在编写如下代码-

[HttpPost]
        public ActionResult Index(FileUploadModel fileUploadModel)
        {
            if (ModelState.IsValid)
                fileUploadModel.File.SaveAs(Path.Combine(Server.MapPath("~/UploadedFiles"), Path.GetFileName(fileUploadModel.File.FileName)));

            return View();
        }

在视图中,我写了下面的代码-

@using (Html.BeginForm("Index", "FileParse", FormMethod.Post, new { enctype = "multipart/form-data"} ))
{
    @Html.Label("Upload Student Excel:")
    <input type="file" name="file" id="file"/>
    <input type="submit" value="Import"/>
    @Html.ValidationMessageFor(m => m.File)
}

当我运行应用程序并提供无效的文件扩展名时,它没有向我显示错误消息。 我知道编写自定义验证属性的解决方案,但我不想使用自定义属性。请指出我哪里出错了。

【问题讨论】:

  • @serhiyb 感谢您的回复。我已经完成了那个解决方案。但我不想使用自定义属性,我想使用.NET 已经提供的属性。我做错了什么还是微软提供的属性有问题?
  • 由于 FileExtensions 属性在 MVC5 中工作正常(刚刚测试)我认为在较低版本中存在问题。
  • 嗨,也许这可以帮助你...stackoverflow.com/questions/8536589/…

标签: c# .net asp.net-mvc file-upload data-annotations


【解决方案1】:

我遇到了同样的问题,我解决了创建一个新的 ValidationAttribute。

像这样:

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class FileExtensionsAttribute : ValidationAttribute
    {
        private List<string> AllowedExtensions { get; set; }

        public FileExtensionsAttribute(string fileExtensions)
        {
            AllowedExtensions = fileExtensions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
        }

        public override bool IsValid(object value)
        {
            HttpPostedFileBase file = value as HttpPostedFileBase;

            if (file != null)
            {
                var fileName = file.FileName;

                return AllowedExtensions.Any(y => fileName.EndsWith(y));
            }

            return true;
        }
    }

现在,就用这个吧:

[FileExtensions("jpg,jpeg,png,gif", ErrorMessage = "Your error message.")]
public HttpPostedFileBase Imagem { get; set; }

我有帮助。 拥抱!

【讨论】:

    【解决方案2】:

    就像 marai 回答的那样,FileExtension 属性仅适用于字符串属性。

    在我的代码中,我使用如下属性:

    public class MyViewModel
    {
        [Required]
        public HttpPostedFileWrapper PostedFile { get; set; }
    
        [FileExtensions(Extensions = "zip,pdf")]
        public string FileName
        {
            get
            {
                if (PostedFile != null)
                    return PostedFile.FileName;
                else
                    return "";
             }
        }
    }
    

    然后,在服务器端,如果发布的文件没有您在属性中指定的扩展名(在我的示例中为 .zip 和 .pdf),则 ModelState.IsValid 将为 false。

    注意:如果您使用 HTML.ValidationMessageFor 帮助器在 PostBack 后呈现错误消息(文件扩展名属性在客户端无效,仅在服务器端验证),您需要为 FileName 属性指定另一个帮助器为了显示扩展错误信息:

    @Html.ValidationMessageFor(m => m.PostedFile)
    @Html.ValidationMessageFor(m => m.FileName)
    

    【讨论】:

    • 谢谢,如果选择了文件,这将非常有用。但是,如果没有选择文件,则只会触发必需的验证。在这种情况下,两个验证都可以。这个问题有补救措施吗?
    • 我成功了!当 PostedFile 为 null 时,它应该返回 null 而不是返回 ""。
    【解决方案3】:

    FileExtensions 属性不知道如何验证 HttpPostedFileBase。请在下面尝试

    [FileExtensions(Extensions = "xlsx|xls", ErrorMessage = "Please select an Excel file.")]
    public string Attachment{ get; set; }
    

    在您的控制器中:

    [HttpPost]
        public ActionResult Index(HttpPostedFileBase Attachment)
        {
            if (ModelState.IsValid)
            {
                if (Attachment.ContentLength > 0)
                {
                    string filePath = Path.Combine(HttpContext.Server.MapPath("/Content/Upload"), Path.GetFileName(Attachment.FileName));
                    Attachment.SaveAs(filePath);
                }
            }
            return RedirectToAction("Index_Ack"});
        }
    

    【讨论】:

    • 为什么不用逗号分隔扩展名?
    【解决方案4】:

    我在FileExtensions attribute of DataAnnotations not working in MVC 中使用了上面的代码,我只是做了一些更改:1) 避免命名空间冲突和 2) 使用 IFormFile 而不是原来的 HttpPostedFileBase。好吧,也许对某人有用。

    我的代码:

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class FileVerifyExtensionsAttribute : ValidationAttribute
    {
        private List<string> AllowedExtensions { get; set; }
    
        public FileVerifyExtensionsAttribute(string fileExtensions)
        {
            AllowedExtensions = fileExtensions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
        }
    
        public override bool IsValid(object value)
        {
            IFormFile file = value as IFormFile;
    
            if (file != null)
            {
                var fileName = file.FileName;
    
                return AllowedExtensions.Any(y => fileName.EndsWith(y));
            }
    
            return true;
        }
    }
    

    【讨论】:

    • 一个不错的解决方案@DanielSilva。工作得很好。但缺点是,它只能在服务器端工作。是否有任何解决方法,以便它也可以在 客户端 中工作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多