Search code examples
asp.net-mvcasp.net-mvc-5asp.net-mvc-routingmodel-binding

Binding parameter to complex type


I have a navigation bar, with several links, like this:

<a href="MyController/Browse/2">MenuItem1</a>

This request would hit my action method:

public ActionResult Browse(int departmentId)
{
    var complexVM = MyCache.GetComplexVM(departmentId);
    return View(complexVM);
}

This is my ComplexVM:

public class ComplexVM 
{
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
}

MyCache, is a static list of departments, which I am keeping in memory, so when user passes in DepartmentId, I wouldn't need to get the corresponding DepartmentName from DB.

This is working fine... but it would be nice if I could somehow initialize ComplexVM in custom model binder, instead of initializing it in the Controller... so I still want to use a link (menu item), but this time, a CustomModelBinder binds my parameter, 2, to ComplexVM: it needs to look up the name of department with id = 2 from MyCache and initialize ComplexVM, then ComplexVM would be passed to this action method:

public ActionResult Browse(ComplexVM complexVM)
{
    return View(complexVM);
}

I want to hit the above controller without doing a post-back, as I have a lot of menu item links in my navigation bar... not sure if this is possible? Or if this is even a good idea?

I have seen this link, which sort of describes what I want... but I am not sure how the routing would work... i.e. routing id:2 => ComplexVM


Alternatively would it be possible to do this in RouteConfig, something like this:

routes.MapRoute(
    name: "Browse",
    url: "{controller}/Browse/{departmentId}",
    // this does not compile, just want to explain what I want...
    defaults: new { action = "Browse", new ComplexVM(departmentId) });

Solution

  • I can achieve this with little change and with one trick

    <a href="MyController/Browse?id=1">MenuItem1</a>
    

    Controller action

    public ActionResult Browse(ComplexVM complexVM)
    {
    return View(complexVM);
    }
    

    View model

    public class ComplexVM
    {
        public int DepartmentId { get; set; }
        public string DepartmentName { get; set; }
        public ComplexVM()
        {
            this.DepartmentId = System.Convert.ToInt32(HttpContext.Current.Request("id").ToString);
            this.DepartmentName = "Your name from cache"; // Get name from your cache 
        }
    }
    

    This is without using model binder. Trick may help.