Asp.Net MVC Routing - how do I match the whole URL

2019-03-29 07:03发布

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 ID.

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.

3条回答
你好瞎i
2楼-- · 2019-03-29 07:33

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).

查看更多
3楼-- · 2019-03-29 07:34

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.

查看更多
smile是对你的礼貌
4楼-- · 2019-03-29 07:55

{*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" }
 );
查看更多
登录 后发表回答