2011-12-16 39 views
8

Theo tài liệu MSDN, theo mặc định FileExtensionsAttribute (.NET 4.5) nên cho phép tôi chỉ tải lên tệp jpg, jpeg, gif và png - đó là những gì tôi muốn .ASP.NET MVC 3: DataAnnotations.FileExtensionsAttribute không hoạt động

Tôi đã thử tải lên một jpg không có thuộc tính, nó hoạt động. Tuyệt quá. Sau đó, Tôi đã thêm thuộc tính vào mô hình chế độ xem của mình ..

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

Không có niềm vui. Việc xác minh không thành công và ErrorMessage được hiển thị. Trên hết, dường như không có cách nào để chỉ định bất kỳ tiện ích mở rộng tệp tùy chỉnh nào được phép. Tôi đã kết thúc mở rộng FileExtensionsAttribute và sử dụng logic xác minh của riêng tôi, hoạt động như mong đợi. Nhưng tại sao cách này không hiệu quả?

Sẽ đăng toàn bộ bộ điều khiển và xem nếu được yêu cầu. Tôi đã sử dụng ví dụ này làm cơ sở cho logic tải lên, nhưng sử dụng DataAnnotations.FileExtensionsAttribute thay vì Microsoft.Web.Mvc.FileExtensions .. How do I upload images in ASP.NET MVC?

Trả lời

5

Sử dụng thuộc tính Extensions để đặt chúng. Mặc dù theo các tài liệu

Các phần mở rộng tên file, hoặc các phần mở rộng tập tin mặc định (".png", ".jpg", ".jpeg", và ".gif") nếu tài sản không được thiết lập .

Bạn có thể đặt nó giống như bạn đã thực hiện ErrorMessage. Vấn đề nhiều khả năng là nó không biết cách đánh giá liệu HttpPostedFileBase có phần mở rộng phù hợp hay không. Bạn sẽ cần phải sử dụng một từ khung MVC hoặc tạo của riêng bạn.

+0

Cảm ơn. Bạn đã đúng về FileExtensionsAttribute không biết cách truy cập tên tệp. Dường như mong đợi một chuỗi như tham số để xác minh. –

+0

Ngoài ra, cũng giống như một lưu ý, tôi nhận ra thông báo lỗi là thuộc tính trong khi chuỗi bộ lọc mở rộng tệp chỉ có thể được đặt làm đối số hàm tạo tùy chọn (nó là thuộc tính chỉ đọc). Cú pháp hơi khác một chút. –

0

Các FileExtensionsAttribute không biết làm thế nào để xác minh một HttpPostedFileBase, vì vậy tôi mở rộng nó ..

/// <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); 
    } 
} 

Lưu ý rằng phương pháp này buộc các tập tin để trở thành một trường bắt buộc. Ngoài ra, nếu đó là trường tùy chọn, hãy sử dụng mã bên dưới cho phần thân phương thức. Điều này luôn luôn trả về thành công nếu không có tập tin được quy định (có thể là nhiều hơn đúng trong hầu hết các trường hợp) ..

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

Không phải là FileExtensionsAttribute sealed? – Ben

+1

FileExtensionsAttribute class được niêm phong. Vì vậy, điều này không thể được thừa hưởng – Unnie

24

Kể từ System.ComponentModel.DataAnnotations.FileExtensionsAttribute được bịt kín. Tôi sử dụng trình bao bọc cho 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

Xác nhận khách hàng có nên hoạt động không? – Escobar5

+0

Có, vì nó là 'IClientValidatable' nó nên phát ra các thuộc tính jquery unobstrusive trong html – jfeinour

+0

@bzlm - Điều này hoạt động như mong đợi với ASP.NET MVC5 và thư viện [JQuery Validation Unobtrusive Native] mới hơn (thư viện http://johnnyreilly.github.io/jQuery.Validation.Unobtrusive.Native/) - điều này sử dụng các thư viện Valquiation được cập nhật mới hơn. –

1

Tôi biết điều này hơi muộn, nhưng có lẽ điều này có thể giúp ai đó ở ngoài đó. Đây là phiên bản sửa đổi của @jfeinour, cũng sẽ hoạt động trên phía máy khách cũng như:

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

Tôi luôn yêu các giải pháp của bạn, nhưng điều này dường như phá vỡ xác nhận phía máy khách của tôi và tôi cũng không thể đặt ErrorMessageResourceName bên trong. Bất kì giải pháp nào? –

+0

Ngay sau khi tôi đặt thuộc tính FileExtensions hoặc trình bao bọc của bạn, xác thực phía máy khách không hoạt động. –

+0

Phiên bản của jfeinour hoạt động như mong đợi với ASP.NET MVC5 và thư viện không hợp lệ của JQuery Validation Unobtrusive] (http://johnnyreilly.github.io/jQuery.Validation.Unobtrusive.Native/) - sử dụng JQuery cập nhật hơn Valdiation thư viện chứ không phải là những người rất cũ đi kèm với gói MS Unobtrusive. –

Các vấn đề liên quan