2012-02-21 13 views
63

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

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

का उपयोग करेंगे, लेकिन किसी कारण से पोस्ट में सूची हमेशा शून्य होती है।

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

+0

आम तौर पर आप इस तरह की संपूर्ण सूचियों को छिपा नहीं पाएंगे। ' के संदर्भ में आपका वांछित आउटपुट क्या है? –

+0

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

+0

'मॉडल। MyList' किस प्रकार का है? आपको मैन्युअल रूप से अपनी सूची में कुछ क्रमिकरण/deserialization प्रदर्शन करने की आवश्यकता हो सकती है। –

उत्तर

91

मैं सिर्फ इस समस्या का सामना करते हैं और बस नीचे दिए तरीके से इसका समाधान कर लिया:

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

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

+0

धन्यवाद! मेरी रात बचा लिया – TSmith

+5

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

+2

मेरे लिए काम किया, यहां तक ​​कि जब मेरे पास संग्रह में मॉडल पर एकाधिक फ़ील्ड थे। अर्थात। '@ एचटीएमएल.एडिटरफॉर (मॉडल => मॉडल। समूह समूह [i] आईडी) '@ एचटीएमएल.एडिटरफॉर (मॉडल => मॉडल। समूह समूह [i] डिस्क्रिप्शन) के बाद अगली बार - दोनों के लिए- पाश। और नियंत्रक इसे उन क्षेत्रों के साथ मॉडल की सूची में मैप करने में सक्षम था। और यह सुनिश्चित करने के लिए कि इसमें से कोई भी स्क्रीन पर दिखाई नहीं दे रहा है, बस इसे '

' – mmcrae

5

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

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

27

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

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

+0

क्या आपके पास एक उदाहरण है ? मैंने यह कोशिश की और फ़ॉर्म सबमिट होने पर व्यूमोडेल मूल्य से जुड़ने में असफल रहा। –

+0

@AlanMacdonald - अगर कुछ बांधने में विफल रहता है, तो ऐसा इसलिए है क्योंकि आपका नामकरण सही नहीं है, संभावना से अधिक है क्योंकि आपने इंडेक्सर के बजाय एक foreach का उपयोग किया था। या हो सकता है कि आपने बाध्यकारी में उचित विशेषताओं का उपयोग नहीं किया हो। Http://weblogs.asp.net/shijuvarghese/archive/2010/03/06/persisting-model-state-in-asp-net-mvc-using-html-serialize.aspx –

+0

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

1

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

2

आप इस solution पर एक नज़र डाल सकते हैं।

संपादक टेम्पलेट के अंदर केवल छुपाएं रखें। @Html.EditorFor(model => model.MyList)

यह काम करता है चाहिए:

और अपने दृश्य में इस डाल दिया।

12

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

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

यह अनुरोध के पोस्ट पर मॉडल में मान को सहेजता नहीं है। – nldev

+0

यदि .ditorFor सही तरीके से काम करने के लिए स्थापित किया गया है, तो यह भी काम करना चाहिए मुझे विश्वास है। –

0

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

3

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

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

किसी मॉडल के संदर्भ में जिसमें किसी अन्य श्रेणी की सूची शामिल है।

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

 @{ 
      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> 
      } 
6

क्या एक json स्ट्रिंग में वस्तु deserialize और फिर सम्मिलित है कि में करने के लिए Newtonsoft उपयोग के बारे में आपका छिपे हुए क्षेत्र उदा

@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] 
    } 

रेंडर (Model.DataResponse.Entity.Commission एक वस्तुओं सरल "CommissionRange" की सूची के रूप में आप JSON में देखेंगे) के रूप में:

<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}]"> 

मेरे मामले में मैं

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

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

यह मेरे लिए काम करता है। मैंने सोचा कि यह बहुत साफ है कि स्वीकार्य समाधान –

0

शायद देर से (सरल डेटा प्रकार वस्तुओं के साथ), लेकिन मैं संग्रह से छिपा क्षेत्रों के लिए विस्तार विधि बनाया: तो यहाँ

यह है: Newtonsoft फिर deserialize करने के लिए उपयोग

/// <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) 
2

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

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