गलत मान के साथ ASP.Net MVC Html.HiddenFor


132

मैं अपने प्रोजेक्ट में MVC 3 का उपयोग कर रहा हूं, और मैं एक बहुत ही अजीब व्यवहार देख रहा हूं।

मैं अपने मॉडल पर एक विशेष मूल्य के लिए एक छिपे हुए क्षेत्र को बनाने की कोशिश कर रहा हूं, समस्या यह है कि किसी कारण से क्षेत्र पर निर्धारित मूल्य मॉडल में मूल्य के अनुरूप नहीं है।

जैसे

मेरे पास यह कोड है, सिर्फ एक परीक्षा के रूप में:

<%:Html.Hidden("Step2", Model.Step) %>
<%:Html.HiddenFor(m => m.Step) %>

मुझे लगता है कि दोनों छिपे हुए क्षेत्रों का एक ही मूल्य होगा। मैं क्या कर रहा हूं, पहली बार जब मैं दृश्य प्रदर्शित करता हूं, तो मान को 1 पर सेट करें, और फिर प्रस्तुत करने के बाद मैं 1 के साथ मॉडल फ़ील्ड का मूल्य बढ़ाता हूं।

इसलिए, पहली बार जब मैं पृष्ठ को सौंपता हूं तो दोनों नियंत्रणों का मूल्य 1 है, लेकिन दूसरी बार प्रदान किए गए मूल्य ये हैं:

<input id="Step2" name="Step2" type="hidden" value="2" />
<input id="Step" name="Step" type="hidden" value="1" />

जैसा कि आप देख सकते हैं, पहला मान सही है, लेकिन दूसरा मान ऐसा प्रतीत होता है जैसे मैंने पहली बार दृश्य प्रदर्शित किया है।

मैं क्या खो रहा हूँ? क्या * Html हेल्पर्स के लिए वैल्यूज़ को किसी तरह से कैशिंग करना है? यदि हां, तो मैं इस कैशिंग को कैसे अक्षम कर सकता हूं?

आपकी सहायता के लिए धन्यवाद।


मैंने अभी कुछ और परीक्षण किया है। अगर मैं हिडफ़ॉर कॉल को हटा देता हूं और केवल हिडन कॉल को छोड़ देता हूं, लेकिन "स्टेप" नाम का उपयोग करते हुए, यह केवल पहले मूल्य (1) का भी प्रतिपादन करता है।
विल्व

1
साथ ही साथ होता है
ओरेन ए

जवाबों:


191

यह सामान्य है और यह है कि HTML सहायकों कैसे काम करते हैं। वे पहले POST अनुरोध के मूल्य और उसके बाद मॉडल में मूल्य का उपयोग करते हैं। इसका मतलब यह है कि भले ही आप अपने नियंत्रक क्रिया में मॉडल के मूल्य को संशोधित करते हैं अगर POST अनुरोध में एक ही चर है तो आपके संशोधन को अनदेखा किया जाएगा और POSTed मूल्य का उपयोग किया जाएगा।

नियंत्रक क्रिया में मॉडल स्थिति से इस मान को निकालने के लिए एक संभव समाधान है जो मूल्य को संशोधित करने का प्रयास कर रहा है:

// remove the Step variable from the model state 
// if you want the changes in the model to be
// taken into account
ModelState.Remove("Step");
model.Step = 2;

एक अन्य संभावना एक कस्टम HTML सहायक लिखना है जो हमेशा मॉडल के मूल्य का उपयोग करेगा और POST मूल्यों को अनदेखा करेगा।

और फिर भी एक और संभावना:

<input type="hidden" name="Step" value="<%: Model.Step %>" />

5
मैंने इस बारे में साइमन इंस के ब्लॉग पोस्ट की वास्तव में सराहना की। यह निष्कर्ष मैं इसे अपने वर्कफ़्लो सही है सुनिश्चित करने के लिए है। इसलिए यदि आपने एक मान्य दृश्य मॉडल स्वीकार कर लिया है और उसके साथ कुछ किया है, तो पुष्टिकरण कार्रवाई के लिए पुनर्निर्देशित करें, भले ही यह भी केवल एक मॉडल को फिर से प्रदर्शित और प्रदर्शित करता हो। इसका मतलब है कि आपके पास एक नया मॉडलस्टैट है। blogs.msdn.com/b/simonince/archive/2010/05/05/… (एक पोस्ट से जुड़ा हुआ है जो मैंने आज इस पर लिखा है: ocbites.blogspot.com/2011/02/mvc-renders-wrong-value.html )
लीसा

2
मुझे वास्तव में MVC3 पसंद है, लेकिन यह बिट वास्तव में क्लंकी है। मुझे उम्मीद है कि वे इसे MVC4 में ठीक कर लेंगे।
केनीजेड

5
वाह, यह एक मुझे काफी समय के लिए जा रहा था। मैंने मूल रूप से पहले सुझाव का उपयोग किया था लेकिन लौटने से पहले सिर्फ ModelState.Clear () कहा जाता था। यह बहुत अच्छा काम करता है, क्या कोई कारण स्पष्ट नहीं है?
जेसन

1
".Remove" ने मेरे लिए काम नहीं किया। लेकिन ModelState.Clear () ने नियंत्रक में वापसी से ठीक पहले किया था। कस्टम-लेखन आपका हिडन भी अच्छा काम करेगा। यह सब इसलिए होता है क्योंकि डेवलपर्स अपने "फॉर्म वैल्यू" को खोना नहीं चाहते हैं यदि वे "सबमिट" दबाते हैं और डीबी सही तरीके से नहीं बचाता है। सबसे अच्छा समाधान: एक ही नाम / आईडी एक ही पृष्ठ पर विभिन्न क्षेत्रों का नाम नहीं है।
Dexter

1
FYI करें इस कष्टप्रद व्यवहार को गंभीरता से ASP.NET को सौंपा गया था, अगर किसी को चिंता थी कि चीजें बेहतर हो जाएंगी
John Hargrove

19

विज़ार्ड लिखते समय मुझे उसी समस्या का सामना करना पड़ा जो हर कदम पर एक बड़े मॉडल के विभिन्न हिस्सों को दिखाता है।
"चरण 1" से डेटा और / या त्रुटियां "चरण 2", आदि के साथ मिश्रित हो जाएंगी, जब तक कि मुझे अंततः पता नहीं चला कि मॉडलस्टैट को 'दोष' देना था।

यह मेरा सरल उपाय था:

if (oldPageIndex != newPageIndex)
{
    ModelState.Clear(); // <-- solution
}

return View(model[newPageIndex]);

10
ModelState.Clear()इसी तरह की स्थिति में क्रमिक POST अनुरोधों के साथ मेरे मुद्दे को हल किया।
इवान मुलावस्की

ModelState.Clear () टिप इवान के लिए धन्यवाद। यह एक विसंगति थी जिसका मैंने पहले कभी सामना नहीं किया। मेरे पास कई अनुक्रमिक ajax.beginform पोस्ट थे और उनमें से एक पिछले पोस्ट से मान बनाए रख रहा था। ब्लैक होल डिबगिंग। किसी को पता है कि यह कैश क्यों हो जाता है?
रोब

1

यह कोड काम नहीं करेगा

// remove the Step variable from the model state
// if you want the changes in the model to be
// taken into account
ModelState.Remove("Step");
model.Step = 2;

... क्योंकि माडफ़ॉर से ही (हमेशा!) हिडफॉर पढ़ता है न कि मॉडल ही। और अगर यह "स्टेप" कुंजी नहीं ढूंढता है, तो यह उस वैरिएबल प्रकार के लिए डिफ़ॉल्ट का उत्पादन करेगा जो इस मामले में 0 होगा

यहाँ समाधान है। मैंने इसे अपने लिए लिखा है लेकिन इसे साझा करने में कोई आपत्ति नहीं है क्योंकि मुझे लगता है कि बहुत से लोग इस शरारती हिफोर हेल्पर के साथ संघर्ष कर रहे हैं।

public static class CustomExtensions
{
    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression);
    }

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression, htmlAttributes);
    }

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
    {
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression, htmlAttributes);
    }

    private static void ReplacePropertyState<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        string text = ExpressionHelper.GetExpressionText(expression);
        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(text);
        ModelStateDictionary modelState = htmlHelper.ViewContext.ViewData.ModelState;
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

        if (modelState.ContainsKey(fullName))
        {                
            ValueProviderResult currentValue = modelState[fullName].Value;
            modelState[fullName].Value = new ValueProviderResult(metadata.Model, Convert.ToString(metadata.Model), currentValue.Culture);
        }
        else
        {
            modelState[fullName] = new ModelState
            {
                Value = new ValueProviderResult(metadata.Model, Convert.ToString(metadata.Model), CultureInfo.CurrentUICulture)
            };
        }
    }
}

तब आप इसे हमेशा अपने भीतर से देखने की तरह उपयोग करते हैं:

@Html.HiddenFor2(m => m.Id)

यह उल्लेख के लायक है यह संग्रह के साथ भी काम करता है।


यह समाधान पूरी तरह से काम नहीं किया। अगली पोस्ट के बाद संपत्ति एक्शन में शून्य है
user576510

खैर, यह उत्पादन से कोड है जहां यह ठीक काम करता है। मैं नहीं बता सकता कि यह आपके लिए काम क्यों नहीं करता है, लेकिन यदि आप पेज पर दिए गए सही मान के साथ छिपे हुए क्षेत्र को देखते हैं, तो मुझे कोई स्पष्ट कारण नहीं दिखता है कि यह मॉडल की संपत्ति में पुनर्स्थापित नहीं किया जाएगा। यदि आप पृष्ठ पर गलत छिपे हुए फ़ील्ड मान को देखते हैं - हालांकि यह एक और कहानी है, तो मुझे यह जानने के लिए बहुत उत्सुक होना होगा कि यह मेरे उत्पादन पर होने वाली परिस्थितियों से पहले क्या होता है :-) धन्यवाद।
रुस्लान Georgievskiy

0

मैं भी उसी स्थिति से जूझ रहा हूं जो मुझे लगता है, जहां मैं कॉल के बीच एक ही मॉडल स्थिति का उपयोग करता हूं, और जब मैं बैकएंड पर एक मॉडल संपत्ति में परिवर्तन करता हूं। हालाँकि, यह मेरे लिए मायने नहीं रखता, अगर मैं टेक्स्टबॉक्स या हिडनफ़ॉर्म का उपयोग करता हूं।

मैं मॉडल वैल्यू को js वेरिएबल के रूप में स्टोर करने के लिए पेज स्क्रिप्ट्स का उपयोग करके केवल स्थिति को बायपास करता हूं, क्योंकि मुझे शुरुआत में उस उद्देश्य के लिए हिडनफ़ील्ड की आवश्यकता है।

यकीन नहीं होता है कि अगर यह मदद करता है लेकिन सिर्फ विचार

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.