@ Html.HiddenFor ASP.NET MVC में सूचियों पर काम नहीं करता है


97

मैं एक मॉडल का उपयोग कर रहा हूं जिसमें एक संपत्ति के रूप में एक सूची शामिल है। मैं SQL सर्वर से हड़पने वाली वस्तुओं के साथ इस सूची को आबाद कर रहा हूं। मैं चाहता हूं कि सूची दृश्य में छिपी हो और पीओएसटी कार्रवाई में पारित हो। बाद में मैं jQuery के साथ इस सूची में और आइटम जोड़ना चाह सकता हूं जो बाद में विस्तार के लिए किसी सरणी को अनुपयुक्त बनाता है। आम तौर पर आप उपयोग करेंगे

@Html.HiddenFor(model => model.MyList)

इस कार्यशीलता को पूरा करने के लिए, लेकिन किसी कारण से POST में सूची हमेशा अशक्त है।

बहुत सरल प्रश्न, किसी को भी पता है कि एमवीसी इस तरह का व्यवहार क्यों करता है?


1
आम तौर पर आप इस तरह से पूरी सूची नहीं छिपाते। <input />S के संदर्भ में आपका वांछित आउटपुट क्या है ?
C

1
क्या होता MyListहै? HiddenForएक समय में केवल एक इनपुट के लिए उपयोग किया जाता है।
डैनियल ए। व्हाइट

1
प्रकार क्या है Model.MyList? आपको मैन्युअल रूप से अपनी सूची में कुछ क्रमांकन / deserialization करने की आवश्यकता हो सकती है।
काइल ट्रुबरमैन


जवाबों:


161

मैं अभी इस मुद्दे पर आया हूं और इसे केवल निम्नलिखित करके हल किया है:

@for(int i = 0; i < Model.ToGroups.Length; i++)
{
    @Html.HiddenFor(model => Model.ToGroups[i])
}

फॉर्च्यूनर के बजाय एक मॉडल का उपयोग करने से मॉडल बाइंडिंग सही ढंग से काम करेगा और सूची में आपके सभी छिपे हुए मूल्यों को उठाएगा। इस समस्या को हल करने का सबसे सरल तरीका लगता है।


5
धन्यवाद! मेरी रात बचाई।
TSmith

7
साभार - अच्छा सरल उपाय बस एक छोटे से मॉड की जरूरत है: ऑब्जेक्ट की आईडी फ़ील्ड को संदर्भित करने की आवश्यकता है। इसलिए यदि इस क्षेत्र को रोव्ड कहा जाता है, तो:@Html.HiddenFor(model => Model.ToGroups[i].RowId)
कृष्णा गुप्ता

3
मेरे लिए काम किया, यहां तक ​​कि जब मेरे पास संग्रह में मॉडल पर कई फ़ील्ड थे। यानी @Html.EditorFor(model => Model.ToGroups[i].Id)जिसके बाद @Html.EditorFor(model => Model.ToGroups[i].Description)दोनों के लिए लूप में - अगली बार पर। और नियंत्रक उन क्षेत्रों के साथ मॉडल की सूची में इसे मैप करने में सक्षम था। और यह सुनिश्चित करने के लिए कि इसमें से कोई भी स्क्रीन पर नहीं दिखाया गया है, बस इसे चारों ओर से <div style="display: none;"></div>
घेरें

प्रतिभाशाली! अच्छी तरह से किया। मेरे लिए काम किया!
एक्सलवैक

3
@ user3186023 यहाँ एक बहुत पुरानी टिप्पणी का उत्तर दे रहा है, लेकिन हो सकता है कि किसी और के पास एक ही मुद्दा होगा: for-लूप को इस पर बदलें :for(int i = 0; i < Model.Departments.Count(); i++)
Stian

28

हिडफ़ॉर डिस्प्लेफ़ॉर या एडिटरफ़ोर की तरह नहीं है। यह संग्रह के साथ काम नहीं करेगा, केवल एकल मान।

आप MVC फ्यूचर्स प्रोजेक्ट में उपलब्ध सीरियलाइज़ HTML हेल्पर का उपयोग किसी हिडन फील्ड में किसी वस्तु को क्रमबद्ध करने के लिए कर सकते हैं, या आपको स्वयं कोड लिखना होगा। एक बेहतर उपाय यह है कि आप किसी प्रकार की आईडी को केवल क्रमबद्ध करें और पोस्टबैक पर डेटाबेस से डेटा को फिर से प्राप्त करें।


आपके पास कोई उदाहरण है? मैंने यह कोशिश की और जब फॉर्म सबमिट किया गया तो यह ViewModel वैल्यू से बंधने में विफल रहा।
एलन मैकडोनाल्ड

@AlanMacdonald - यदि कोई चीज़ बाँधने में विफल हो जाती है, तो यह इसलिए है क्योंकि आपका नामकरण सही नहीं है, संभावना से अधिक क्योंकि आप इंडेक्सर के बजाय फॉरएवर का उपयोग करते हैं। या हो सकता है कि आपने बाइंडिंग में उचित विशेषताओं का उपयोग न किया हो। देखें weblogs.asp.net/shijuvarghese/archive/2010/03/06/...
एरिक Funkenbusch

धन्यवाद। वास्तव में जब मैंने कोशिश की तो यह शाब्दिक रूप से @ Html.Serialize था ("Model.ModelIDs", Model.ModelIDs) जहां मॉडल मेरा ViewModel था और इसमें एक ModelIDs इंट सरणी संपत्ति थी। इसलिए लूप या कुछ भी नहीं थे। जब फॉर्म सबमिट किया गया था तो मॉडलआईडी हमेशा बाध्य व्यूमॉडल में शून्य थे।
एलन मैकडोनाल्ड

@AlanMacdonald - आप नाम में "मॉडल" शामिल नहीं करते हैं।
एरिक फुन्केनबस 18

16

यह एक हैक का एक सा है, लेकिन अगर @Html.EditorForया @Html.DisplayForअपनी सूची के लिए काम करते हैं, इसे का उपयोग करने के लिए पोस्ट अनुरोध पर भेजा आप सुनिश्चित करना चाहते हैं यदि है, लेकिन दिखाई नहीं है, तो आप कर सकता है सिर्फ शैली यह display: none;बजाय इसे छिपाने के लिए, उदाहरण के लिए:

<div style="display: none;">@Html.EditorFor(model => model.MyList)</div>

यह अनुरोध के बाद मॉडल में मूल्य नहीं बचाता है।
जालदेव ev

यदि .EditorFor को सही ढंग से काम करने के लिए सेट किया गया है, तो यह काम करना चाहिए मुझे भी विश्वास है।
मार्क रोड्स

9

ऑब्जेक्ट को एक जोंस स्ट्रिंग में शामिल करने के लिए न्यूटनसॉफ्ट का उपयोग करने के बारे में क्या है और फिर इसे अपने छिपे हुए क्षेत्र में सम्मिलित करें जैसे ( Model.DataResponse.Entity.Commission साधारण "CommissionRange" ऑब्जेक्ट्स की एक सूची है जैसा कि आप JSON में देखेंगे)

@using (Ajax.BeginForm("Settings", "AffiliateProgram", Model.DataResponse, new AjaxOptions { UpdateTargetId = "result" }))
   {
      string commissionJson = JsonConvert.SerializeObject(Model.DataResponse.Entity.Commission);
      @Html.HiddenFor(data => data.DataResponse.Entity.Guid)
      @Html.Hidden("DataResponse_Entity_Commission", commissionJson)
      [Rest of my form]
   }

निम्नानुसार रेंडर करें:

<input id="DataResponse_Entity_Commission" name="DataResponse_Entity_Commission" type="hidden" value="[{"RangeStart":0,"RangeEnd":0,"CommissionPercent":2.00000},{"RangeStart":1,"RangeEnd":2,"CommissionPercent":3.00000},{"RangeStart":2,"RangeEnd":0,"CommissionPercent":2.00000},{"RangeStart":3,"RangeEnd":2,"CommissionPercent":1.00000},{"RangeStart":15,"RangeEnd":10,"CommissionPercent":5.00000}]">

मेरे मामले में मैं वापस पोस्ट करने से पहले छिपे हुए क्षेत्र में जसन को संपादित करने के लिए कुछ JS सामान करता हूं

अपने कंट्रोलर में मैं फिर न्यूट्रोसॉफ्ट का उपयोग फिर से deserialize:

string jsonCommissionRange = Request.Form["DataResponse_Entity_Commission"];
List<CommissionRange> commissionRange = JsonConvert.DeserializeObject<List<CommissionRange>>(jsonCommissionRange);

इसने मेरे लिए काम किया। मैंने सोचा कि यह बहुत साफ था कि स्वीकृत समाधान।
ई-ऑन

6

Html.HiddenForकेवल एक मूल्य के लिए डिज़ाइन किया गया है। छिपे हुए क्षेत्र को बनाने से पहले आपको किसी तरह से अपनी सूची को क्रमबद्ध करना होगा।

उदाहरण के लिए, यदि आपकी सूची टाइप स्ट्रिंग की है, तो आप सूची को अल्पविराम से अलग की गई सूची में शामिल कर सकते हैं, फिर सूची को अपने नियंत्रक में वापस पोस्ट के बाद विभाजित कर सकते हैं।


4

मैंने अभी पता लगाया है (कुछ घंटों के बाद यह पता लगाने की कोशिश कर रहा है कि मॉडल मान नियंत्रक पर वापस क्यों नहीं जा रहे हैं) जिसे संपादकफोर को पालन करना चाहिए।

जब तक मैं कुछ और गलत कर रहा हूं यह मुझे मिला है। मैं दोबारा गलती नहीं करूंगा।

एक मॉडल के संदर्भ में जिसमें किसी अन्य वर्ग की सूची है।

यह काम नहीं करेगा:

        @{
            for (int i = 0; i < Model.Categories.Count; i++)
            {
                <tr>
                    <td>
                        @Html.HiddenFor(modelItem => Model.Categories[i].Id)
                        @Html.HiddenFor(modelItem => Model.Categories[i].ProductCategoryId)
                        @Html.HiddenFor(modelItem => Model.Categories[i].CategoryName)                            
                        @Html.DisplayFor(modelItem => Model.Categories[i].CategoryName)                            
                    </td>
                    <td>
                        @Html.HiddenFor(modelItem => Model.Categories[i].DailyPurchaseLimit)                                                        
                        @Html.EditorFor(modelItem => Model.Categories[i].DailyPurchaseLimit)
                        @Html.ValidationMessageFor(modelItem => Model.Categories[i].DailyPurchaseLimit)
                    </td>
                    <td style="text-align: center">
                        @Html.HiddenFor(modelItem => Model.Categories[i].IsSelected)                            
                        @Html.EditorFor(modelItem => Model.Categories[i].IsSelected)
                    </td>
                </tr>
            }
        }

जहां इस के रूप में होगा ......

            for (int i = 0; i < Model.Categories.Count; i++)
            {
                <tr>
                    <td>
                        @Html.HiddenFor(modelItem => Model.Categories[i].Id)
                        @Html.HiddenFor(modelItem => Model.Categories[i].ProductCategoryId)
                        @Html.HiddenFor(modelItem => Model.Categories[i].CategoryName)                            
                        @Html.DisplayFor(modelItem => Model.Categories[i].CategoryName)                            
                    </td>
                    <td>
                        @Html.EditorFor(modelItem => Model.Categories[i].DailyPurchaseLimit)
                        @Html.HiddenFor(modelItem => Model.Categories[i].DailyPurchaseLimit)                            
                        @Html.ValidationMessageFor(modelItem => Model.Categories[i].DailyPurchaseLimit)
                    </td>
                    <td style="text-align: center">
                        @Html.EditorFor(modelItem => Model.Categories[i].IsSelected)
                        @Html.HiddenFor(modelItem => Model.Categories[i].IsSelected)                            
                    </td>
                </tr>
            }

3

मैंने स्रोत कोड के माध्यम से खुदाई शुरू कर दी है HiddenFor, और मुझे लगता है कि आप जिस सड़क को देख रहे हैं, वह यह है कि आपकी जटिल वस्तु MyListस्पष्ट रूप से टाइप करने के लिए परिवर्तनीय नहीं है string, इसलिए फ्रेमवर्क आपके Modelमान को मानता है nullऔर valueविशेषता को खाली करता है।



3

उसी मुद्दे का सामना किया। लूप के बिना, यह केवल सूची का पहला तत्व पोस्ट करता है। लूप के माध्यम से पुनरावृति के बाद, यह पूरी सूची और पोस्ट को सफलतापूर्वक रख सकता है।

 @if (Model.MyList!= null)
    {
    for (int i = 0; i < Model.MyList.Count; i++)
      {
        @Html.HiddenFor(x => x.MyList[i])
      }
    }

2

एक और विकल्प होगा:

<input type="hidden" value=@(string.Join(",", Model.MyList)) />

यह मेरा भी पहला विचार था। लेकिन मेरे पास एक दृश्य मॉडल था, जिसने MyList क्षेत्र के लिए एक int [] की उम्मीद की थी और अल्पविराम से अलग स्ट्रिंग को MVC बाध्यकारी तंत्र द्वारा एक सरणी में पार्स नहीं किया गया है।
तडेज माली

2

foreachएक के बजाय पाश forपाश एक से थोड़ा क्लीनर समाधान हो सकता है।

@foreach(var item in Model.ToGroups)
{
    @Html.HiddenFor(model => item)
}

1

इसे ठीक करने का एक अन्य संभावित तरीका यह होगा कि आप अपनी सूची की प्रत्येक वस्तु को एक आईडी दें, फिर @Html.DropDownListFor(model => model.IDs)उस सरणी का उपयोग करें और उसे आबाद करें जो आईडी रखती है।


1

शायद देर से, लेकिन मैंने संग्रह से छिपे हुए फ़ील्ड के लिए विस्तार विधि बनाई (सरल डेटा प्रकार आइटम के साथ):

तो यहाँ यह है:

/// <summary>
/// Returns an HTML hidden input element for each item in the object's property (collection) that is represented by the specified expression.
/// </summary>
public static IHtmlString HiddenForCollection<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) where TProperty : ICollection
{
    var model = html.ViewData.Model;
    var property = model != null
                ? expression.Compile().Invoke(model)
                : default(TProperty);

    var result = new StringBuilder();
    if (property != null && property.Count > 0)
    {
        for(int i = 0; i < property.Count; i++)
        {
            var modelExp = expression.Parameters.First();
            var propertyExp = expression.Body;
            var itemExp = Expression.ArrayIndex(propertyExp, Expression.Constant(i));

            var itemExpression = Expression.Lambda<Func<TModel, object>>(itemExp, modelExp);

            result.AppendLine(html.HiddenFor(itemExpression).ToString());
        }
    }

    return new MvcHtmlString(result.ToString());
}

उपयोग के रूप में सरल है:

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