2010-10-17 16 views
8

मैं एक सूची है कि कस्टम मॉडल बांधने की मशीन का सहारा के बिना एक बड़ा दृश्य मॉडल का हिस्सा है बाध्य करने के लिए प्रयास कर रहा हूँ में IList बाइंडिंग। जब मैं इनपुट की सूची बनाने के लिए एक संपादक टेम्पलेट का उपयोग करता हूं, तो जेनरेट किए गए नाम काम करने के लिए डिफ़ॉल्ट बाइंडर के सही प्रारूप में नहीं होते हैं।ASP.NET MVC मॉडल एक संपादक खाका

आइटम [3] .id जैसे मैं इसे आइटम है उम्मीद करेंगे के बजाय

। [3] .id। अगर मैं एक संपादक टेम्पलेट के बिना सूची का निर्माण करता हूं तो यह अपेक्षित के रूप में काम करता है।

मैं स्पष्ट रूप से गलत कुछ कर रही हूँ या यह सिर्फ Html.Hidden और Html.TextBox के एक मोड़ है?

public class ItemWrapper 
{ 
    [UIHint("ItemList")] 
    public IList<Item> Items { get; set; } 
} 

public class Item 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public int Value { get; set; } 
} 

index.aspx

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 

    <h2>Index</h2> 

    <% using(Html.BeginForm()) 
    {%> 
    <%:Html.EditorFor(m => m.Items) %> 
    <%}%> 
</asp:Content> 

ItemList.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IList<Mvc2Test.Models.Item>>" %> 

<h4>Asset Class Allocation</h4> 
<% if(Model.Count > 0) { %> 
<table> 
    <tbody> 
    <% for(int i = 0; i < Model.Count; i++) 
    {%> 
     <tr> 
     <td><%: Model[i].Name%></td> 
     <td> 
      <%: Html.HiddenFor(m => m[i].Id) %> 
      <%: Html.TextBoxFor(m => m[i].Value) %> 
     </td> 
     </tr> 
    <%}%> 
    </tbody> 
</table> 
<% 
}%> 

आउटपुट

<tr> 
    <td>Item 4</td> 
    <td> 
    <input id="Items__3__Id" name="Items.[3].Id" type="hidden" value="f52a1f57-fca8-4bc5-a746-ee0cef4e05c2" /> 
    <input id="Items__3__Value" name="Items.[3].Value" type="text" value="40" /> 
    </td> 
</tr> 

संपादित (कार्रवाई विधि)

public ActionResult Test() 
{ 
    return View(
    new ItemWrapper 
    { 
     Items = new List<Item> 
     { 
     { new Item { Id = Guid.NewGuid(), Name = "Item 1", Value = 10 } }, 
     { new Item { Id = Guid.NewGuid(), Name = "Item 2", Value = 20 } }, 
     { new Item { Id = Guid.NewGuid(), Name = "Item 3", Value = 30 } }, 
     { new Item { Id = Guid.NewGuid(), Name = "Item 4", Value = 40 } } 
     } 
    }); 
} 

# संपादित 2

HttpPost कार्रवाई

[HttpPost] 
public ActionResult Test(ItemWrapper w) 
{ 
    if(w.Items == null) 
     Response.Write("Items was null"); 
    else 
     Response.Write("Items found " + w.Items.Count.ToString()); 
    return null; 
} 

index.aspx

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 

<h4>Does Not Work</h4> 
<% using(Html.BeginForm("Test", "Home")) 
{%> 
     <%:Html.EditorFor(m => m.Items) %> 
     <input type="submit" value-"Go" /> 
<%}%> 

<h4>Does Work</h4> 
     <% using(Html.BeginForm("Test", "Home")) 
     {%> 
    <table> 
     <tbody> 
      <% for(int i = 0; i < Model.Items.Count; i++) 
      {%> 
      <tr> 
       <td><%: Model.Items[i].Name%></td> 
       <td> 
        <%: Html.HiddenFor(m => Model.Items[i].Id) %> 
        <%: Html.TextBoxFor(m => Model.Items[i].Value) %> 
       </td> 
      </tr> 
      <%}%> 
     </tbody> 
    </table> 
      <input type="submit" value-"Go" /> 
     <%}%> 

</asp:Content> 

उत्तर

7

मैं आपकी समस्या को समझ लिया है, और मैं बहुत अच्छी तरह से एक समाधान भी हो सकता है :)!

सबसे पहले, मुझे आपको बताएं कि मैंने framework's source code का निरीक्षण करके क्या सीखा है (यह हमेशा एक अच्छा विचार है कि एक ओपनसोर्स प्रोजेक्ट के स्रोत कोड का निरीक्षण करना बेहतर होगा ताकि यह समझ सके कि कुछ चीजें कैसे काम करती हैं)।

1-) जब सरल उपयोग करने की सशक्त एचटीएमएल सहायकों द्वारा लिखा गया (यानी सभी Html.xxxFor (...) EditorFor और DisplayFor) को छोड़कर तरीकों, लैम्ब्डा अभिव्यक्ति में मॉडल की संपत्ति को परिभाषित रेंडर करने के लिए, उत्पन्न HTML तत्व का नाम है जो कुछ इस प्रकार है स्ट्रिंग के बराबर है "मॉडल =>", शून्य से क्या पहले "=>", ऐसा कहा जा सकता है आता है:

  • स्ट्रिंग "मॉडल" मॉडल एक संग्रह
  • या स्ट्रिंग "मॉडल है यदि। "(अंत में" "अंत में)।

तो, उदाहरण के लिए करें:

<input type="text" name="OneProperty.OneNestedProperty" ../> 

और यह:

:

<%: Html.TextBoxFor(m=>m[0].OneProperty.OneNestedProperty)%> 

इस उत्पन्न होगा

<%: Html.TextBoxFor(m=>m.OneProperty.OneNestedProperty)%> 

इस एचटीएमएल उत्पादन उत्पन्न होगा

<input type="text" name="[0].OneProperty.OneNestedProperty" ../> 

==> यह आंशिक रूप से बताता है कि संपादकफ़ोर का उपयोग करते समय आपको यह "अजीब" HTML आउटपुट क्यों मिला है।

2-)जटिल दृढ़ता से टाइप किया सहायकों (EditorFor और DisplayFor), एक ही पिछले नियम आपके मामले में जुड़े आंशिक दृश्य के अंदर लागू किया जाता है (ItemList.ascx) का उपयोग कर, और में इसके अलावा, सभी सृजित HTML तत्वों क्या के बाद "==>" आता लगाया जाता, के रूप में 1-) में विस्तार से बताया हो जाएगा।

उपसर्ग यहाँ है "। आइटम", क्योंकि आप अपने लिखा जाता है (index.aspx) ध्यान में रखते हुए इस राशि:

<%:Html.EditorFor(m => m.Items) %> 

==> यह पूरी तरह से उत्पादन, और क्यों डिफ़ॉल्ट बताते हैं बांधने की मशीन आइटम की अपनी सूची के साथ अब और काम नहीं करता है

समाधान नीचे को तोड़ने के लिए किया जाएगा आपके ItemWrapper में पैरामीटर [HttpPost] विधि, उसके गुण में, और उसके बाद बाइंड गुण उसकी उपसर्ग पैरामीटर के साथ प्रत्येक जटिल संपत्ति के लिए इस तरह का उपयोग करें,:

[HttpPost] 
    public string Index(string foo,[Bind(Prefix = "Items.")]IList<Item> items) 
    { 
     return "Hello"; 
    } 

(मान ItemWrapper भी है कि एक सरल प्रकार स्ट्रिंग की फू) नाम दिया संपत्ति

संघर्ष से बचने के लिए जब पोस्ट विधि में गुण लिस्टिंग, मैं दृढ़ता से आप ईए के अनुसार अपने मानकों को नाम के लिए सलाह देते हैं ch संपत्ति का नाम (मामला कोई मामला नहीं) जैसा मैंने किया था।

आशा इस में मदद मिलेगी!

+0

तो यह वास्तव में जिस तरह से MVC उत्पन्न फ़ील्ड नाम में एक मोड़ है। आंशिक दृश्य इस बात पर विचार नहीं कर रहा है कि फ़ील्ड नाम उत्पन्न करते समय मॉडल संग्रह होता है। मुझे लगता है कि आइटम।आंशिक दृश्य स्तर की बजाय दृश्य स्तर पर बनाया गया है, तो इसे ठीक करने का एक अच्छा तरीका नहीं हो सकता है। धन्यवाद। –

+0

कोंडोटिन: एएसपीएनटी एमवीसी बग की तरह लगता है, क्या किसी ने अभी तक इसकी सूचना दी है? – Wout

+0

ठीक है, मैंने खुद की सूचना दी: http://aspnet.codeplex.com/workitem/7711, कृपया इस बग फिक्स के लिए वोट दें! – Wout

-1

एक और अधिक आलसी समाधान सिर्फ क्रम में इस तरह की घटनाओं को "ठीक" में jQuery का उपयोग करने के लिए है। बस पृष्ठ (या आंशिक पेज) के बाद निम्नलिखित समारोह चलाने भार:

function makeHiddenInputBindable() { 
    $('input[type="hidden"]').each(
     function (i) { 
      $(this).attr('name', function() { 
       return this.name.replace(/\.\[/g, "["); 
      }) 
     } 
    ); 
} 
+1

टूटी हुई HTML को फिर से काम करने के लिए jQuery को क्रैच के रूप में उपयोग नहीं किया जाना चाहिए। इसे सर्वर की तरफ ठीक करें। –