MVC3 Html.Editor targeting dictionary is not binding down to the client

寵の児 提交于 2019-12-14 02:59:17

问题


My view model is along the lines of

EditViewModel
    SomeUserType User
        Dictionary<string, string> Claims

In my view I'm trying to bind this as follows

@{
    int i = 0;
    foreach (var key in Model.User.Claims.Keys)
    {                                                                       
            <div class="editor">
                <input type="hidden" value="@i" name="User.Claims.Index">
                <div class="editor-label">
                    @Html.Label(string.Format("User.Claims[{0}].Key", i))
                </div>
                <div class="editor-field">
                    @Html.Editor(string.Format("User.Claims[{0}].Key", i))
                </div>
                <div class="editor-label">
                    @Html.Label(string.Format("User.Claims[{0}].Value", i))
                </div>
                <div class="editor-field">
                    @Html.Editor(string.Format("User.Claims[{0}].Value", i))
                </div>
            </div>    
        i++;
    }
}

Which renders out the series of Key Value pair text boxes on the edit screen as I would expect. However the text boxes are always empty even though there are KeyValuePairs in the Claims dictionary.

If I fill in values for the KVP text boxes and post the form back to my controller I do get the values correctly model bound back into my User.Claims Dictionary.

What am I missing that is preventing the binding from having the correct values in it as the view loads?

Edit: Additional information, basically I'm trying to figure out how exactly this works for MVC inherently. I created my view above directly from the core MVC (2) object template that Brad Wilson discusses here. I tried to find the exact code for this in Razor but I couldn't find it at all anywhere... digressing... Converting this to Razor I ended up with

@if (ViewData.TemplateInfo.TemplateDepth > 4) 
{
    @ViewData.ModelMetadata.SimpleDisplayText
}
else
{
    <div class="editor">    
        @foreach (var prop in ViewData.ModelMetadata.Properties
            .Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm)))
        {                        

            if (prop.HideSurroundingHtml)
            {
            @Html.Editor(prop.PropertyName)
            }
            else
            {
                if (!String.IsNullOrEmpty(Html.Label(prop.PropertyName)
                                                            .ToHtmlString()))
                {
                    <div class="editor-label"> @Html.Label(prop.PropertyName) 
                    </div>
                }

                <div class="editor-field">
                    @Html.Editor(prop.PropertyName)
                    @Html.ValidationMessage(prop.PropertyName)
                </div>            
            }
        }
    </div>    
}

The main difference is the edit to the @if (ViewData.TemplateInfo.TemplateDepth > 4) which will allow MVC to dive deep enough that it reaches my dictionary it can then bind everything correctly. However upon further interrogation with debugging I see when it binds the Key property it actually sees just @Html.Editor("Key") how does this work?

Clearly Editor must have some kind of knowledge of ViewData.ModelMetadata.Properties and however it determines ViewData.TemplateInfo.Visited()'s result that it's able to correctly place the right stuff, just at this point I'm at a loss of what's happening behind the scenes that somehow inside of this foreach loop that @Html.Editor("Key") does ANYTHING.


回答1:


@Html.Editor(string name) will generate editor for field name in ViewData. If ViewData not contains your object, you must used another overload: @Html.Editor(string name, object viewData).

In your case, you can replace @Html.Label(string.Format("User.Claims[{0}].Key", i)) with @Html.Label(string.Format("User.Claims[{0}].Key", i),User.Claims[i].Value)




回答2:


Try like this:

@{
    var i = 0;
    foreach (var key in Model.User.Claims.Keys)
    {
        <div class="editor">
            <input type="hidden" value="@i" name="User.Claims.Index" />
            <div class="editor-label">
                @Html.Label(string.Format("User.Claims[{0}].Key", i))
            </div>
            <div class="editor-field">
                @Html.TextBox(string.Format("User.Claims[{0}].Key", i), key)
            </div>
            <div class="editor-label">
                @Html.Label(string.Format("User.Claims[{0}].Value", i))
            </div>
            <div class="editor-field">
                @Html.TextBox(string.Format("User.Claims[{0}].Value", i), Model.User.Claims[key])
            </div>
        </div>            
        i++;
    }
}



回答3:


   @{
 foreach (KeyValuePair<string, string> item  in Model.ShippingCarrier)
 {
    <tr>
    <td>
   @Html.TextBox(item.Key.ToString(), item.Key, new { @class = "w50" }) : @Html.TextBox(item.Key.ToString(), item.Key, new { @class = "w50" }) 
    </td>
   </tr>

 }
    }


来源:https://stackoverflow.com/questions/5424643/mvc3-html-editor-targeting-dictionary-is-not-binding-down-to-the-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!