MVC Catch All route not working - asp.net-mvc

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

Related

Remove "Home/Index" secondary route to home page

I have an ASP.net MVC 5 site. The home page is at http://mydomain.
However, there's also a second route to the home page - http://mydomain/home/index - which I think
This causes problems because it may be seen as duplicate content, and images are broken on this page.
How can I totally remove this route (so it goes to a 404, I guess?).
I've searched Google but can only find articles on removing Home from routes entirely - not what I need.
I'm using Attribute routing, and this is all that's in the RouteConfig.cs:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Enable Route Attributes in Controllers
routes.MapMvcAttributeRoutes();
// Fall through all routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The Home Index action has no attribute route on it (as you'd probably expect?). This /home/index route works even on newly generated MVC projects - which I think is a bad idea?
How can I do this?
Are there any problems with removing this route I may not have considered?
thx.
You can block unintended routes that you don't want by using IgnoreRoute().
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("Home");
routes.IgnoreRoute("Home/Index");
// Enable Route Attributes in Controllers
routes.MapMvcAttributeRoutes();
// Fall through all routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
However, if these URLs are already in the wild, you should instead setup a 301 redirect to the canonical URL you intended. The simplest way to do that is with the URL rewrite module.
This /home/index route works even on newly generated MVC projects - which I think is a bad idea?
I see this as more of a blessing in disguise. It is an advantage over any SEO competitor using MVC who doesn't do the extra work to remove these routes when you are the one who does.
This is not necessary.
The default route provides optional controller and action names. So if user does not put any name for controller and/or action in path (/Home/Index or /Home in this situation) asp.net will put the right values in application routing.
Whenever you use Url.Action or Url.Route functions it will produce the shortest link for you. So in your website there will be always http://mydomain produced for your root. And for example Category > Index action it will produce http://mydomain/category.
In your website bots will never get to duplicate content if your links are in this way. If you are writing your links manually write as short as you can or simply use Url.Action.
About the images there must be something different, because images are static files. just use "~/imagefolder/imagename.jpg" way to get them. "~" is important to start link from the root of application if you are making your application work on a subfolder in IIS.

Github like routes

How is this achievable in asp.net mvc? I have seen some ruby examples out there...
Github like routes in Rails
i.e. nested folders, can be unlimited... however they are usually nested once
e.g.
lets say my main route in my app is:
/projects/{projectid}/
I am hooked into a file system, so I want users to navigate through whatever directory structure so I can have:
/projects/{projectid}/foldera/
/projects/{projectid}/folderb/
/projects/{projectid}/foldera/pic1.png
/projects/{projectid}/folderb/special/car134d.jpeg
etc...
This way I can only show files or pictures that are inside the url/directory the user is in...
I think what you're after is the {*queryvalues} segmented url handler for routing. The * indicates a wildcard-style match of one or more segments, delimited by a "/".
To map to a physical path, you can use this to add a route to your Global.asax.cs:
routes.MapPageRoute(
"Projects", // Route name
"projects/{projectId}/{*path}", // Route url format
"~/ProjectFolder/{projectId}/{path}" // Path to files
);
If you want to get the path into an MVC Controller Action and then do something with it, you could use MapRoute:
routes.MapRoute(
"Projects", // Route name
"projects/{projectId}/{*path}", // Route url format
new { controller = "Project", action = "Index" } // Defaults
);
Then create a ProjectController, and in the Index action retrieve RouteData.Values["projectId"] and RouteData.Values["path"] and do whatever you need to with them...

Default route problem

If I want to hit a url like
http://localhost:8080/controllername
I want the "Index" action to be the default action called. I assumed the default route mapping would be fine and the "Index" action would be called on whatever controller was specified - seems I need to specify
http://localhost:8080/controllername/index
Is this correct?
Mapping:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
What you're trying should definitely work. In fact, the code you posted is from the default templates, and I've just tested it by adding an "Index" action to the AccountController and visiting /Account in my browser.
I'd recommend creating a new project and testing this behaviour (first with the built-in web server, then with IIS, if you're not always using the built-in server). If it works, there's probably something different in your project that's causing the issue.
I had a similar problem and it occured because of a collision with a directory in the project. I had a structure like this in my project:
Controllers \
HomeController.cs
CmsController.cs
Cms \
WhateverFile.cs
The Cms subdirectory collided with the /Cms URL, while Cms/Index worked. I simply renamed my colliding folder name. If you have to keep it, there is a RouteCollection.RouteExistingFiles that can be used to prevent automatic lookup of files. If that is enabled I think that a lot exclusions have to be added for the Script etc, see this blog post for an example.

ASP.NET MVC - Running in a Subdirectory

I am attempting to deploy an ASP.NET MVC application in a subdirectory of an existing application and I am running into some routing issues. I have set up the folder structure such that all of the binaries and config files for the MVC app are correctly located in the root directory, while the rest of the content is in the subdirectory. Additionally, I updated all of the routes in the MVC application to reflect the subdirectory; however, every request to the application produces:
The incoming request does not match
any route.
All defined routes are being ignored, including the default route:
routes.MapRouteLowercase(
"Main_Default",
"blog/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
I tried enabling RouteDebug to test the issue, but even that is not getting routed to. Any advice on what else I can try?
Note: This question is not a duplicate.
Try running it as a virtual directory instead of just a directory, otherwise your routes are not going to be called. You will not need to put the name of the virtual directory in the route.
Here's a route that I have setup in a v-dir MVC app that works just fine...
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Tour", action = "Index", id = "" } // Parameter defaults
);
Looks like I found the problem.
In addition to the binaries and the config files, Global.asax must also be placed in the root in order for its code to be executed.
Thanks guys. :)

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