2011-12-16 4 views
8

Согласно документации MSDN, по умолчанию FileExtensionsAttribute (.NET 4.5) должен позволить мне загружать только файлы jpg, jpeg, gif и png - вот что я хочу ,ASP.NET MVC 3: DataAnnotations.FileExtensionsAttribute не работает

Я попытался загрузить jpg без атрибута, он работает. Отлично. Затем я добавил атрибут мой взгляд модель ..

[FileExtensions(ErrorMessage = "Please specify a valid image file (.jpg, .jpeg, .gif or .png)")] 
public HttpPostedFileBase ImageFile { get; set; } 

Нет радости. Проверка завершается ошибкой, и отображается сообщение ErrorMessage. Кроме того, не существует способа указать разрешенные пользовательские расширения файлов. Я закончил тем, что расширил атрибут FileExtensionsAttribute и использовал свою собственную логику проверки, которая работает так, как ожидалось. Но почему так не работает?

Выведет весь контроллер и, если необходимо, просмотрит его. Я использовал этот пример в качестве основы для логики, добавления видео, но с использованием DataAnnotations.FileExtensionsAttribute вместо Microsoft.Web.Mvc.FileExtensions .. How do I upload images in ASP.NET MVC?

ответ

5

Используйте Extensions свойства, чтобы установить их. Хотя в соответствии с документацией

Расширения имен файлов или расширений файлов по умолчанию («.png», «.jpg», «.jpeg», и «.gif»), если свойство не установлено ,

Вы можете установить его так же, как вы сделали ErrorMessage. Более вероятная проблема заключается в том, что она не знает, как оценить, имеет ли HttpPostedFileBase правильное расширение. Вам нужно будет использовать один из структуры MVC или создать свой собственный.

+0

Спасибо. Вы были правы в FileExtensionsAttribute, не зная, как получить доступ к имени файла. Кажется, ожидает, что строка будет проверяться. –

+0

Кроме того, как примечание, я понял, что сообщение об ошибке является свойством, тогда как строка фильтра расширений файлов может быть установлена ​​только как необязательный аргумент конструктора (это свойство только для чтения). Синтаксис немного отличается для каждого. –

0

FileExtensionsAttribute не знает, как проверить HttpPostedFileBase, поэтому я продлил его ..

/// <summary> 
/// A File extensions attribute for verifying the file extensions of posted files from MVC forms. 
/// </summary> 
public class PostedFileBaseFileExtensionsAttribute : FileExtensionsAttribute 
{ 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var file = value as HttpPostedFileBase; 
     if (file == null) 
     { 
      return new ValidationResult("No File Specified"); 
     } 

     return base.IsValid(file.FileName, validationContext); 
    } 
} 

Обратите внимание, что этот метод заставляет файл быть обязательным полем. В качестве альтернативы, если это поле необязательное, используйте следующий код для тела метода. Это всегда возвращает успех, если файл не указан (возможно, более правильно в большинстве случаев) ..

 var file = value as HttpPostedFileBase; 
     return file == null ? ValidationResult.Success : base.IsValid(file.FileName, validationContext); 
+9

Не является ли FileExtensionsAttribute закрытым? – Ben

+1

Класс FileExtensionsAttribute запечатан. Таким образом, это не может быть унаследовано – Unnie

24

С System.ComponentModel.DataAnnotations.FileExtensionsAttribute запечатан. Я использую обертку для MVC 4.

public class HttpPostedFileExtensionsAttribute : DataTypeAttribute, IClientValidatable 
{ 
    private readonly FileExtensionsAttribute _innerAttribute = 
     new FileExtensionsAttribute(); 

    /// <summary> 
    ///  Initializes a new instance of the <see cref="HttpPostedFileExtensionsAttribute" /> class. 
    /// </summary> 
    public HttpPostedFileExtensionsAttribute() 
     : base(DataType.Upload) 
    { 
     ErrorMessage = _innerAttribute.ErrorMessage; 
    } 

    /// <summary> 
    ///  Gets or sets the file name extensions. 
    /// </summary> 
    /// <returns> 
    ///  The file name extensions, or the default file extensions (".png", ".jpg", ".jpeg", and ".gif") if the property is not set. 
    /// </returns> 
    public string Extensions 
    { 
     get { return _innerAttribute.Extensions; } 
     set { _innerAttribute.Extensions = value; } 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, 
     ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
     { 
      ValidationType = "extension", 
      ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) 
     }; 
     rule.ValidationParameters["extension"] = _innerAttribute.Extensions; 
     yield return rule; 
    } 

    /// <summary> 
    ///  Applies formatting to an error message, based on the data field where the error occurred. 
    /// </summary> 
    /// <returns> 
    ///  The formatted error message. 
    /// </returns> 
    /// <param name="name">The name of the field that caused the validation failure.</param> 
    public override string FormatErrorMessage(string name) 
    { 
     return _innerAttribute.FormatErrorMessage(name); 
    } 

    /// <summary> 
    ///  Checks that the specified file name extension or extensions is valid. 
    /// </summary> 
    /// <returns> 
    ///  true if the file name extension is valid; otherwise, false. 
    /// </returns> 
    /// <param name="value">A comma delimited list of valid file extensions.</param> 
    public override bool IsValid(object value) 
    { 
     var file = value as HttpPostedFileBase; 
     if (file != null) 
     { 
      return _innerAttribute.IsValid(file.FileName); 
     } 

     return _innerAttribute.IsValid(value); 
    } 
} 
+0

Должна ли выполняться проверка клиента? – Escobar5

+0

Да, он должен, так как это 'IClientValidatable', он должен испускать ненавязчивые атрибуты jquery в html – jfeinour

+0

@bzlm. Это работает как ожидается с ASP.NET MVC5 и более новая [JQuery Validation Unobtrusive Native] (http://johnnyreilly.github.io/jQuery.Validation.Unobtrusive.Native/) библиотека - в ней используются более современные библиотеки JQuery Valdiation. –

1

Я знаю, что это слишком поздно, но, возможно, это может помочь кому-то там. Это модифицированная версия @jfeinour, которая будет работать на стороне клиента, а также:

public class HttpPostedFileExtensionAttribute : ValidationAttribute, IClientValidatable { 
    private readonly FileExtensionsAttribute _fileExtensionsAttribute = new FileExtensionsAttribute(); 

    public HttpPostedFileExtensionAttribute() { 
     ErrorMessage = _fileExtensionsAttribute.ErrorMessage; 
    } 

    public string Extensions { 
     get { return _fileExtensionsAttribute.Extensions; } 
     set { _fileExtensionsAttribute.Extensions = value; } 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { 
     var rule = new ModelClientValidationRule { 
      ValidationType = "extension", 
      ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) 
     }; 

     rule.ValidationParameters["extension"] = 
      _fileExtensionsAttribute.Extensions 
       .Replace(" ", string.Empty).Replace(".", string.Empty) 
       .ToLowerInvariant(); 

     yield return rule; 
    } 

    public override string FormatErrorMessage(string name) { 
     return _fileExtensionsAttribute.FormatErrorMessage(name); 
    } 

    public override bool IsValid(object value) { 
     var file = value as HttpPostedFileBase; 
     return _fileExtensionsAttribute.IsValid(file != null ? file.FileName : value); 
    } 
} 
+0

Я всегда любил ваши решения, но это, похоже, нарушает мою проверку на стороне клиента, и я также не могу помещать ErrorMessageResourceName внутри. Любое решение? –

+0

Как только я поместил атрибут FileExtensions или вашу оболочку, проверка на стороне клиента не работает. –

+0

версия jfeinour работает, как и ожидалось, с помощью ASP.NET MVC5 и JQuery Validation Unobtrusive Native] (http://johnnyreilly.github.io/jQuery.Validation.Unobtrusive.Native/), которая использует более современный JQuery Valdiation, а не очень старые, которые поставляются с MS Unobtrusive. –

Смежные вопросы