2011-12-16 43 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を拡張し、期待通りに機能する独自の検証ロジックを使用しました。しかし、なぜこのように動作しないのですか?

コントローラ全体を投稿し、必要に応じて表示します。私はアップロードロジックの基礎としてこの例を使用しますが、How do I upload images in ASP.NET MVC?

答えて

5

は、それらを設定するExtensionsプロパティを使用します。.. Microsoft.Web.Mvc.FileExtensionsの代わりにDataAnnotations.FileExtensionsAttributeを使用します。ドキュメント

ファイル名の拡張子、またはデフォルトのファイル拡張子(「.PNG」、 「.JPG」、「.JPEG」、および「.GIF」)に応じてプロパティが設定されていない場合が。

ErrorMessageと同じように設定できます。より可能性の高い問題は、HttpPostedFileBaseが正しい拡張子を持っているかどうかを評価する方法を知らないことです。 MVCフレームワークのものを使用するか、独自のものを作成する必要があります。

+0

ありがとう:これは、同様にクライアント側上で動作します@jfeinourの修正版です。 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); 
    } 
} 

。代わりに、オプションのフィールドの場合は、メソッド本体の下のコードを使用します。ファイルを指定しない場合System.ComponentModel.DataAnnotations.FileExtensionsAttributeが封入されているので、これは常に...(おそらくより正確なほとんどの場合)

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

FileExtensionsAttributeが封印されていませんか? – Ben

+1

FileExtensionsAttributeクラスが封印されています。だからこれは継承することはできません – Unnie

24

を成功を返します。私は、これは遅すぎる少しですけど、多分これはそこに誰かを助けることができる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'なので、htmlで邪魔にならないjquery属性を出すべきです – jfeinour

+0

@bzlm - これはASPで期待通りに動作します。NET MVC5と新しい[JQuery Validation Unobtrusive Native](http://johnnyreilly.github.io/jQuery.Validation.Unobtrusive.Native/)ライブラリ - これはより最新のJQuery Valdiationライブラリを使用します。 –

1

のラッパーを使用します。

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 MS Unobtrusiveパッケージに付属している古いライブラリではなく、Valdiationライブラリです。 –

関連する問題