0

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?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
jahrentorp
  • 155
  • 1
  • 11
  • Is a user required to have a name? If yes, what does this situation imply? – Aluan Haddad Feb 15 '18 at 13:48
  • The variables userName, logonAccount and phone are actually search terms. What has happened here is that a list of existing users has been presented and one of them is clicked on in order to change it. Those three variables are then not used in the form on the change page but rather in order to make it possible to return to the list page as it looked before the user was clicked. If someone had searched for every username containing "abcde" that particular list should be restored. – jahrentorp Feb 15 '18 at 13:53

1 Answers1

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:

  1. Use query string parameters
  2. 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.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212