2010-03-16 29 views
5

Tôi muốn tạo chức năng ràng buộc mô hình để người dùng có thể nhập ',' '.' vv cho các giá trị tiền tệ liên kết với một giá trị gấp đôi của ViewModel của tôi.asp.net MVC 1.0 và 2.0 mô hình tiền tệ ràng buộc

Tôi có thể thực hiện việc này trong MVC 1.0 bằng cách tạo một trình kết nối mô hình tùy chỉnh, tuy nhiên kể từ khi nâng cấp lên MVC 2.0, chức năng này không còn hoạt động nữa.

Có ai có bất kỳ ý tưởng hay giải pháp nào tốt hơn để thực hiện chức năng này không? Một giải pháp tốt hơn là sử dụng một số chú thích dữ liệu hoặc thuộc tính tùy chỉnh.

public class MyViewModel 
{ 
    public double MyCurrencyValue { get; set; } 
} 

Một giải pháp ưu tiên sẽ là một cái gì đó như thế này ...

public class MyViewModel 
{ 
    [CurrencyAttribute] 
    public double MyCurrencyValue { get; set; } 
} 

Dưới đây là giải pháp của tôi cho ràng buộc trong MVC 1.0 model.

public class MyCustomModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     object result = null; 

     ValueProviderResult valueResult; 
     bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName, out valueResult); 
     bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueResult); 

     if (bindingContext.ModelType == typeof(double)) 
     { 
      string modelName = bindingContext.ModelName; 
      string attemptedValue = bindingContext.ValueProvider[modelName].AttemptedValue; 

      string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; 
      string alternateSeperator = (wantedSeperator == "," ? "." : ","); 

      try 
      { 
       result = double.Parse(attemptedValue, NumberStyles.Any); 
      } 
      catch (FormatException e) 
      { 
       bindingContext.ModelState.AddModelError(modelName, e); 
      } 
     } 
     else 
     { 
      result = base.BindModel(controllerContext, bindingContext); 
     } 

     return result; 
    } 
} 

Trả lời

7

Bạn có thể thử một cái gì đó giữa các dòng:

// Just a marker attribute 
public class CurrencyAttribute : Attribute 
{ 
} 

public class MyViewModel 
{ 
    [Currency] 
    public double MyCurrencyValue { get; set; } 
} 


public class CurrencyBinder : DefaultModelBinder 
{ 
    protected override object GetPropertyValue(
     ControllerContext controllerContext, 
     ModelBindingContext bindingContext, 
     PropertyDescriptor propertyDescriptor, 
     IModelBinder propertyBinder) 
    { 
     var currencyAttribute = propertyDescriptor.Attributes[typeof(CurrencyAttribute)]; 
     // Check if the property has the marker attribute 
     if (currencyAttribute != null) 
     { 
      // TODO: improve this to handle prefixes: 
      var attemptedValue = bindingContext.ValueProvider 
       .GetValue(propertyDescriptor.Name).AttemptedValue; 
      return SomeMagicMethodThatParsesTheAttemptedValue(attemtedValue); 
     } 
     return base.GetPropertyValue(
      controllerContext, 
      bindingContext, propertyDescriptor, 
      propertyBinder 
     ); 
    } 
} 

public class HomeController: Controller 
{ 
    [HttpPost] 
    public ActionResult Index([ModelBinder(typeof(CurrencyBinder))] MyViewModel model) 
    { 
     return View(); 
    } 
} 

UPDATE:

Dưới đây là một sự cải tiến của các chất kết dính (xem TODO phần trong mã trước):

if (!string.IsNullOrEmpty(bindingContext.ModelName)) 
{ 
    var attemptedValue = bindingContext.ValueProvider 
     .GetValue(bindingContext.ModelName).AttemptedValue; 
    return SomeMagicMethodThatParsesTheAttemptedValue(attemtedValue); 
} 

Trong Để xử lý các bộ sưu tập, bạn sẽ cần phải đăng ký chất kết dính trong Application_Start như bạn sẽ không còn có thể để trang trí trong danh sách với ModelBinderAttribute:

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    RegisterRoutes(RouteTable.Routes); 
    ModelBinders.Binders.Add(typeof(MyViewModel), new CurrencyBinder()); 
} 

Và sau đó hành động của bạn có thể trông như thế này:

[HttpPost] 
public ActionResult Index(IList<MyViewModel> model) 
{ 
    return View(); 
} 

Khái quát những phần quan trọng:

bindingContext.ValueProvider.GetValue(bindingContext.ModelName) 

Một bước cải thiện hơn nữa chất kết dính này sẽ được xử lý xác nhận (AddModelErro r/SetModelValue)

+0

Nếu bạn đang xử lý danh sách MyViewModel, điều đó có thay đổi ModelBinder cho hành động không? Chỉ mục hành động công khai ([ModelBinder (typeof (CurrencyBinder))] IList mô hình) – David

+0

Vui lòng xem cập nhật của tôi. –

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