7

I have a following types of url used in my Application.

localhost/admin/userdetail/id

localhost/admin/userdetail/id/true

localhost/admin/userdetail/id/true/success

Here is my Admin Controller

bool inSaveAction, string status are optional

    [Authorize]
    public ActionResult UserDetail(string Id, bool inSaveAction, string status)
    {
    }

    [HttpPost, Authorize, ValidateAntiForgeryToken]
    public ActionResult SaveUserDetail(UserDetailViewModel viewModel)
    {
        User userToSave = new User();
        AdminService.UpdateUser(userToSave);
        //This is calling the above function as it sending all 3 params
        return RedirectToAction("UserDetail", new { Id = viewModel.Id, 
                           inSaveAction = true, status = "success" });
    }

Below case is not working

  @Html.ActionLink("DisplayName", "UserDetail", new { id = Model.Id })

In Global.asax

 routes.MapRoute("UserDetail",
            "UserDetail/{id}",
            new
            {
                controller = "Admin",
                action = "UserDetail",
                id = UrlParameter.Optional
            }
         );

I followed http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx

How can i make inSaveAction & status as optional parameter for my UserDetail action?

Murali Murugesan
  • 22,423
  • 17
  • 73
  • 120

1 Answers1

9

You're missing the parameters in your route config. In order to make this work with different parameters optional (as in Phil Haack's post), you need to define multiple routes

routes.MapRoute("UserDetail-WithStatus", 
                "UserDetail/{id}/{inSaveAction}/{status}", 
                 new
                 {
                     controller = "Admin",
                     action = "UserDetail",
                     // nothing optional 
                 }
);

routes.MapRoute("UserDetail-WithoutStatus", 
                "UserDetail/{id}/{inSaveAction}", 
                 new
                 {
                     controller = "Admin",
                     action = "UserDetail",
                     // nothing optional 
                 }
);

routes.MapRoute("UserDetail-WithoutSaveAction", 
                "UserDetail/{id}", 
                 new
                 {
                     controller = "Admin",
                     action = "UserDetail",
                     id = UrlParameter.Optional
                 }
);

And then create links with:

@Html.ActionLink("Link", "Index", "Admin", new { id = 1, inSaveAction = true, success = "success" }, null)

You'll also need to set the optional parameters as nullable, otherwise you'll get exceptions if id or inSaveAction are missing.

public ActionResult UserDetail(int? id, bool? inSaveAction, string status)
{

}
mfanto
  • 14,168
  • 6
  • 51
  • 61
  • I Tried with the code you give. This also not working. Its not taking to the action method. Any problem in routing or action method params? – Murali Murugesan Jan 05 '13 at 08:10
  • I just posted an edit, you'll need to make id and inSaveAction nullable. What's not working though? I tested this and all the routes work. – mfanto Jan 05 '13 at 08:12
  • Thanks. status also optional only. – Murali Murugesan Jan 05 '13 at 08:13
  • Sorry, what do you mean? Can you verify the routes work? Set a breakpoint in your UserDetail action, and then try the urls /Admin/UserDetail/1, /Admin/UserDetail/1/true, /Admin/UserDetail/1/true/success. All should work, with the respective parameters set. – mfanto Jan 05 '13 at 08:15
  • In all the cases i have to pass the Id. So can we remove the last route saying optional parameter? – Murali Murugesan Jan 05 '13 at 08:20
  • You shouldn't need the id if you mark it nullable (int? id). The id = UrlParameter.Optional means that it's not required to match the route. So the last route will match /Admin/UserDetail and /Admin/UserDetail/id. One thing you might find helpful is Route Debugger. It'll show you which route parameters are being matched http://nuget.org/packages/routedebugger – mfanto Jan 05 '13 at 08:25
  • I didnot write Controller Name and page had erro,,,routes.MapRoute("MyRoute", "Learn14/{id}/{name}", new { controller="Home", action="Learn14"}); Why?? – Hamid Bahmanabady Apr 11 '14 at 14:18