C# MVC 5 Multiple routes not working server - c#

I have a project that I tried to make the mapping "short" for the Urls to look beautiful.
In my environment it is working, however when publishing to the server it gives the error below.
Url my site: www.papodealemao.com.br
My Routes
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Pagina",
url: "pagina/{id}",
defaults: new { controller = "Principal", action = "Index", id = "1" }
);
routes.MapRoute(
name: "Secao",
url: "Secao/{id}",
defaults: new { controller = "Blog", action = "Secao" }
);
routes.MapRoute(
name: "Categoria",
url: "Categoria/{id}",
defaults: new { controller = "Blog", action = "Categoria" }
);
routes.MapRoute(
name: "PorData",
url: "PorData/{id}",
defaults: new { controller = "Blog", action = "PorData" }
);
routes.MapRoute(
name: "Artigo",
url: "artigo/{id}",
defaults: new { controller = "Blog", action = "Artigo" }
);
routes.MapRoute(
name: "Tag",
url: "Tag/{id}",
defaults: new { controller = "Blog", action = "Tag" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Principal", action = "Index", id = UrlParameter.Optional }
);
}
Error
Multiple types were found that match the controller named 'Blog'. This can happen if the route that services this request ('artigo/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Blog' has found the following matching controllers:
PapoDeAlemao.Controllers.BlogController
blog.Controllers.BlogController
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Multiple types were found that match the controller named 'Blog'. This can happen if the route that services this request ('artigo/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Blog' has found the following matching controllers:
PapoDeAlemao.Controllers.BlogController
blog.Controllers.BlogController
Visual Studio

You need to add namespaces to the route indicating which BlogController your want, i.e.:
routes.MapRoute(
name: "Secao",
url: "Secao/{id}",
defaults: new { controller = "Blog", action = "Secao" },
namespaces: new[] { "PapoDeAlemao.Controllers" }
);

The reason of the error is that you have to classes named "BlogController" once inside "Controllers" folder and one inside "PapoDeAlemao/Controllers" folder. Please unify then in one class and the error will be gone.
OR
You may namespace routing
routes.MapRoute(
name: "Secao",
url: "Secao/{id}",
defaults: new { controller = "Blog", action = "Secao" },
namespaces: new[] { "PapoDeAlemao.Controllers" }
);

The error message indicates that you have multiple classes called BlogController and route table does not know which one you want to route to. Could be that it is stray code you meant to delete. Could also be an old dll left on the server that is still referencing old code.
Try clearing previous files and publish afresh.

Related

Routing to another action than Index as default

I already searched for long, but for this case I found no answer.
I have a HomeController and the default route in my route.config is as follows:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
So; http://localhost:36690/Home automatically calls Index.
I also have a MyController (and it's custom route in route.config) with an Index method and can just write http://localhost:36690/My and it works.
But I want to have a custom route without any Index.
If I request localhost:36690/New, it should call BASIC.
So I tried the following:
routes.MapRoute(
"New",
"{controller}/{action}",
new { controller = "New", action = "Basic" }
);
But it ignores my default action 'Basic' and throws the error:
Server Error in '/' Application. The resource cannot be found. "
You can add another route specifically for that controller.
routes.MapRoute(
name: "New",
url: "New/{action}",
defaults: new { controller = "New", action = "Basic" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
That way, when /New is called it will default to NewController.Basic

How to solve this same routing pattern issue in asp.mvc routing?

I'm practicing MVC routing and now I'm stuck in a situation which I don't understand how to solve. I have two controllers and action in both controllers and two routes in RouteConfig class. Here:
RouteConfig
routes.MapRoute(
name: "Students",
url: "{Class}/{Students}",
defaults: new { controller = "Class", action = "Students" });
routes.MapRoute(
name: "SubjectDetail",
url: "{Class}/{Subject}",
defaults: new { controller = "Subject", action = "SubjectDetail"});
Now the problem is when I go to the class/Students url it works fine but in case of class/subject it again redirects me to the class/Students url. I know there is some route pattern mistakes. How to solve this issue. Thanks.
Try:
routes.MapRoute(
name: "Students",
url: "classes/{classId}/students/{studentId}",
defaults: new { controller = "Class", action = "Students" });
routes.MapRoute(
name: "SubjectDetail",
url: "classes/{classId}/subjects/{subjectId}",
defaults: new { controller = "Subject", action = "SubjectDetail"});

MVC RouteConfig affected the Html.ActionLink() helper method

In my MVC project, I've Item controller and some actions like Index.
The RouteConfig includes:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
In some views, I'm using the helper method Html.ActionLink("Items","Index","Item") to create anchors for the index action. So the href of the anchor result will be (/Item/Index)
Now, I need to map the following static URL:
/IndirectItem/Index
to the Index action of the Item controller with default parameter (indirect = true), so the RouteConfig will be:
routes.MapRoute(
name: "IndirectItem",
url: "IndirectItem/Index",
defaults: new { controller = "Item", action = "Index", indirect = true }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
It seems OK and the client requests were mapped correctly , but all anchors resulted from the Html.ActionLink("Items","Index","Item") helper method were mapped to the URL (/IndirectItem/Index) instead of (/Item/Index).
How can I fix this problem without changing all Html.ActionLink() to Html.RouteLink() or adding another route for the original url ?
Using constraints will be a convenient solution for your problem.
Use the following IndirectItem route instead of yours.
routes.MapRoute(
name: "IndirectItem",
url: "{staticVar}/{action}",
defaults: new { controller = "Item", action = "Index", indirect = true},
constraints: new { staticVar = "IndirectItem" }
);
and you don't need any change in the Default route.
It works fine with me.
You are experiencing this issue because Html.ActionLink uses Routing table for generating URLs and since IndirectItem route is match to Html.ActionLink("Items","Index","Item") (because it has Index action and Item controller specified in both route and action link). The resolving done by a first match so the order of routes registration matters
By adding DefaultItem route:
routes.MapRoute(
name: "DefaultItem",
url: "Item/Index/{id}",
defaults: new { controller = "Item", action = "Index", id = UrlParameter.Optional }
);
prior to your current routes:
routes.MapRoute(
name: "IndirectItem",
url: "IndirectItem/Index/,
defaults: new { controller = "Item", action = "Index", indirect = true}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Should fix the issue
Another option could be creating empty IndirectItem controller that inherits from Item controller:
public IndirectItemController : ItemController
{
}
and then changing the route to
routes.MapRoute(
name: "IndirectItem",
url: "IndirectItem/Index/,
defaults: new { controller = "IndirectItem", action = "Index", indirect = true}
);
The answers given by Omar Gohar and Alex Art are misleading.
The problem you are running into is that your route does not match when generating the URL. This is simply because you have not provided all of the route values to create a match in your ActionLink.
#Html.ActionLink("Items", "Index", "Item", new { indirect = true }, null)
If changing your ActionLink declaration is not an option, you can attach your "indirect" metadata to the route using the DataTokens parameter.
You use the DataTokens property to retrieve or assign values associated with the route that are not used to determine whether a route matches a URL pattern. These values are passed to the route handler, where they can be used for processing the request.
routes.MapRoute(
name: "IndirectItem",
url: "IndirectItem/Index",
defaults: new { controller = "Item", action = "Index" }
).DataTokens = new RouteValueDictionary(new { indirect = true });
The bottom line is that RouteValues (which are populated by the defaults if not provided by the URL pattern) are not meant to be used for metadata. They are meant to be real data to match to make the URL unique.
Of course, if you are not actually using the indirect route value for anything, you can simply omit it from the route.
routes.MapRoute(
name: "IndirectItem",
url: "IndirectItem/Index",
defaults: new { controller = "Item", action = "Index" }
);

Getting HTTP Error 403.14 - Forbidden when accessing MVC application with default route

I have this in my route config
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "Accessibility/{controller}/{action}/{id}",
defaults: new { controller = "Cardholders", action = "Index", id = UrlParameter.Optional }
);
}
However, when I view my project in browser, it doesn't seem to redirect to the action that I have specified. It remains at http://localhost:54358/ which is probably why I'm getting the http error.
I have no problems viewing the page directly, e.g., browinsg it at http://localhost:54358/Accessibility/Cardholders/Index
What could be the issue here?
You don't have a route that match localhost
If you try "localhost:54358/Accessibility" it should work
If you want that localhost goes to the cardholders page, your route should be:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Cardholders", action = "Index", id = UrlParameter.Optional }
);

Keep getting 404 eventhough I mapped my routes

I have been dealing with some issues about routes. I have defined the routes but I keep getting 404. Here are the routes :
routes.MapRoute(
name: "Default",
url: "{controller}",
defaults: new { controller = "Login", action = "Login" }
);
routes.MapRoute(
name: "Home",
url: "{controller}/{Date}",
defaults: new { controller = "Home", action = "Home", Date = UrlParameter.Optional }
);
routes.MapRoute(
name: "Calendar",
url: "{controller}/{action}",
defaults: new { controller = "Calendar", action = "Index" }
);
routes.MapRoute(
name: "Act",
url: "{controller}",
defaults: new { controller = "Act", action = "New" }
);
localhost:51081/login works!
localhost:51081/Home/25.04.2013 works!
localhost:51081/act doesnt work!
localhost:51081/calendar/index doesnt work!
Here "login" and "home" works but "calendar" and "act" doesnt. When I move "calendar" mapping to the top then "home" mapping doesnt work. how do you map your pages?
Basically I dont want action name to appear on the url ex : http://localhost:51081/Home/Home/25.04.2013. I want to see it like http://localhost:51081/Home/25.04.2013 or http://localhost:51081/calendar
Like #MarcGravell says: you only add special rules for the exceptions
In your case routes Calendar and Home are the same.
You can map your routes more specific by replacing {controller} with the Home, cause that route isn't that dynamic and is really an exception(it ignores the action)
routes.MapRoute(
name: "Home",
url: "Home/{Date}",
defaults: new { controller = "Home", action = "Home", Date = UrlParameter.Optional }
);
Act is the same as calendar so you don't need two routes for those. Just call Act/New instead of only Act.
For the Default use:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Login", action = "Login" }
);
And put it at the bottom of your routes off course.
routes.MapRoute(
name: "Default",
url: "{controller}",
defaults: new { controller = "Login", action = "Login" }
);
This defines a route that matches / and /anything; the / will try to use LoginController.Login, and /anything will try to use anythingController.Login. Note that at no point does this route allow it to pick up any "action" other than Login.
If you trow all of those away, and use something like:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
then that will match any of /, /anything and /anything/anythingelse.
/ will map to HomeController.Index
/anything will map to anythingController.Index
/anything/anythingelse will map to anythingController.anythingelse
Hopefully that explains how the mapping works in terms of defaults.
If you have any specific routes, they should be added before this blanket default.
Remember that asp.net routes are evaluated in the order in which you add them to the MapRoute table.
Your "default" and "act" routes are the same, since they have the same pattern. "Act" will probably never get hit.
Also, your "default" route is pretty generic, and most requests will satisfy it. You should add your routes in order of most specific (e.g. hard-coded routes) to least specific (e.g. all placeholders).
So if I have a request of foo/bar, it will fall to your "default" route since "foo" will be interpreted as the controller -- it's then going to look for a resource of "bar" which probably doesn't exist. So you'll get a 404.
Your "home" and "calendar" routes are also the same pattern, so only one will get hit (which will be the first defined).
Make your routes more specific, and define them from most specific to least.
Good luck!

Categories