2009-12-04 29 views
19

Tôi đã tạo tùy chỉnh ResourceProvider để lấy thông tin bản địa hóa từ cơ sở dữ liệu. Bây giờ tôi muốn sử dụng DataAnnotation để thêm xác thực vào mô hình.DataAnnotation với ResourceProvider tùy chỉnh

DataAnnotationErrorMessageResourceTypeErrorMessageResourceName tính nhưng ErrorMessageResourceType chỉ chấp nhận System.Type (ví dụ một tập tin tài nguyên biên soạn)

Có cách nào để có được DataAnnotation sử dụng ResourceProvider tùy chỉnh?

Trả lời

5

Tôi nhận thấy đây là câu hỏi cũ nhưng muốn thêm một chút. Tôi thấy mình trong tình huống tương tự và dường như không có bất kỳ tài liệu/blog nào về chủ đề này. Tuy nhiên, tôi đã tìm ra cách để sử dụng nhà cung cấp tài nguyên tùy chỉnh, với một báo trước. Thông báo trước là tôi đang ở trong ứng dụng MVC nên tôi vẫn có sẵn HttpContext.GetLocalResourceObject(). Đây là phương pháp mà asp.net sử dụng để bản địa hóa các mục. Việc thiếu đối tượng tài nguyên không ngăn bạn viết giải pháp riêng của chúng tôi, ngay cả khi đó là truy vấn trực tiếp của các bảng DB. Tuy nhiên, tôi nghĩ rằng nó là giá trị chỉ ra.

Mặc dù tôi không hài lòng với giải pháp sau, có vẻ như nó hoạt động. Đối với mỗi thuộc tính xác nhận tôi muốn sử dụng tôi kế thừa từ thuộc tính đã nói và quá tải IsValid(). Trang trí trông như thế này:

[RequiredLocalized(ErrorMessageResourceType= typeof(ClassBeginValidated), ErrorMessageResourceName="Errors.GenderRequired")] 
public string FirstName { get; set; } 

Thuộc tính mới trông như thế này:

public sealed class RequiredLocalized : RequiredAttribute { 

    public override bool IsValid(object value) { 

     if (! (ErrorMessageResourceType == null || String.IsNullOrWhiteSpace(ErrorMessageResourceName)) ) { 
      this.ErrorMessage = MVC_HtmlHelpers.Localize(this.ErrorMessageResourceType, this.ErrorMessageResourceName); 
      this.ErrorMessageResourceType = null; 
      this.ErrorMessageResourceName = null; 
     } 
     return base.IsValid(value); 
    } 
} 

Ghi chú

  • Bạn cần phải trang trí mã của bạn với các thuộc tính có nguồn gốc, không tiêu chuẩn một
  • Tôi đang sử dụng ErrorMessageResourceType để chuyển loại của lớp đang được xác thực. Điều đó có nghĩa là nếu tôi ở trong một lớp khách hàng và xác nhận tài sản FirstName tôi sẽ vượt qua loại (khách hàng). Tôi đang làm điều này bởi vì trong backend cơ sở dữ liệu của tôi, tôi đang sử dụng tên lớp đầy đủ (namespace + classname) làm khóa (giống như một URL trang được sử dụng trong asp.net).
    • MVC_HtmlHelpers.Localize chỉ là một wrapper đơn giản để cung cấp tài nguyên tùy chỉnh của tôi

The (bán bị đánh cắp) mã helper trông như thế này ....

public static string Localize (System.Type theType, string resourceKey) { 
    return Localize (theType, resourceKey, null); 
} 
public static string Localize (System.Type theType, string resourceKey, params object[] args) { 
    string resource = (HttpContext.GetLocalResourceObject(theType.FullName, resourceKey) ?? string.Empty).ToString(); 
    return mergeTokens(resource, args); 
} 

private static string mergeTokens(string resource, object[] args)  { 
    if (resource != null && args != null && args.Length > 0) { 
     return string.Format(resource, args); 
    } else { 
     return resource; 
    } 
} 
3

Tôi đã sử dụng xác thực thông thạo để đạt được điều này. Nó giúp tôi tiết kiệm rất nhiều thời gian. Đây là những gì Trình xác nhận toàn cầu hóa của tôi trông như thế nào. Nó có nghĩa là bạn không sử dụng dữ liệu anotations, nhưng đôi khi dữ liệu anotations nhận được một chút lớn và lộn xộn.

Dưới đây là một ví dụ:

(Errors.Required, Labels.Email và Errors.AlreadyRegistered trong thư mục nguồn blobal tôi.)

public class CreateEmployerValidator : AbstractValidator<CreateEmployerModel> { 
    public RegisterUserValidator() { 
     RuleFor(m => m.Email) 
      .NotEmpty() 
      .WithMessage(String.Format(Errors.Required, new object[] { Labels.Email })) 
      .EmailAddress() 
      .WithMessage(String.Format(Errors.Invalid, new object[] { Labels.Email })) 
      .Must(this.BeUniqueEmail) 
      .WithMessage(String.Format(Errors.AlreadyRegistered, new object[] { Labels.Email })); 
    } 

    public bool BeUniqueEmail(this IValidator validator, string email) { 
     //Database request to check if email already there? 
     ... 
    }  
} 

Như tôi đã nói, đó là một chú thích dữ liệu biểu mẫu di chuyển, chỉ vì tôi đã có quá nhiều chú thích trên phương thức của tôi rồi!

2

Tôi sẽ thêm các phát hiện của mình vì tôi phải chiến đấu với điều này. Có lẽ nó sẽ giúp ai đó.

Khi bạn lấy được từ RequiredAttribute, có vẻ như nó sẽ phá vỡ xác thực phía máy khách. Vì vậy, để khắc phục điều này, tôi đã triển khai IClientValidatable và triển khai phương thức GetClientValidationRules. Tài nguyên.GetResources là phương thức trợ giúp tĩnh tôi đã kết thúc tốt đẹp quanh HttpContext.GetGlobalResourceObject.

Tục thuộc tính yêu cầu:

public class LocalizedRequiredAttribute : RequiredAttribute, IClientValidatable 
{ 
    public LocalizedRequiredAttribute(string resourceName) 
    { 
     this.ErrorMessage = Resources.GetResource(resourceName); 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     yield return new ModelClientValidationRule 
     { 
      ErrorMessage = this.ErrorMessage, 
      ValidationType= "required" 
     }; 
    } 
} 

Cách sử dụng:

[LocalizedRequired("SomeResourceName")] 
public string SomeProperty { get; set; } 

Và Tài helper của tôi nếu có ai quan tâm:

public class Resources 
{ 
    public static string GetResource(string resourceName) 
    { 
     string text = resourceName; 
     if (System.Web.HttpContext.Current != null) 
     { 
      var context = new HttpContextWrapper(System.Web.HttpContext.Current); 
      var globalResourceObject = context.GetGlobalResourceObject(null, resourceName); 
      if (globalResourceObject != null) 
       text = globalResourceObject.ToString(); 
     } 

     return text; 
    } 
} 
Các vấn đề liên quan