2010-03-16 9 views
5

मैं मॉडल बाध्यकारी कार्यक्षमता बनाना चाहता हूं ताकि उपयोगकर्ता ',' '' दर्ज कर सके। आदि मुद्रा मूल्यों के लिए जो मेरे ViewModel के दोहरे मूल्य से बंधे हैं।एएसपीएनटी एमवीसी 1.0 और 2.0 मुद्रा मॉडल बाध्यकारी

मैं एक कस्टम मॉडल बाइंडर बनाकर एमवीसी 1.0 में ऐसा करने में सक्षम था, हालांकि एमवीसी 2.0 में अपग्रेड करने के बाद से यह कार्यक्षमता अब काम नहीं करती है।

क्या किसी के पास इस कार्यक्षमता को करने के लिए कोई विचार या बेहतर समाधान है? एक बेहतर समाधान कुछ डेटा एनोटेशन या कस्टम विशेषता का उपयोग करना होगा।

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

एक पसंदीदा समाधान कुछ इस तरह होगा ...

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

नीचे मॉडल MVC 1.0 में बांधने के लिए मेरे समाधान है।

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

उत्तर

7

आप लाइनों के बीच में कुछ कोशिश कर सकते हैं:

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

अद्यतन:

यहाँ बांधने की मशीन के एक सुधार है (पिछले कोड में TODO अनुभाग देखें):

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

इन आदेश आप के रूप में तुम अब ModelBinderAttribute के साथ इस सूची को सजाने के लिए सक्षम हो जाएगा Application_Start में बांधने की मशीन में पंजीकरण करना होगा संकलन प्रबंधित करने के लिए:

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

और फिर अपनी कार्रवाई ऐसा दिखाई दे सकता:

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

सारांश महत्वपूर्ण हिस्सा:

bindingContext.ValueProvider.GetValue(bindingContext.ModelName) 

इस बांधने की मशीन के एक और सुधार कदम मान्यता को संभालने के लिए होगा (AddModelErro आर/SetModelValue)

+0

यदि आप MyViewModel की एक सूची से निपट रहे हैं तो क्या कार्रवाई के लिए मॉडलबिन्डर बदलता है? सार्वजनिक एक्शन रिसैट इंडेक्स ([मॉडलबिंडर (टाइपोफ (मुद्राबिंदर))] IList मॉडल) – David

+0

कृपया मेरा अपडेट देखें। –

संबंधित मुद्दे