问题
In Global.asax.cs in a project that I'm maintaining there is a method that looks like this
private static void MapRouteWithName(string name, string url, string physicalPath, bool? checkPhysicalUrlAccess = null, RouteValueDictionary defaults = null)
{
Route route;
if ((checkPhysicalUrlAccess != null) && (defaults != null))
{
route = System.Web.Routing.RouteTable.Routes.MapPageRoute(name, url, physicalPath, checkPhysicalUrlAccess.Value, defaults);
}
else
{
route = System.Web.Routing.RouteTable.Routes.MapPageRoute(name, url, physicalPath);
}
route.DataTokens = new RouteValueDictionary();
route.DataTokens.Add("RouteName", name);
}
It's then used in Global.asax.cs to set up routes like this:
MapRouteWithName("Change User", "User/Change/{id}/{organizationid}/{username}/{logonaccount}/{phone}", "~/User/Change.aspx", true,
new RouteValueDictionary { { "id", "0" }, { "organizationid", "0" }, { "username", "" }, { "logonaccount", "" }, { "phone", "" } });
And then in the code behind a page one can find things like this:
Response.RedirectToRoute("Change User", new
{
id = userID,
organizationid = selectedOrganizationID,
username = userName,
logonaccount = logonAccount,
phone = phone
});
Now this works nicely in most cases but in this particular example I don't know if the variables userName, logonAccount and phone actually contains something or is empty. When for instance userName is empty ("") and logonAccount has a value ("abcde") an exception is thrown:
System.InvalidOperationException: No matching route found for RedirectToRoute.
It seems like the exception is thrown when there is a variable with an empty string in between variables that has values. (Did this make sense?) What can I do about this?
回答1:
The issue here is that the redirect doesn't match the route because you are declaring optional values incorrectly. The only way to make them optional would be to have a configuration like this:
routes.MapPageRoute(
routeName: "ChangeUser1",
routeUrl: "User/Change/{id}/{organizationid}/{username}/{logonaccount}/{phone}",
physicalFile: "~/User/Change.aspx",
checkPhysicalUrlAccess: true,
defaults: new RouteValueDictionary(new {
phone = UrlParameter.Optional,
})
);
routes.MapPageRoute(
routeName: "ChangeUser2",
routeUrl: "User/Change/{id}/{organizationid}/{username}",
physicalFile: "~/User/Change.aspx",
checkPhysicalUrlAccess: true,
defaults: new RouteValueDictionary(new
{
username = UrlParameter.Optional
})
);
This will always work when any of the last 3 parameters are left off of the redirect. However, there's a catch - when you leave out a parameter, all of the parameters to the right will also be empty. That is the way the built-in routing works. A parameter can only be optional if there is no value to the right of it.
If you want to have all 3 parameters optional and not have to worry about what order or combination the parameters are passed, you have 2 options:
- Use query string parameters
- Use a convention to build up a series of routes as in this example
Query string parameters are the far simpler option when dealing with search forms with lots of optional parameters because they can be supplied in any order and any combination without having to do anything extra. They are a natural fit for this scenario.
来源:https://stackoverflow.com/questions/48808698/mappageroute-cant-send-empty-strings-in-the-middle