There are two ways of providing parameter values as part of the URL - as path segments (e.g.
/yourpage/1
) or as query string values (e.g. /yourpage?id=1
).
Query strings are fairly straightforward to work with. Path segments require
configuration, which is normally done by supplying a route template to the @page
directive in a Razor content page specifying the name of a route parameter:
@page "{id}"
You can specify the constraint for the data type that the value must match:
@page "{id:int}"
And you can use the ?
syntax to indicate that the parameter value
is not required:
@page "{id:int?}"
This will be matched by /yourpage
and yourpage/2
but not yourpage/blah
(because of the type constraint). But what if you have multiple optional parameters?
Let's say that you have a report that can take either a start date or an end
date as parameters, or both, or neither:
@page "{startdate:datetime?}/{enddate:datetime?}"
This works fine when values for both parameters are provided e.g. /report/2019-1-1/2019-12-31
. Both values are bound to PageModel properties:
If you provide just one value, e.g. /report/2019-1-1
, it will always be bound
to the first parameter:
So what are your options? At this stage, it helps if you start to equate routes to C# method signatures.
Method Overloading
You can overload C# methods, and you can do that same with routes in Razor
Pages via the
AddPageRoute
method. However, in this example, overloading won't work
because both parameters are the same data type. If you added a route that takes
one datetime
value representing the startdate
, you can't add another to
represent the endate
value.
Default Values
What you can do instead is to change the first parameter so that it is no longer optional, and provide a default value:
@page "{startdate:datetime=2000-1-1}/{enddate:datetime?}"
This is a neat solution all the time that you are in control of how URLs are
generated for this route. The
anchor tag helper, for example, will populate the startdate
with the default
value if no value is provided:
<a asp-page="/report" asp-route-enddate="2019-12-31">View Report</a>
Named Parameters
When
optional arguments were introduced in C# 4.0, the implementation also
included named arguments as part of the package. If you want to skip an
optional parameter, you can provide values for others that come after it in the
parameter list by prefixing the value with the name of the argument. If Report
was a C# method instead of a Razor page, you would call it like this when only
providing an enddate
value:
Report(enddate: new Date(2019,12,31));
You can implement the same approach by using query string values rather than
path segments for data passed in URLs. To take advantage of this method, don't
provide a route template to the @page
directive. Any values
provided to asp-route
attributes will be assigned to query string
values instead:
As long as your PageModel properties have SupportsGet=true
applied to their
BindProperty
attribute, the value will be bound to the correct property:
Summary
Multiple optional parameters in Razor Pages URLs are one of those things that can cause a mental block. Once you start to think of them in the same way as arguments to C# methods, solutions are much easier to grasp.