Routing *Path wildcard will not accept Path when only one slash - asp.net-mvc

I have a problem with the wildcard route that I wonder if anyone can help on, I have a route as below
routes.MapRoute(
"ReportRoute",
"Report/{*path}",
new { controller = "Home", action = "Index"})
.RouteHandler = new ReportPathRouteHandler();
where the routehandler splits the path into its correct parts to get the correct report and this works great, if I put in a route www.mysite.com/report/folder1/folder2/report then I'll get what I'm looking for however my problem is if I have a link like www.mysite.com/report/folder1/report, the *path is only folder1/report and the routing really doesn't like this, in fact it doesn't even hit my route handler, just goes straight to 'resource can't be found' server error page. I tried to get around this by adding a new route before the wildcard as below
routes.MapRoute(
"ReportRoute2",
"Report/{path}/{name}",
new { controller = "Home", action = "Index" });
where the Controller takes Path and Name as two string parameters but still no joy, has anyone got any ideas or pointers as to what can fix this issue? Thanks for your help.

The first example should be fine (except that odd .RouteHandler = new ReportPathRouteHandler(); at the end). What does your controller action look like? Does it take a "string path" as a parameter?

Related

ASP.NET MVC routing issue: How to allow "\" in id's

I am using following route map
routes.MapRoute(
"RenderAssociatedForm",
"DoAction/{nodeLevelId}/{nodeSystemId}",
new {
controller = "FrontEnd",
action = "RenderAssociatedForm",
});
Now nodeLevelId can be anything like zs\bbal. As we know that we should escape '\', so we are using 'zs%5cbbal'. But still the following url is not mapping to this route.
//localhost/DoAction/zs%5cbbal/5
When I try simple Id without the escape character, it maps properly. Can anybody tell me where I am going wrong?
You could try it with two routes. The first route would be the one you showed, and the one after it would simply have "DoAction/{nodeLevelId}".
You'll need to use wildcards and parse the values out yourself:
routes.MapRoute(
"RenderAssociatedForm",
"DoAction/{*nodeLevelId}/{nodeSystemId}",
new
{
controller = "FrontEnd",
action = "RenderAssociatedForm",
});
#jfar probably has the best solution. Substitute the \ for a - or $ or something more URL friendly.

I'm getting a "Does not implement IController" error on images and robots.txt in MVC2

I'm getting a strange error on my webserver for seemingly every file but the .aspx files.
Here is an example. Just replace '/robots.txt' with any .jpg name or .gif or whatever and you'll get the idea:
The controller for path '/robots.txt'
was not found or does not implement
IController.
I'm sure it's something to do with how I've setup routing but I'm not sure what exactly I need to do about it.
Also, this is a mixed MVC and WebForms site, if that makes a difference.
You can ignore robots.txt and all the aspx pages in your routing.
routes.IgnoreRoute("{*allaspx}", new {allaspx=#".*\.aspx(/.*)?"});
routes.IgnoreRoute("{*robotstxt}", new {robotstxt=#"(.*/)?robots.txt(/.*)?"});
You might want to ignore the favicon too.
routes.IgnoreRoute("{*favicon}", new {favicon=#"(.*/)?favicon.ico(/.*)?"});
You can adjust the regular expression to exclude paths.
Haacked from the source.
The ignore route given above didn't work for me but I found a similar one that did:
routes.IgnoreRoute("{*staticfile}", new { staticfile = #".*\.(css|js|gif|jpg)(/.*)?" });
This error could also happen if inside a view in your area, you use the Html.Action helper. This helper will always use the area as a prepend, unless you specifically tell it not to. E.g.,
#Html.Action("Main", "Navigation", new { area = string.Empty })
I found another solution too... While I don't think I'll use it, it's worth showing here in the answers:
The following should (in theory) ignore looking for controllers for anything with a '.' in it.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" }, // Parameter defaults
new { controller = #"[^\.]*" } // Parameter contraints.
);
Do you still have:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
... in your Global.asax.cs?
MVC puts it there by default, and it's supposed to handle this.
If you do, then the problem may be how you're mixing MVC and WebForms.
I encountered this error when I request resources that did not exist.
Specifically, I was requesting a custom IE css file:
<!--[if lt IE 8]>#Styles.Render("~/Content/ie7.css")<![endif]-->
(These are condition comments, interpreted by IE)
However, the actual resource existed on ~/Content/ie/ie7.css.
So, without any modifications to the routing, the error was solved by using the correct url of the resource.

MVC Catch All route not working

My first route:
// Should work for /Admin, /Admin/Index, /Admin/listArticles
routes.MapRoute(
"Admin", // Route name
"Admin/{action}", // URL with parameters
new { controller = "Admin", action = "Index" } // Parameter defaults
);
is not resolving the route(I use Phil Haack's Route Debugger) and even the last route, "Catch All" route does not work:
//Maps any completely invalid routes to ErrorController.NotFound
routes.MapRoute("Catch All", "{*path}",
new { controller = "Error", action = "NotFound" }
);
If I go to /Admin/listArticles it works but /Admin gives me Error 403.15 "The Web server is configured to not list the contents of this directory." That points me to the idea that no routing is used as it looks for a physical file in a directory?
This is a simple low-level route problem but I cannot get it to work and everybody gives me links to read (yes I know MSDN is out there) but no real answers. I have researched routes and have tried but I am posting this because I cannot get it to work, any help, answers?
The answer to my question was that I had a route called /Admin and I wrote my error log to a directory /Admin/Error It seems that there is no overload to specify if the route should be resolved or if it is part of a physical directory.
The problem might be that you have added this route below the default route, all custom routes should be added above default route.
Are you using IIS 6.0? If so it'll need to look like...
// Should work for /Admin, /Admin/Index, /Admin/listArticles
routes.MapRoute(
"Admin", // Route name
"Admin.mvc/{action}", // URL with parameters
new { controller = "Admin", action = "Index" } // Parameter defaults
);
Where you need to set mvc as an application extension

How to handle empty URL in ASP.NET MVC

How do you set up the routing to handle http://mysite.com/Foo?
Where foo can be any value. I want it to go to /Home/Action/Id where foo is the id.
These are the mappings I have tried:
routes.MapRoute("Catchall", "{*catchall}",
new { controller = "Home", action = "Index", id=""});
routes.MapRoute("ByKey", "{id}",
new { controller = "Home", action = "Index" id=""});
They both generated a 404.
Thanks for any help.
Try this (note you had a missing comma in your original post):
routes.MapRoute("ByKey", "{id}",
new { controller = "Home", action = "Index", id=""});
I would, however, make it a bit more explanatory to prevent clashes later, even if it means a bit longer URIs:
routes.MapRoute("ByKey", "ByKey/{id}",
new { controller = "Home", action = "Index", id=""});
And place this as the first MapRoute command. Order does matter there, and the first route you add is the first route for a URL to be tested with.
Your second route is correct. It should work. Maybe you have another routes above? Debug your routes with Phil Haack's ASP.NET Routing Debugger
Steps to solve
Right click on the project
Go to web tab of the page.
My Start URL was found to be empty
I copied what in Project url of Servers section
Pasted at Start Url
It worked.

Issue with Default and catchall routes

I define a lot of explicit routes. One of them is:
routes.MapRoute("default", "",
new { controller = "Home", action = "Index" });
At the end, I define a catchall route:
routes.MapRoute("PageNotFound", "{*url}",
new { controller = "Error", action = "Http404" });
If I go to the homepage http://localhost, then the http404 page is shown. And strangely, if I remove the catchall route, then the welcome page appears correctly.
Note also that I have a menu where I call Url.RouteUrl("default") and the link to the homepage is correctly generated.
So, why is my default route not activated when the catchall route exists?
Update: I'm using routes.RouteExistingFiles=true. If I remove it, then it works as expected. But I need it to be set to true. What's the problem here?
Thanks.
If you use "routes.RouteExistingFiles=true" it means it will route existing (physically exist) files as its own - so routing will be skipped for those. I think in your root website there is probably a "default.aspx" or "index.htm" or something like that.
Turning on RouteExistingFiles will then allow those files to be executed normally (instead of via routing).
Now I think what happen is that your catchall routing is overriding you RouteExistingFiles - so it automatically routes the default.aspx into your 404 catchall.
If you still have the default route (I.E. {controller}/{action}/{id}) in RegisterRoutes() it will trap all URLs that match the format of a normal MVC request.
In other words the catch-all route can only intercept a bad URL if it doesn't fit the normal format (blah/blah/blah/blah).
In the case of a non-existent controller the exception must be handled through conventional ASP.NET handling.
Theres a good description of handling this here
Did you try to put a constraint on the catch all route? Constraint should tell it that the catch-all segment should not have 0 characters.

Resources