के साथ मॉडलस्टेट अपडेट करना समस्या: पोस्टिंग + सत्यापन स्थिति में मॉडलस्टेट को अपडेट करने के लिए कैसे करें।मॉडल ऑब्जेक्ट
मैं एक सरल रूप मिल गया है:
<%= Html.ValidationSummary() %>
<% using(Html.BeginForm())%>
<%{ %>
<%=Html.TextBox("m.Value") %>
<input type="submit" />
<%} %>
उपयोगकर्ता द्वारा सबमिट जब मैं इनपुट को मान्य करना चाहते हैं और कुछ परिस्थितियों में मैं उपयोगकर्ता की त्रुटियों को ठीक, दे उसे पता है कि वह गलती से हुआ है कि चाहते हैं पहले से ही तय हो:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(M m)
{
if (m.Value != "a")
{
ModelState.AddModelError("m.Value", "should be \"a\"");
m.Value = "a";
return View(m);
}
return View("About");
}
खैर समस्या है, MVC बस मॉडल को देखने के लिए पारित कर दिया पर ध्यान नहीं देगा और फिर से प्रस्तुत करना होगा जो कुछ भी उपयोगकर्ता द्वारा लिखा गया है - और नहीं मेरी मूल्य ("एक")। ऐसा होता है, क्योंकि टेक्स्टबॉक्स रेंडरर जांचता है कि मॉडलस्टेट है और यदि यह शून्य नहीं है - मॉडलस्टेट का मान उपयोग किया जाता है। यह मान निश्चित रूप से पोस्ट करने से पहले एक उपयोगकर्ता टाइप किया गया है।
चूंकि मैं टेक्स्टबॉक्स रेंडरर के व्यवहार को नहीं बदल सकता क्योंकि मुझे लगता है कि केवल एक ही समाधान मॉडलस्टेट को अपडेट करना होगा। Quick'n'dirty तरीका है (ab) DefaultModelBinder का उपयोग करें और उस विधि को ओवरराइड करें जो असाइनमेंट दिशा को बदलकर फ़ॉर्म से मानों को मॉडल में निर्दिष्ट करता है;)। DefaultModelBinder का उपयोग करके मुझे आईडी को पार्स करने की आवश्यकता नहीं है।
/// <summary>
/// Updates ModelState using values from <paramref name="order"/>
/// </summary>
/// <param name="order">Source</param>
/// <param name="prefix">Prefix used by Binder. Argument name in Action (if not explicitly specified).</param>
protected void UpdateModelState(object model, string prefix)
{
new ReversedBinder().BindModel(this.ControllerContext,
new ModelBindingContext()
{
Model = model,
ModelName = prefix,
ModelState = ModelState,
ModelType = model.GetType(),
ValueProvider = ValueProvider
});
}
private class ReversedBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
string prefix = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
object val = typeof(Controller)
.Assembly.GetType("System.Web.Mvc.DictionaryHelpers")
.GetMethod("DoesAnyKeyHavePrefix")
.MakeGenericMethod(typeof(ValueProviderResult))
.Invoke(null, new object[] { bindingContext.ValueProvider, prefix });
bool res = (bool)val;
if (res)
{
IModelBinder binder = new ReversedBinder();//this.Binders.GetBinder(propertyDescriptor.PropertyType);
object obj2 = propertyDescriptor.GetValue(bindingContext.Model);
ModelBindingContext context2 = new ModelBindingContext();
context2.Model = obj2;
context2.ModelName = prefix;
context2.ModelState = bindingContext.ModelState;
context2.ModelType = propertyDescriptor.PropertyType;
context2.ValueProvider = bindingContext.ValueProvider;
ModelBindingContext context = context2;
object obj3 = binder.BindModel(controllerContext, context);
if (bindingContext.ModelState.Keys.Contains<string>(prefix))
{
var prefixKey = bindingContext.ModelState.Keys.First<string>(x => x == prefix);
bindingContext.ModelState[prefixKey].Value
= new ValueProviderResult(obj2, obj2.ToString(),
bindingContext.ModelState[prefixKey].Value.Culture);
}
}
}
}
तो सवाल रहता है:: मैं कुछ अत्यंत असामान्य कर रहा हूँ या मैं कुछ याद आ रही है निम्नलिखित कोड (DefaultModelBinder के मूल कार्यान्वयन के आधार पर) यह करने के लिए अपने समाधान है? यदि पूर्व, तो मैं इस तरह की कार्यक्षमता को बेहतर तरीके से कैसे कार्यान्वित कर सकता हूं (मौजूदा एमवीसी आधारभूत संरचना का उपयोग करके)?
लेकिन मैं डिफ़ॉल्ट बाध्यकारी प्राप्त करना चाहता हूं। मुझे यह चाहिए क्योंकि मैं मॉडलस्टेट का उपयोग करना चाहता हूं। मैं अपने मॉडल ऑब्जेक्ट में बदलावों को दर्शाने के लिए मॉडलस्टेट को अपडेट करना चाहता हूं। – user87338
कृपया मेरा संपादन देखें। –
आपकी टिप्पणी बिल्कुल वैसा ही है जो मैं कर रहा हूं, लेकिन आप इसे स्वयं करते हैं और मैं ते डेल्ट बाइंडर का उपयोग कर रहा हूं, इसलिए मेरे पास कुछ और "जेनेरिक" है। मूल्य ("ए") का परिवर्तन निम्न स्तर में होता है, इसलिए मुझे वास्तव में पता नहीं है कि प्रोप क्या बदल गए हैं। और आप मॉडलस्टेट ["एम। वैल्यू"] नहीं चाहते हैं। वैल्यू = नया वैल्यूप्रोवाइडर रीसेट ("ए", एम। एनएएम, संस्कृतिइन्फो। कंटेंटकल्चर); प्रत्येक 12 ऑब्जेक्ट की संपत्ति के लिए , क्या आप :)। – user87338