Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attribute Routing for Multiple DateTime parameters

I have defined attribute route which takes two parameter as datetime

  [Route("{controller}/{action}/{*startDate:datetime}/{*endDate:datetime}")]
        public bool OverView(DateTime startDate,DateTime endDate)
        {
            var dt = startDate.ToString("yyyy-MM-dd");
            return true;
        }

But not sure, how it is possible. The attribute route works fine for a single parameter, but no sure how it will work for 2 params. Also it's hard to know how it will distinguish two parmeters from the url

Single param which is work fine

http://domain.com/Home/overview/2014/02/01

What will be the url for two params? I tried the below one but got an exception

http://domain.com/Home/overview/2014/02/01/2014/02/04

Exception
A catch-all parameter can only appear as the last segment of the route URL.
Parameter name: routeUrl
like image 238
Ammar Khan Avatar asked Feb 05 '14 17:02

Ammar Khan


1 Answers

First possibility

You should be formatting your dates by other means than / because those are URL segment delimiters... And even if MVC supported multiple greedy segments, there should be at least one static segment in between so routing would be able to distinguish where one ends and second starts.

So if you just replace your notation from

/home/overview/2014/02/01

to

/home/overview/2014-02-01

Your current routing would almost work and route parameters would easily get model bound to datetime type instance. Your route declaration on your action method should be like:

[Route("{controller}/{action}/{startDate:datetime?}/{endDate:datetime?}")]
public ActionResult OverView(DateTime? startDate, DateTime? endDate)
{
    ...
}

So if you can live with this change (/ to -) then this is the simplest solution for you because it doesn't require you to write any customization code (i.e. custom model binders)

Second possibility

Have a single greedy route parameter and manually parse it. It will either have 0, 3 or 6 segments. You should be able to parse those manually.

[Route("{controller}/{action}/{*dateRange}")]
public ActionResult Overview(string dateRange)
{
    int numberOfSegments = dateRange.Split('/').Length;

    if (dateRange.EndsWith("/"))
    {
        numberOfSegments--;
    }

    switch (numberOfSegments)
    {
        case 0:
            // no dates provided
            ...
            break;
        case 3:
            // only one date provided
            ...
            break;
        case 6:
            // two dates privided
            ...
            break;
        default:
            // invalid number of route segments
            ...
            break;
    }
}
like image 74
Robert Koritnik Avatar answered Sep 20 '22 19:09

Robert Koritnik