2

I've got a very basic ASP.Net MVC project where I'd like to use a parameter name of id on one of my controller actions. From everything I've read that shouldn't be a problem but for some reason using a parameter name of id fails to get the value extracted from the query string but if I change it to any other different name it will work.

I only have a single route in my global.asx

routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);

My controller method is:

public ActionResult Confirm(string id)
{
     ....
}

A URL of http://mysite/customer/confirm/abcd works. A URL of http://mysite/customer/confirm?id=abcd fails.

If I change the controller method to:

public ActionResult Confirm(string customerID)
{
     ....
}

then a URL of http://mysite/customer/confirm?customerID=abcd works.

Is there something special about using "id" as a parameter in an ASP.Net MVC query string?

Update: Changed id from 1234 to abcd, my id's are actually strings.

sipsorcery
  • 30,273
  • 24
  • 104
  • 155
  • I'm guessing the default value "" for the "id" route value is used *before* the id you supply in the query string, since "confirm?id=" only matches the first two route values (controller and action). The question is; why do you want URLs like "confirm?id="? It is bound to cause confusion; not just for the URL routing module. :) – bzlm Jan 27 '10 at 10:31
  • I was hoping to be able to keep the URL format I had pre MVC which used id in the querystring. – sipsorcery Jan 27 '10 at 10:33
  • @sipwiz that approach may cause subtle problems. If you use MVC to generate links, it won't be an issue - things like `HtmlHelper.ActionLink` are route aware, which means a link to the `Confirm` action method with id = 1 as a route value would be rendered as `/Confirm/1`, not as `Confirm?id=1`. Do you need to support legacy incoming links, even for confirmations? Then see here: http://stackoverflow.com/questions/817325/asp-net-mvc-routing-legacy-urls-passing-querystring-ids-to-controller-actions – bzlm Jan 27 '10 at 10:57
  • `{id}` should be removed from route, then when creating the link, `new { id=1 }` should be added into the `HtmlHelper.ActionLink` to propagate it to query string. I don't know then param name now. – stej Jan 27 '10 at 11:05
  • @stej that will remove the support for proper MVC links, and only allow legacy links. It's a bit more complicated than that. :) – bzlm Jan 27 '10 at 12:06
  • @bzlm sipvwiz wrote: 'I was hoping to be able to keep the URL format I had pre MVC which used id in the querystring.' That means that he does want to use query string, doesn't he. – stej Jan 27 '10 at 13:01

2 Answers2

1

If you need to have id in query string, then don't create route with 'id' parameter. In case you have route "{controller}/{action}" then you can use public ActionResult Confirm(string id) as your controller method.

Routes don't care about query strings.

stej
  • 28,745
  • 11
  • 71
  • 104
1

If you do not apply an id parameter (either querystring or POST), the system just ignores it, and you can remove the "id" parameter in your controller:

public ActionResult Confirm()

In your case, you would just stick with the id parameter. Why make an ugly customerID parameter, when id is "mapped" automatically?

This is an easy and simple example of the use of id parameter.

public ActionResult Confirm(int? id)
{
     if (id.HasValue && id.Value > 0) // check the id is actually a valid int
         _customerServer.GetById(id.Value);

    // do something with the customer

    return View();
}

This works too, for me. We're doing it in our application right now with a standard route:

public ActionResult Confirm(string id)
{
     if (!string.IsNullOrEmpty(id)) // check the id is actually a valid string
         _customerServer.GetByStringId(id);

    // do something with the customer

    return View();
}
Kordonme
  • 2,314
  • 3
  • 20
  • 32
  • 1
    That's effectively what I tried with Confirm(string id). The MVC engine works with id being an int? but not a string for some reason. – sipsorcery Jan 27 '10 at 11:15
  • But you specified an example of the id being 1234 - that's an int :-) You could also make it "int id". Then it's not nullable. But, regardless, it should still work with the "id" being a string. I've updated the answer. – Kordonme Jan 27 '10 at 11:26
  • Are you able to use both URL formats: customer/confirm/abcd and customer/confirm?id=abcd if so what do you have for your route in global.asx? – sipsorcery Jan 27 '10 at 11:31
  • No, I'm not able to do that. You're not able to use the names of the parameters, you're using in the global.asax as querystring parameters, too. But /customer/confirm/1234 looks a lot better ;-) – Kordonme Jan 27 '10 at 11:44