MVC model binding naming convention for child obje

2019-04-10 10:23发布

问题:

I'm having trouble with default model binding naming convention when there is a child property. For example:

I have a ViewModel which looks something like this:

public class UserViewModel
{
    public User BusinessObject { get; set; }
}

My User class has a property called "NetworkLogin"

My View has something like this: <%: Html.LabelFor(model => model.BusinessObject.NetworkLogin)%> <%: Html.TextBoxFor(model => model.BusinessObject.NetworkLogin)%> Auto-Fill

And my controller, what I'd like to do, is

    [HttpGet]
    public ActionResult UserIndex(string networkLogin) { }

The problem: The input parameter "networkLogin" is always null. This makes sense, because the actual parameter on the html element is name="BusinessObject.NetworkLogin" and id="BusinessObject_NetworkLogin". However, I don't know what parameter name I should use in my action method. I've tried "businessObject_NetworkLogin" and it doesn't work either.

However, I have this workaround that does work, but I don't like it. I add this to my ViewModel:

    public string NetworkLogin
    {
        get
        {
            if (BusinessObject == null)
                BusinessObject = new User(); 
            return BusinessObject.NetworkLogin;
        } 
        set
        {
            if (BusinessObject == null)
                BusinessObject = new User();
            BusinessObject.NetworkLogin = value;
        }
    }

And my View page now says this instead. <%: Html.TextBoxFor(model => model.NetworkLogin)%>

Can someone tell me what the proper naming convention is for default model binding so that I don't have to employ the above workaround?

Thank you!

回答1:

Indicate the prefix so that the model binder knows that the BusinessObject.NetworkLogin query string parameter actually refers to networkLogin which is what you use as action argument

public ActionResult UserIndex(
    [Bind(Prefix = "BusinessObject")] string networkLogin
) 
{ 
    ...
}

or reuse your view model:

public ActionResult UserIndex(UserViewModel model) 
{ 
    // TODO: use model.BusinessObject.NetworkLogin
    // which is gonna be correctly bound here
    ...
}

As far as your workaround is concerned, once you put one of my two suggestions into action your view model property should really look like this:

public string NetworkLogin { get; set; }