Asp.Net Routing: How do I ignore multiple wildcard routes? - c#

I'd like to ignore multiple wildcard routes. With asp.net mvc preview 4, they ship with:
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
I'd also like to add something like:
RouteTable.Routes.IgnoreRoute("Content/{*pathInfo}");
but that seems to break some of the helpers that generate urls in my program. Thoughts?

There are two possible solutions here.
Add a constraint to the ignore route to make sure that only requests that should be ignored would match that route. Kinda kludgy, but it should work.
RouteTable.Routes.IgnoreRoute("{folder}/{*pathInfo}", new {folder="content"});
What is in your content directory? By default, Routing does not route files that exist on disk (actually checks the VirtualPathProvider). So if you are putting static content in the Content directory, you might not need the ignore route.

This can be quite tricky.
When attempting to figure out how to map route data into a route, the system currently searches top-down until it finds something where all the required information is provided, and then stuffs everything else into query parameters.
Since the required information for the route "Content/{*pathInfo}" is entirely satisfied always (no required data at all in this route), and it's near the top of the route list, then all your attempts to map to unnamed routes will match this pattern, and all your URLs will be based on this ("Content?action=foo&controller=bar")
Unfortunately, there's no way around this with action routes. If you use named routes (f.e., choosing Html.RouteLink instead of Html.ActionLink), then you can specify the name of the route to match. It's less convenient, but more precise.
IMO, complex routes make the action-routing system basically fall over. In applications where I have something other than the default routes, I almost always end up reverting to named-route based URL generation to ensure I'm always getting the right route.

Related

.Net Core Application Parts, change view import/search location

I've been experimenting with ASP.NET Core application parts, but have ran into two problems:
Firstly, I need a way to specify an extra directory in the view engine's search path, some of the time.
Secondly, is there any way to change the import location of views when pulled in through application parts?
The reason I am asking is due to some of my application parts having identically named controllers and views (i.e., Home/Index) which causes AmbiguousMatchExceptions. I have already relocated the controllers using a namespace routing scheme detailed here: .net core replacement for MvcCodeRouting. Namespace based routing.
Any help would be appreciated. Thanks.
An implementation of the IViewLocationExpander interface did the job in this case.
By creating an implementation of the IViewLocationExpander, you can specify alternative locations, in which, views may be located. The "default" locations are passed into the ExpandViewLocations method (which returns an IEnumerable<string>), only the locations returned are searched, meaning that you get the choice to either include the defaults or leave them out, forcing only your newly specified locations to be searched.

Configuring ASP.NET MVC Attribute Routing for multi language site

I'm creating a MVC5 web site that should support multiple languages. The structure of the app is complex so I'm using Attribute Routing only. RouteConfig.cs is very simple:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
}
I want to keep language information in URL by adding language identifier after site name. For English, which is default language, URL should remain "clean". Here are an example:
http://test.com/foo/1/bar/2
http://test.com/de/foo/1/bar/2
My first attempt was to use two RoutePrefix attributes for each controller:
[RoutePrefix("foo")]
[RoutePrefix("{lang}/foo")]
But MVC doesn't allow to use more than one RoutePrefix attribute for a controller.
So now I'm not using RoutePrefix attributes at all, and specify full route for each controller action:
[Route("foo/{a}/bar/{b}")]
[Route("{lang}/foo/{a}/bar/{b}")]
Is there any better way to handle lang route? Ideally I would like to specify in one place only, not for every controller.
PS. I'm setting current thread culture by parsing language route in custom filter.
I found the easiest solution (at least for ASP.NET MVC 5.2) is to use a default value for the optional parameter.
For example, if English is your default language, you can use a single attribute on the Controller:
[RoutePrefix("{lang=en}/foo")]
or a single attribute on the Action:
[Route("{lang=en}/foo/bar")]
Note that optional URI parameters (e.g. {lang?}) don't work if they are at the start of the URL.
If all else fails then I suggest you keep your default routes as is and store the language in a query parameter
For English, your default language, URL will remain "clean" as you intended.
http://test.com/foo/1/bar/2
But for other languages you include lang as query parameter
http://test.com/foo/1/bar/2?lang=De-DE
Then in your custom filter, check if the query parameter is present. If it is then change culture to match. Otherwise use default language.
Also: You should use 5 character encoding and not 2 char globalization ISO code. De-DE and not DE or fr-FR and not FR
You basically need three things:
A multi-language aware route to handle incoming URLs (if you're using MVC5 or above you could also go for Attribute-based routing instead, but I still prefer to use a global rule to handle this).
A LocalizationAttribute to handle these kinds of multi-language requests.
An helper method to generate these URLs within your application (Html.ActionLink and/or Url.Action extension methods).
See this answer for further details and code samples.
Code sample for multi-language Html.ActionLink extension
Code sample for multi-language Url.Action extension
(both are written in C# - affiliation disclaimer: I made those samples)
For additional info and further samples you can also read this blog post I wrote on this topic.
http://www.ryadel.com/en/html-actionlink-extension-method-written-c-handle-multi-language-routes-asp-net-mvc/

WebApi2 Attribute Routing doesn't work unless controller classes are named in a specific manner

I was debugging an issue with attribute routing giving 404s for known-good routes. Well, known-good to me, but they weren't being picked up by the framework. I was grouping my controllers/models into logical units, e.g.:
Auth
Models
Model1
Model2
Controller
So my "AuthController" is named MyApi.Auth.Controller instead of, for instance, MyApi.Auth.AuthController.
My routes were not being picked up until I renamed my controller, adding anything before it, e.g. zzController. This makes me think there's a bug in attribute routing, or am I missing something?
ASP is convention over configuration. Whether they add features that go away from that or not, always stick to the convention when it comes to Controllers and Views. It'll make maintenance so much easier (plus in the next version of MVC, there is no more ApiController, everything is just a Controller).

Restricted all routes expect the alowed one

Yeah, this might sound odd but we have a third party library which enable a sort of service consumed by a JavaScript application. This third party library take care of calling the correct controller and action.
This works all very well but we now need to restrict the routes to this "ServiceController" and maybe one or two other controllers. In the current version (MVC2) we simply override the controller factory which statically checks for a valid controller. Yeah it worked but it was more a workaround which then stayed there forever. So is there any clean way for archiving this (by configuring the routes? Note that we don't use the authorize attribute. And we will be using MVC4 in the next release)
Add global filter and put logic into OnActionExecuting (http://msdn.microsoft.com/en-us/library/gg416513(v=vs.98).aspx)
Option 1: Check routeValues for a correct controller and action
var controllerName = filterContext.RouteData.Values["controller"];
var actionName = filterContext.RouteData.Values["action"];
Option 2: Check this value Request.Url
Actually you allow only the routes defined and nothing else, so the question is really a little odd.

How to ignore all of a particular file extension in MVC routing

How do I configure an IgnoreRoute to ignore all files with a certain extension, regardless of what directory they're in?
If I do this, everything works and my Flash movie gets played:
routes.Ignore("community/123/plan/456/video/moviename.flv");
So the "123" and "456" sections are variable and can be any integer number. Obviously though, I don't want to do one of these for each movie NOR do I have a need to replace 123 and 456 with variable placeholders. This is only an example of one type of directory, there are Flash movies stored throughout the application so what I need is an IgnoreRoute value that will ignore files that have a .flv extension no matter where in the hierarchy they are.
I've tried the following:
routes.IgnoreRoute("{file}.flv");
routes.IgnoreRoute("(.*).flv(.*)"); // Yeah I know, I'm horrible at RegEx
The only thing I can get to work so far is specifically passing the full relative path to the FLV file. Any suggestions?
Check this article by Phil Haack: http://haacked.com/archive/2008/07/14/make-routing-ignore-requests-for-a-file-extension.aspx
Long story short, we didn’t want routing to attempt to route requests
for static files such as images. Unfortunately, this caused us a
headache when we remembered that many features of ASP.NET make
requests for .axd files which do not exist on disk.
To fix this, we included a new extension method on RouteCollection,
IgnoreRoute, that creates a Route mapped to the StopRoutingHandler
route handler (class that implements IRouteHandler). Effectively, any
request that matches an “ignore route” will be ignored by routing and
normal ASP.NET handling will occur based on existing http handler
mappings.
Hence in our default template, you’ll notice we have the following
route defined.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
This handles the standard .axd requests.
........
We only allow one catch-all route and it must happen at the end of the
URL. However, you can take the following approach. In this example, I
added the following two routes.
routes.IgnoreRoute("{*allaspx}", new {allaspx=#".*\.aspx(/.*)?"});
routes.IgnoreRoute("{*favicon}", new {favicon=#"(.*/)?favicon.ico(/.*)?"});
What I’m doing here is a
technique Eilon showed me which is to map all URLs to these routes,
but then restrict which routes to ignore via the constraints
dictionary. So in this case, these routes will match (and thus ignore)
all requests for favicon.ico (no matter which directory) as well as
requests for a .aspx file. Since we told routing to ignore these
requests, normal ASP.NET processing of these requests will occur.

Categories

Resources