Possible to have Guid as an optional parameter in asp.net mvc 3 controller action?

andryuha picture andryuha · Mar 1, 2011 · Viewed 19.3k times · Source

I was trying to have an index action on a controller to optionally take a guid like so:

public ActionResult Index(Guid id = default(Guid))

or like so

public ActionResult Index(Guid id = new Guid())

I was hoping to take advantage of C#'s optional parameters and my routes are also defined optional parameters:

routes.MapRoute(
    "Default", "{controller}/{action}/{id}",
     new { controller = "somecontroller", action = "Index", id = UrlParameter.Optional }

but calling "somecontroller/index" gives following error...

The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Guid' for method 'System.Web.Mvc.ActionResult Index(System.Guid)' in 'Controllers.SomeController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter

is it just not possible? What am I missing? Thanks

Answer

Scott Anderson picture Scott Anderson · Mar 1, 2011

A Guid is not nullable. For example you can't do this

Guid myGuid = null;  // invalid

However, in C# 2, some syntactic sugar was added to make value types nullable (by wrapping them in a Nullable object), like so:

Guid? myGuid = null; // valid.  myGuid will be Nullable<Guid>.

Given that rule, let's take a look at your route:

routes.MapRoute(
    "Default", "{controller}/{action}/{id}",
    new { controller = "somecontroller",
        action = "Index",
        id = UrlParameter.Optional // <-- Optional!!
    });

Since you specified in your route that the id parameter is optional, you must use a type that can be null, or you must omit the parameter completely in your action. So to fix your action, you need to change the Guid id parameter to be Guid? id and it should work. After that, you can check the value to make sure it's not null like so:

public ActionResult Index(Guid? id) {
    if (id.HasValue) {
        // it's not null, so I can call "id.Value" to get the Guid
    }
}