MVC 4 routing "finding" controllers inside an Area - c#

I have a MVC 4 WebSite with several Areas... I´m using all default routing created by VS2012...
So, I can access (from Area1) :
Area1/ControllerX/ActionX
I have some controllers without Area, so I can access :
ControllerY/ActionY
All fine... But, if I try to access the ControllerX without the Area1, like that :
ControllerX/ActionX
I got that error:
Exception: The view 'ActionX' or its master was not found or no view engine supports the
searched locations. The following locations were searched: ~/Views/mangavagao/ActionX.cshtml
~/Views/Shared/ActionX.cshtml
Controller: ControllerX
Action: ActionX
I was expecting a Not Found 404 error... Why is that route been captured ?
--
Area route:
context.MapRoute(
"Area1_default",
"Area1/{controller}/{action}/{id}",
new { controller = "ControllerX", action = "ActionY", id = UrlParameter.Optional }
);
Default route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "ControllerY", action = "ActionY", id = UrlParameter.Optional );

Add the namespaces parameter in the default maproute function. Then set the UseNamespaceFallback datatoken to false.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "MvcApplication.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;
namespaces parameter is set to prioritize the controller finding, when multiple controller with the same name exists.
MVC will still search for controller outside of this namespace, if no match is found in the namespace.
UseNamespaceFallback datatoken tells MVC to disregard the (2) statement.
hope this helps.

Try to map the area route with a namespace:
context.MapRoute(
"Area1_default",
"Area1/{controller}/{action}/{id}",
new { controller = "ControllerX", action = "ActionY", id = UrlParameter.Optional },
new[] { "App.Areas.AreaName.Controllers" }
);
Change App and AreaName to the corresponding values.

This is similar to this question: Not including area name in URL results in "The view 'Index' or its master was not found" instead of 404
In your case the namespaces need to be added to the default route, not the area route. The namespace in this case should not reference the area controllers.
Something like this should work:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
null, // object constraints
new string[] { "Namespace.Application.Controllers" } // namespaces
);

Related

ASP.Net C# MVC create exception to a global route

I am writing a URL Shortener application.
When someone enters root.com/whatever, they are redirected to a configured URL.
I managed to create a global route which will catch the paths after the root ("whatever" above) and execute the corresponding redirection successfully.
My problem and question is this:
The admin interface is at root.com/admin and when I try to access that, I get the global controller. How do I make an exception to the global controller for "admin"?
Here is what I have in my route config right now:
routes.MapRoute(
name: "Admin",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Admin", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Global",
url: "{suffix}",
defaults: new { controller = "Home", action = "Index", suffix = UrlParameter.Optional }
);
For the first route, I also tried:
routes.MapRoute(
name: "Admin",
url: "admin/{action}/{id}",
defaults: new { controller = "Admin", action = "Index", id = UrlParameter.Optional }
);
And I also tried putting it second in the file.
I don't know if this will help you, but take a look at this stack overflow posting: ASP.Net MVC: Routing issue which throwing exception
This person reduced the more specific route and it worked for him.

MVC Routing Parameter Not Being Passed

I am trying to do some MVC routing, following online tutorials, but for some reason the routing is not working.
I am trying to do http://www.website.com/news/news-title
The route I am trying to do is below.
routes.MapRoute(
"News",
"{controller}/{url}",
new { controller = "News", action = "Index", url = "" }
);
Within my NewsController I have the following ActionResult.
public ActionResult Index(String url)
{
return View();
}
However, when stepping thorough the code, url is not being populated.
Thanks
== Update ==
Thank you all for your replies.
I have no amended the Route to below
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.LowercaseUrls = true;
routes.Add(new SubdomainRoute());
routes.MapRoute(
"News",
"News/{action}/{slug}",
new { controller = "News", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
This URL works: /news/index/?slug=test-news-title
But this URL does not: /news/index/test-news-title
=== Further Edit ===
It appears my subdomain route is messing with it. If i remove the subdomain route it works fine.
Thanks.
Most likely, your route is too broad. But it depends on how the rest of your routes are configured. You would need to post your entire route configuration (including area routes and attribute routing) in order to reasonably get an answer what is wrong with your route.
However, you can be more specific with this route because you know that it needs to start with /News.
routes.MapRoute(
"News",
"News/{url}",
new { controller = "News", action = "Index" }
);
Also, it probably doesn't make sense to make the URL parameter optional by providing a default value. If you remove url = "", the url parameter is required in the URL. If configured as above, if you just pass /News, it won't match this route. However, as you have it this URL will match.
Finally, make sure this route is placed in the right order. It should be placed before your default route (if you still have it).
You have set for the parameter url the empty string. you should use instead UrlParameter.Optional (or removing it at all if is mandatory):
routes.MapRoute(
"News",
"{controller}/{url}",
new { controller = "News", action = "Index", url = UrlParameter.Optional }
);
You are missing the action part in the MapRoute
routes.MapRoute(
"News",
"{controller}/{action}/{url}",
new { controller = "News", action = "Index", url = "" }
);
Hope this help

default routing not working

In my MVC application, I have following route configuration,
routes.MapRoute(
name: "ProductRoute",
url: "{productName}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Now if i give some thing like this, localhost:56789/prd1/Home/Index
The first routing is working.
However if i directly access localhost:56789/Home/Index or any other controller action, like localhost:56789/Account/Login the routing is not working.
Is it because I have a {productName} defined?
For testing purpose how can I add few products like prd1, prd2 along with routing?
Routes are matched against the request in the order they are defined. When a route matching the request is found, no further routes are considered. Thus, you need to list your routes in order of decreasing specificity.
However, your first route matches more requests than your second route, i.e. it is less specific than the second route:
When ASP.NET MVC tries to match the request for Home/Index to your routes, it will match the first route because it will consider Home to be the productName, it will consider Index to be the controller name and the rest of the parameters are not required.
You need to reorder your routes or make the first route more specific. This could be done by putting constraints on the productName parameter.
UPDATE
Without knowing anything about your products and their names, it is impossible for me to suggest an appropriate constraint. Maybe you could use a numeric SKU and have a constraint like
routes.MapRoute(
name: "ProductRoute",
url: "{productName}/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { productName = #"\d+" }
);
forcing productName to be numeric.
Alternatively, you could change the url to
"products/{productName}/{controller}/{action}/{id}"
For more on constraints see this link or use Google.
For route configuration
routes.MapRoute(
name: "ProductRoute",
url: "{productName}/{controller}/{action}/{id}",
defaults: new { productName = 'put your method name to get productName over here', controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "your namespace of controller" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Multiple types found routing error even though a namespace is specified

related:
Multiple types were found that match the controller named 'Home'
Multiple types were found that match the controller named 'Home' - In two different Areas
Multiple types were found that match the controller named 'FW'.
The request for 'FW' has found the following matching controllers:
app.Controllers.Admin.FWController
app.Areas.Manage.Controllers.FWController
I tried the suggestions from those related links. I attempted to differentiate the controllers by using different namespaces:
global.asax.cs
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional },
new string[] { "app.Controllers" }
);
routes.MapRoute(
"Default_Admin_Top", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional },
new string[] { "app.Controllers.Admin" }
);
in the manage area ManageAreaRegistration
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Manage_default",
"Manage/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new string[] { "app.Areas.Manage.Controllers" }
);
}
I also looked in the bin folder for an old version but there was only the current one.
What am I missing? It seems like this should work.
The issue appears to revolve around the fact that I gave my controller its own namespace without it being in its own area:
namespace app.Controllers.Admin
{
public class FWController : Controller{}
}
Removing the .Admin from the namespace here will remove the collision and also the error, but I do not fully understand why.
can you try and rearrage your rotes like this. The problem might be arising because app.Controllers.Admin lies in app.Controller
routes.MapRoute(
"Default_Admin_Top", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional },
new string[] { "app.Controllers.Admin" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional },
new string[] { "app.Controllers" }
);
it looks similar to an issue which i have faced lately.
according to your scenario and having experienced the same issue, i suspect the problem would be the naming convention with controllers. Say for instance, your application has a controller named FWController in your root structure before re-structuring/maintaining your code in separate areas. when your application starts, the Application_Start() method inside Global.asax file registers route to route collection table (one of the core features of MVC 3 pattern) which maintain your incoming request when an action method executes inside a controller.
problem arises when you have a controller with same name like in your case FWController and directory structure of area somehow mimics the root directory just as you see in one of the referenced urls.
I implemented the similar solution as one of the URL justifies, i.e.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, //Parameter defaults
new []{"MyProject.WWW.Controllers"}
);
i did not touch my area registration.cs file at all.
When you rename the namespace, your routing starts pointing to the app.Controllers.FWController (not in app.Areas.Manage.Controllers.FWController), which resolved the conflict that was occurring before because you specified this in your Global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional },
new string[] { "app.Controllers" }
);
that request also neglects the MapRoute that contains .admin namespace. That could possibly be the reason i believe. Hope it helped you.

How can I create a friendly URL in ASP.NET MVC?

How do I generate friendly URLs within the ASP.NET MVC Framework? For example, we've got a URL that looks like this:
http://site/catalogue/BrowseByStyleLevel/1
The 1 is Id of the study level (Higher in this case) to browse, but I'l like to reformat the URL in the same way StackOverflow does it.
For example, these two URLs will take you to the same place:
https://stackoverflow.com/questions/119323/nested-for-loops-in-different-languages
https://stackoverflow.com/questions/119323/
EDIT: The friendly part of the url is referred to as a slug.
There are two steps to solve this problem. First, create a new route or change the default route to accept an additional parameter:
routes.MapRoute( "Default", // Route name
"{controller}/{action}/{id}/{ignoreThisBit}",
new { controller = "Home",
action = "Index",
id = "",
ignoreThisBit = ""} // Parameter defaults )
Now you can type whatever you want to at the end of your URI and the application will ignore it.
When you render the links, you need to add the "friendly" text:
<%= Html.ActionLink("Link text", "ActionName", "ControllerName",
new { id = 1234, ignoreThisBit="friendly-text-here" });
This is how I have implemented the slug URL on my application.
Note: The default Maproute should not be changed and also the routes are processed in the order in which they're added to the route list.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional
} // Parameter defaults
);
routes.MapRoute("Place", "{controller}/{action}/{id}/{slug}", new { controller = "Place", action = "Details", id = UrlParameter.Optional,slug="" });
you have a route on the global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = ""}
// Parameter defaults )
you can define your own route like :
controller is the cs class inside the the controllers folder.
you can define your id - with the name you choose.
the system will pass the value to your actionResult method.
you can read more about this step here : http://www.asp.net/learn/mvc/tutorial-05-cs.aspx

Categories

Resources