ASP.Net MVC 4 w / AttributeRouting and Multiple RoutePrefix Attributes

TL DR

I need a way to programmatically select which RoutePrefix is ​​selected when creating URLs based on user properties in my MVC application

Not TL; DR

I have an MVC 4 application (with AttributeRouting NuGet package)

Due to the requirements of the hosting environment, I have to have two routes for many of my actions, so that the hosting environment can have different access permissions.

I solve this by decorating my controller with [RoutePrefix("full")] [RoutePrefix("lite)] . Which allows you to access each action method via / full / {action} and / lite / {action}.

This works great.

 [RoutePrefix("full")] [RoutePrefix("lite")] public class ResultsController : BaseController { // Can be accessed via /full/results/your-results and /lite/results/your-results and [Route("results/your-results")] public async Task<ActionResult> All() { } } 

However, each user should use only full or lite in their URLs, which is determined by some properties of this user.

Obviously, when I use RedirectToAction() or @Html.ActionLink() , it will simply select the first available route and not save the “correct” prefix.

I decided that I could override the RedirectToAction() method, and also add my own version of @Html.ActionLink() methods.

This will work, but it will require some kind of nasty code to create the urls, because all I get is a string representing the action and controllers, but not the reflected types. There may also be route attributes, for example, in my example, so I will have to replicate a large number of MVCs embedded in the code.

Is there a better solution to the problem I'm trying to solve?

+5
source share
2 answers

I ended up finding a solution for this

I simply redefined the default routes to enable this. ASP.Net automatically saves the usertype value and returns it back when it restores the routes.

 const string userTypeRegex = "^(full|lite)$"; routes.Add("Default", new Route("{usertype}/{controller}/{action}/{id}", new { controller = "Sessions", action = "Login", id = UrlParameter.Optional }, new { usertype = userTypeRegex })); 

I found that this does not work with Route or RoutePrefix , so I had to remove all of them. Forcing me to add specific routes in these cases

 routes.Add("Profile-Simple", new Route("{usertype}/profile/simple", new { controller = "ProfileSimple", action = "Index" }, new { usertype = userTypeRegex })); 

I thought that half a dozen hard-coded routes in my RouteConfig file were a better solution than manually adding values ​​to every place I created the URL (as in Chris's solution).

+2
source

How about something like:

 [RoutePrefix("{version:regex(^full|lite$)}")] 

Then when you create your links:

 @Url.RouteUrl("SomeRoute", new { version = "full" }) 

or

 @Url.RouteUrl("SomeRoute", new { version = "lite" }) 

You could even do the following to just save everything that has already been installed:

 @Url.RouteUrl("SomeRoute", new { version = Request["version"] }) 
+6
source

Source: https://habr.com/ru/post/1205365/


All Articles