Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC model binding naming convention for child objects?

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!

like image 396
Raymond Avatar asked Dec 21 '22 13:12

Raymond


1 Answers

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; }
like image 92
Darin Dimitrov Avatar answered Dec 28 '22 11:12

Darin Dimitrov