views:

89

answers:

3

Hey Y'all..

Trying to get started with MS's implementation of MVC and I'm already in a jam..

I have a have a route like so:

  routes.MapRoute( "Custom", // Route name
           "RightHere/{entryDate}", // URL with parameters
           new { controller = "RightHere", action = "GetDate" } // Parameter defaults

           );

And the corresponding controller action (RightHereController) looks like so:

 public ActionResult GetDate(DateTime date)
    {


             try
             {
                 ViewData["Date"] = date;
                 return View();
             }
             catch
             {
                 return View();
             }
    }

The view:

<h2>RightHere</h2>
<p><%= Html.Encode(ViewData["Date"]) %></p>

Simple enough.. But get the orange screen of death when using URL /RightHere/GetDate/1-1-2009

:

The parameters dictionary contains a null entry for parameter 'date' of non-nullable type 'System.DateTime' for method 'System.Web.Mvc.ActionResult GetDate(System.DateTime)'

Need you more tenured Ms MVC peps tell me what I'm missing :)

A: 

The problem lies with your Route mapping.

You're trying to access URL /RightHere/GetDate/{entryDate}, but you have defined your mapped route as /RightHere/{entryDate}. You can either add "/GetDate" to your route or remove it from the URL you are testing.

What gives this away is the error message. At first, I thought there was an issue with the ViewData dictionary somehow not having a Date key. However, the error message refers to the controller action and the parameters collection. This means the error occurs before a View is returned/executed.

EDIT: Route mapping is tricky. Please remember that the best-matched route DOES NOT necessarily win the day. The order in which you add a route mapping is the order evaluated at runtime. The very first route that matches the URL requested will be used.

David Andres
+2  A: 

You actually have two problems. The first problem is that the URL you mentioned above doesn't match the route you created. The second problem lies with your route and your action not quite matching.

You have this for the URL in your question:

/RightHere/GetDate/1-1-2009

It needs to be this:

/RightHere/1-1-2009

If you want it to be the latter, then you need to change your route to this:

routes.MapRoute(
    "Custom", 
    "RightHere/GetDate/{entryDate}", 
    new { controller = "RightHere", action= "GetDate" }
);

You have this for your action:

public ActionResult GetDate(DateTime date)
{
    ...
}

It needs to be this, to match your route:

public ActionResult GetDate(DateTime entryDate)
{
    ...
}

Other than that, you're good to go. Just make sure you have the route at the top, above the default route. I can recommend one other thing that would help is by adding a constraint to your route, for example:

routes.MapRoute(
    "Custom", 
    "RightHere/{entryDate}", 
    new { controller = "RightHere", action= "GetDate" }, 
    new { entryDate = @"\d{2}-\d{2}-\d{4}"}
);

This makes sure that the entry date passed in, is in the correct format.

Dale Ragan
Thanks for this!
Nick
I still find is necessary to form my URL with the action identified:RightHere/GetDate/1-1-2009I have my route like you suggested. If I don't add the "GetDate" action in the URL I get a 404. Am I still missing something?
Nick
Which route above in my answer did you use, there are two? If you use the bottom one, then GetDate is not required. If you used the top one, then it is required.
Dale Ragan
A: 

The issue is because you defined the datetime as 'entryDate' in your route but then in your action you've got it defined as 'date'.

I haven't tested binding datetimes in routes but try changing your action to this:

public ActionResult GetDate(DateTime entryDate)

Also, the url you're calling it from doesn't need the action in it, so use this url: /RightHere/1-1-2009

If that doesn't work I would suggest using this approach:

routes.MapRoute(
    "Custom", // Route name
    "RightHere/{year}/{month}/{day}", // URL with parameters
    new { controller = "RightHere", action = "GetDate" } // Parameter defaults
);

public ActionResult GetDate(int year, int month, int day)
{
    //do stuff
}

HTHs
Charles

Charlino