2010-03-16 31 views
5

Bir kullanıcı girebilsin diye model bağlama işlevi oluşturmak istiyorum ',' '.' ViewModel'imin çifte değerine bağlanan para birimi değerleri için vb.asp.net MVC 1.0 ve 2.0 para birimi model bağlama

Bunu MVC 1.0'da özel bir model bağlayıcı oluşturarak yapabilirdim, ancak MVC 2.0'a yükselttikten sonra bu işlev artık çalışmıyor.

Bu işlevsellik için herhangi bir fikri veya daha iyi çözümleri olan var mı? Daha iyi bir çözüm, bazı veri açıklamalarını veya özel niteliklerini kullanmak olabilir.

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

bir tercih edilen çözüm

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

Aşağıda MVC 1.0'da bağlama modeli için benim çözüm ... Böyle bir şey olurdu.

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

cevap

7

Sen hatları arasında bir şeyler deneyebilirsiniz:

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

GÜNCELLEME: Burada

bağlayıcı bir gelişmedir (önceki kodda TODO bölümüne bakınız):

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

In

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

Ve sonra eylem bu gibi görünebilir::

[HttpPost] 
public ActionResult Index(IList<MyViewModel> model) 
{ 
    return View(); 
} 
artık ModelBinderAttribute listeyi süslemek mümkün olacak gibi Application_Start yılında bağlayıcı kayıt gerekecek koleksiyonları işlemek için sipariş

özetlenmesi önemli bir parçasıdır:

bindingContext.ValueProvider.GetValue(bindingContext.ModelName) 

bu bağlayıcı bir başka gelişme, aşama (doğrulama işlemek olur AddModelErro r/SetModelValue)

+0

MyViewModel'in bir listesiyle ilgileniyorsanız, bu eylem için ModelBinder'ı değiştirir mi? public ActionResult Dizini ([ModelBinder (typeof (CurrencyBinder))] IList model) – David

+0

Lütfen güncellemeye bakın. –

İlgili konular