Asp.Net MVC Routing - how do I match the whole URL?
I'm trying to create a catch-all route to track when an affiliate string is in the URL. An affilite code is marked by an x
followed by an int
, and will only appear at the end of a URL (but before the query string).
The idea is that I will extract the affiliate ID, do some logging, then do a 301 to the same request without the affiliate 开发者_如何学PythonID.
For example:
http://www.domain.com/x32
http://www.domain.com/x32/
http://www.domain.com/path/to/something/x32
http://www.domain.com/x32?query=string
http://www.domain.com/x32/?query=string
http://www.domain.com/path/to/something/x32?query=string
http://www.domain.com/path/to/something/x32/?query=string
I have this route
routes.Add(new Route("{url}/x{affiliateExternalId}", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(
new { controller = "Home", action = "LogCookieAndRedirect" }
),
Constraints = new RouteValueDictionary(new { affiliateExternalId = @"\d{1,6}" })
});
Which only matches
http://www.domain.com/path/x32
http://www.domain.com/path/x32/
What do I need to do to match everything and pass the query string to the controller? There is a *
operator that I suspect I should use, but I can't get it to do what I need.
{*url}
will match the whole path rather than just one segment. However, since it matches the whole path, you can't then match the affiliate ID on the end. The route will match every request. You can get around that by adding a route constraint to check that url
has an affiliate ID at the end:
routes.MapRoute(
"WithAffiliate",
"{*url}",
new { controller="Home", action="LogCookieAndRedirect" },
new { url = @"/x[0-9]+$" }
);
Your action will then need to parse the affiliate ID from the url
parameter itself. If you have the option to modify the URL structure, it would be possible to match the ID if it were at the start of the path:
routes.MapRoute(
"WithAffiliate",
"x{affiliateExternalId}/{*url}",
new { controller="Home", action="LogCookieAndRedirect" }
);
If I were doing it, I would make it one of the values in the query string.
Example:
http//www.domain.com/path/to/something?affiliate=X32&query=string
The problem is that the affiliate id is optional. If you put it in the path you will change the structure of the path based on whether or not the affiliate id is present, so you'll have to do every one of your routes twice (once with the affiliate id, and once without).
You can only have this catch-all route if you have only one route defined. But if you have multiple routes, then you're going to have to add that {affiliateExternalId}
parameter to all routes (unless I'm missing something).
I second Robert Harvey's suggestion.
精彩评论