Search code examples
c#asp.net-mvcasp.net-mvc-routing

MVC weird routing behaviour


I have a weird problem with some routing in MVC. Here's my scenario:

  1. The user gets presented to the front page, once visiting the site: testproject.com:57416/Home.
  2. The user has a menu on the left side, with the menu item "Solutions".
  3. The user presses the menu item "Solutions" and the menu item expands, showing 5 sub items.
  4. The user presses the sub item "Demo", and redirects to testproject.com:57416/Solutions/SetLayout?layoutString=page1%7Csize15
  5. As the param layoutString is defined, the grid (DevExpress) know how to filter the data to show.
  6. The grid is presented to the user, and (s)he can now navigate around the grid, manipulating the layout.
  7. The user now wants to see the clean Demo layout again, and (s)he presses the menu item "Solutions" -> sub item "Demo".
  8. The action ActionResult SetLayout(string layoutString) is not hit in this case, but instead the action ActionResult Index() is hit, thereby not setting the layout as the layoutString is not sent in as a param
  9. The url that the user is redirected to, looks like this: testproejct.com:57416/Solutions?undefined=undefined

This might be a bit tiresome to read through, but it's the best way possible for me to explain my scenario as I have never seen anything like this before in MVC. I truly have no idea what's going on, and why the action ActionResult SetLayout(string layoutString) is not hit the second time.

I suppose I should show some code so we can narrow down the possibilities.

_Layout.cshtml (has menu items)

<li class="has-submenu">
    <a href ="#" class="navigation-submenu-toggler show-solution-views">Solutions</a>

    <ul class="nav sub-menu-list">
        <li>
            @Html.ActionLink("Demos", "SetLayout", "Solutions", new { layoutString = "page1|size15" }, null)
        </li>
    </ul>
</li>

ActionResult SetLayout(string layoutString)

public ActionResult SetLayout(string layoutString)
{
    Session["Layout"] = layoutString;
    return RedirectToAction("Index", "Solutions");
}

ActionResult Index()

public ActionResult Index ()
{
    using(var db = new DataBasecontext())
    {
        var list = db.Solutions.ToList();
        return View(list);
    }
}

EDIT

I've found out that this only happens when I'm inside the same controller. The controller holding the action ActionResult SetLayout(string layoutString) is the SolutionsController. If I'm coming from, let's say the AccountController everything works fine, but changing from SolutionsController to another action in the SolutionsController doesn't work.

Come to think of it, could have something to do with my map routes?

routes.MapRoute(
    name: "ControllerIdActionId",
    url: "{controller}/{id}/{action}/{id2}",
    default : new { id2 = UrlParameter.Optional }
);

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

routes.MapRoute(
    name: "Solutions",
    url: "{controller}/{id}/{action}",
    default : new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Solution

  • I managed to solve the problem on my own.

    I'm not quite sure what the issue was, but changing the Html.ActionLink() into Html.RouteLink()'s I was able to define what MapRoute to use.

    I solved it by using the following MapRoute

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    )
    

    I could then use the Html.RouteLink like so:

    Html.Routelink("Demos",                       //Display text
                   "Default",                     //The MapRoute to use
            new { layoutString = "page1|size15|", //The param (layoutString)
                  controller = "Solutions",       //The controller
                  action = "SetLayout" })         //The action
    

    I made no changes to the action:

    public ActionResult SetLayout(string layoutString)
    {
        Session["Layout"] = layoutString;
        return RedirectToAction("Index", "Solutions");
    }