2013-07-17 31 views
6

Tôi đang làm việc trong MVC4 và muốn xác định mô hình bằng thuộc tính Uppercase. Ý tưởng sẽ là sự hiện diện của thuộc tính Chữ hoa sẽ làm cho giá trị mô hình được chuyển thành chữ hoa khi nó đến máy chủ.Thuộc tính chữ hoa chuyển đổi đầu vào thành chữ hoa

Tại thời điểm tôi có đoạn mã sau trong mô hình:

[Required] 
    [Display(Name="Account Code")] 
    [StringValidation(RegExValidation.AccountCode, Uppercase=true)] 
    public string Account 
    { 
     get { return _account; } 
     set 
     { 
      if (value != null) 
       _account = value.ToUpper(); 
     } 
    } 

Nhưng những gì tôi thực sự muốn là thế này:

[Required] 
    [Display(Name="Account Code")] 
    [StringValidation(RegExValidation.AccountCode)] 
    [Uppercase] 
    public string Account { get; set; } 

Tôi nghĩ rằng tôi có thể cần để tạo ra các thuộc tính viết hoa dưới dạng ValidationAttribute để đảm bảo nó được kích hoạt khi mô hình truy cập máy chủ. Nhưng điều đó có vẻ hơi sai, vì tôi không thực sự xác thực dữ liệu. Có cách nào tốt hơn?

Ngoài ra, có cách nào để đảm bảo lệnh gọi trên các thuộc tính không? Tôi thực sự muốn chuyển đổi dữ liệu thành chữ hoa trước khi thuộc tính tùy chỉnh StringValidation kích hoạt, vì điều này kiểm tra trường hợp của văn bản trong mẫu regex.

Để thêm một chút nền vào điều này, tôi muốn giảm bớt nhu cầu thêm mã vào chữ hoa dữ liệu. Niết bàn sẽ là một thuộc tính duy nhất, cập nhật dữ liệu trên đường vào máy chủ, trong giai đoạn ràng buộc hoặc xác thực mô hình. Thuộc tính này sau đó có thể được tham chiếu trong thuộc tính StringValidation để sửa đổi giá trị RegEx được sử dụng trong các kiểm tra của nó. Tôi cũng có thể tra cứu thuộc tính này trong phương thức trợ giúp tùy chỉnh TextBoxFor, sao cho tôi có thể thêm text-transform: uppercase để nó có vẻ chính xác ở phía máy khách.

Có ai có ý tưởng nào không?

Trả lời

5

Tôi đã cố gắng làm việc này, đến một điểm, vì vậy đây là giải pháp của tôi cho những người khác để đánh giá.

Một khi điểm cần lưu ý là không thể đạt được giải pháp đầy đủ vì tôi không thể nhận được Modelmetadata bên trong thuộc tính StringValidation.IsValid(). Vấn đề cụ thể tôi có ở đây là tôi có thể lấy Siêu dữ liệu, tuy nhiên tôi không thể lấy số PropertyName từ nó, chỉ có DisplayName. Có nhiều lựa chọn ở đó, nhưng thực tế là một số thuộc tính của tôi có cùng một DisplayName có nghĩa là tôi không thể chắc chắn rằng ProprtyName là một trong những thực tế tôi đã xác thực.

Dưới đây là các mã cho ValidationAttribute:

public class StringValidationAttribute : ValidationAttribute, IClientValidatable, IMetadataAware { 

    private bool _uppercase; 

    public StringValidationAttribute(bool uppercase = false) { 
     _uppercase = uppercase; 
    } 

    ... 

    public void OnMetadataCreated(ModelMetadata metadata) 
    { 
     metadata.AdditionalValues["Uppercase"] = _uppercase; 
    } 
} 

sau đó tôi đã tạo ra một mới IModelBinder thực hiện:

public class StringBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {   
     ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     if (result == null) 
      return null; 

     if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey("Uppercase")) { 
      if ((bool)bindingContext.ModelMetadata.AdditionalValues["Uppercase"]]) 
       return result.AttemptedValue.ToUpper(); 
     } 

     return result.AttemptedValue; 
    } 
} 

Và đăng ký mà trong Global.asax tập tin của tôi:

ModelBinders.Binders.Add(typeof(string), new StringBinder()); 

Mã cho đến nay sẽ gây ra bất kỳ hợp đồng đầu vào chuỗi nào ming vào MVC sẽ được chuyển thành chữ hoa nếu nó có StringValidationAttribute gắn với nó trên mô hình, và nơi chỉ báo chữ hoa đã được đặt.

Tiếp theo, để đạt được mong muốn tạo các biểu mẫu html của tôi là chữ hoa, tôi đã triển khai EditorTemplate mới có tên string.cshtml. Trong chế độ xem này tôi đã thêm:

RouteValueDictionary htmlAttributes = new RouteValueDictionary(); 
if ((bool)ViewData.ModelMetadata.AdditionalValues["Uppercase"]) { 
    htmlAttributes.Add("class", "Uppercase"); 
} 
@Html.TextBox("", Model, htmlAttributes) 

Với CSS như;

.Uppercase { 
    text-transform: uppercase; 
} 

Hy vọng bài đăng này sẽ giúp một số người khác ngoài đó.

+0

Điều đó khá thú vị! –

+0

Xin chào, điều này có áp dụng cho MVC 4 không? vì tôi nhận được lỗi sau. 'UpperCaseValidationAttribute' không thực hiện thành viên giao diện 'System.Web.Mvc.IClientValidatable.GetClientValidationRules (System.Web.Mvc.ModelMetadata, System.Web.Mvc.ControllerContext)' bạn có thể vui lòng giúp đỡ không? Cảm ơn!! – ecasper

+0

Có tính năng này hoạt động trong MVC4. Bạn cần phải thêm một ghi đè cho 'public IEnumerable GetClientValidationRules (siêu dữ liệu ModelMetadata, bối cảnh ControllerContext)'. Đây là một chút trong ... trong câu trả lời :) – Nick

0

Bạn nói đúng, ValidationAttribute không phù hợp. Nó có vẻ như làm điều này ở giai đoạn mô hình ràng buộc sẽ là một ý tưởng tốt hơn. Xem this article để có giải thích chi tiết về cách tùy chỉnh hành vi này.

Dựa trên những thông tin được cung cấp ở đó, tôi tin rằng bạn sẽ có thể tạo ra một thuộc tính dựa trên CustomModelBinderAttribute như thế này:

[AttributeUsage(AttributeTargets.Property)] 
public class UppercaseAttribute : CustomModelBinderAttribute 
{ 
    public override IModelBinder GetBinder() 
    { 
     return new UppercaseModelBinder(); 
    } 

    private class UppercaseModelBinder : DefaultModelBinder 
    { 
     public override object BindModel(
      ControllerContext controllerContext, 
      ModelBindingContext bindingContext) 
     { 
      var value = base.BindModel(controllerContext, bindingContext); 
      var strValue = value as string; 
      if (strValue == null) 
       return value; 
      return strValue.ToUpperInvariant(); 
     } 
    } 
} 

tôi đã không kiểm tra này. Hãy cho tôi biết nếu nó hoạt động hay không.

+0

Cảm ơn Daniel, tiếc là không thể gán DefaultModelBinder cho Thuộc tính. 'AttributeUsageAttribute (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Parameter' – Nick

+0

Sau đó chúng ta sẽ phải đi một cấp cao hơn.Chúng ta cần thay đổi chất kết dính mô hình cho các lớp có chứa các chuỗi này, thay đổi thuộc tính UppercaseAttribute thành một thuộc tính đánh dấu đơn giản và yêu cầu trình mô hình tìm kiếm thuộc tính này và xử lý các chuỗi khác nhau. –

-1

LƯU Ý: Tôi đang thêm vào bài đăng này bởi vì cho đến khi tôi phát hiện ra cách tiếp cận hiện tại, tôi đọc và thử tất cả ở trên không thành công.

Tôi thường sử dụng quy trình hai phần khi xử lý việc buộc dữ liệu văn bản được định dạng là chữ hoa. 1. ở chế độ xem và 2. tại bộ điều khiển

  1. Ở lớp xem để người dùng biết dữ liệu sẽ được sử dụng ở dạng chữ hoa. Điều này có thể được thông qua htmlAttributes được sử dụng trong trình trợ giúp EditorFor HTML.

    @HTML.EditorFor(model => model.Access_Code, new { htmlAttributes = new Style= "text-transform:uppercase"}}) 
    

Bây giờ này chỉ buộc các dữ liệu nhìn thấy và nhập vào bởi người sử dụng chữ hoa và không phải là dữ liệu được gửi đến máy chủ. Để làm điều đó đòi hỏi một số mã trong phương pháp liên kết trong bộ điều khiển.

  1. Tôi thêm phương thức ToUpper() vào thuộc tính đích của đối tượng được truyền lại cho đối tượng. Đây là ví dụ giả định cho thấy điều này.

    public ActionResult verify(int? id) 
         { 
         var userData = db.user.Where (i=> i.userID == id).Single(); 
    
         userData.Access_Code = userData.Access_Code.ToUpper(); 
    
        ... 
    } 
    
0

Đối với mục đích API Web nó là tốt hơn để chuyển đổi json đến chữ hoa hay chữ thường.

public class ToUpperCase : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return objectType == typeof(string); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return reader.Value.ToString().ToUpper(); 
     }    
    } 



    [Display(Name = "PNR NAME")] 
    [JsonConverter(typeof(Annotations.ToUpperCase))] 
    public string PNR { get; set; } 

HOẶC toàn cầu;

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 
     //.......... others 



     JsonMediaTypeFormatter jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter; 
     JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings(); 
     jSettings.Converters.Add(new UpperCaseStringConverter()); 
     jsonFormatter.SerializerSettings = jSettings; 
    }