I tried implementing Phil's Areas Demo in my project
http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx.
I appended the Areas/Blog structure in my existing MVC project and I get the following error in my project.
The controller name Home is ambiguous between the following types:
WebMVC.Controllers.HomeController
WebMVC.Areas.Blogs.Controllers.HomeController
this is how my Global.asax looks.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapAreas("{controller}/{action}/{id}",
"WebMVC.Areas.Blogs",
new[] { "Blogs", "Forums" });
routes.MapRootArea("{controller}/{action}/{id}",
"WebMVC",
new { controller = "Home", action = "Index", id = "" });
//routes.MapRoute(
// "Default", // Route name
// "{controller}/{action}/{id}",// URL with parameters
// new { controller = "Home", action = "Index", id = "" }
// // Parameter defaults
//);
}
protected void Application_Start()
{
String assemblyName = Assembly.GetExecutingAssembly().CodeBase;
String path = new Uri(assemblyName).LocalPath;
Directory.SetCurrentDirectory(Path.GetDirectoryName(path));
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new AreaViewEngine());
RegisterRoutes(RouteTable.Routes);
// RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
}
If I remove the /Areas/Blogs from routes.MapAreas, it looks at the Index of the root.
In ASP.NET MVC 2.0, you can include the namespace(s) for your parent project controllers when registering routes in the parent area.
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" },
new string[] { "MyProjectName.Controllers" }
);
This restricts the route to searching for controllers only in the namespace you specified.
Instead of WebMVC.Areas.Blogs and WebMVC, use WebMVC.Areas.Blogs and WebMVC.Areas.OtherAreaName. Think of the area name as the namespace root, not an absolute namespace.
You can prioritize between multiple controllers with the same name in routing as follows
E.g., I have one controller named HomeController in Areas/Admin/HomeController
and another in root /controller/HomeController
so I prioritize my root one as follows:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", // Parameter defaults
id = UrlParameter.Optional },
new [] { "MyAppName.Controllers" } // Prioritized namespace which tells the current asp.net mvc pipeline to route for root controller not in areas.
);
Related
I have two routes in my routeConfig files as follow.
Route with admin prefix which handles request for admin part
default Route without a prefix, for which I have added a datatoken to map routes in candidate Area
routes.MapRoute(
name: "admin",
url: "Admin/{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional },
namespaces: new[] { "abc.namespace1" }
);
routes.MapRoute(
name: "default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional },
namespaces: new[] { "abc.namespace2" }
).DataTokens.Add("area", "Candidate");
But the problem is when i type in a url localhost/MyApp/Admin/Home/Index
it is hitting the controller in abc.namespace1 (which is expected) and localhost/MyApp/Home/Index also hitting Home controller inside abc.namespace1 instead of HomeController inside abc.namespace2 in candidate Area.
What i want to do here is handle all routes with Admin prefix with controllers inside abc.namespace1 and all routes without any prefix with controllers inside abc.namespace2 which is my candiate Area.
regards
I believe this might have something to do with the way you have specified your namespaces. The namespace must be for where the controller classes reside.
The pattern is typically <namespace of area>.<area name>.<controller namespace>
For example, in a project with an area named "Admin", the namespace must be:
"MvcMusicStore.Areas.Admin.Controllers"
In my experience, the conventions for how areas are set up are pretty strict. You should not set up the route in an AreaRegistration rather than the root of your project in order to get it to work.
public class CandidateAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Candidate";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Candidate_default",
"{controller}/{action}/{id}",
new { controller = "Account", action = "Login", id = UrlParameter.Optional },
new string[] { "<project name>.Areas.Candidate.Controllers" }
);
}
}
Areas are convention-based. If you deviate too far from the anticipated conventions, they simply don't function.
My area is below. Only the concerned part is highlighted.
Route Table
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"SubFolder", // Route name
"SubFolder/ChildController",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
}
This only works when the url is like this
localhost:2474/SOProblems/ChildController/index
This does not works when the url is like this
localhost:2474/SOProblems/SubFolder/ChildController/index
Can you please tell me what is missing?
This does not works when the url is like this
localhost:2474/SOProblems/SubFolder/ChildController/index
That's normal. You route pattern looks like this: SubFolder/ChildController and not SubFolder/ChildController/index. In addition to that you defined your route in the WRONG place. You defined it in your main route definitions and not in your area route definitions. So get rid of the custom route definition from your main routes and add it to the SOProblemsAreaRegistration.cs file (which is where your SOProblems routes should be registered):
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"SubFolderRoute",
"SOProblems/SubFolder/ChildController",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" }
);
context.MapRoute(
"SOProblems_default",
"SOProblems/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
Also since your route pattern (SOProblems/SubFolder/ChildController) doesn't have the possibility to specify an action name, you can only have one action on this controller and that would be the default action that you registered (index) in this case.
If you wanted to have more actions on this controller and yet index be the default one you should include that in your route pattern:
context.MapRoute(
"SubFolder",
"SOProblems/SubFolder/ChildController/{action}",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" }
);
In both cases your main route definition could remain with their default values:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index" }
);
}
Your new route "SubFolder" does not include the possibility of including an action in the route (in your case, "Index").
Your sample URL
localhost:2474/SOProblems/SubFolder/ChildController/index
Wants to try to match a route like:
"SubFolder/ChildController/{action}"
But you don't include the "{action}" in your route, so it won't match your route. It then tries the default route, which obviously fails.
Try adding "{action}" to your route:
routes.MapRoute(
"SubFolder", // Route name
"SubFolder/ChildController/{action}",
new { controller = "ChildController", action = "Index" },
new[] { "Practise.Areas.SOProblems.Controllers.SubFolder" });
or take "index" off your test URL.
For any future users looking to do this; Look into using Areas.
Here's a helpful video.
Organizing an application using Areas
I'm learning about creating custom routes in ASP.NET MVC and have hit a brick wall. In my Global.asax.cs file, I've added the following:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
// My Custom Route.
routes.MapRoute(
"User_Filter",
"home/filter/{name}",
new { controller = "Home", action = "Filter", name = String.Empty }
);
}
The idea is for me to able to navigate to http://localhost:123/home/filter/mynameparam. Here is my controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Filter(string name)
{
return this.Content(String.Format("You found me {0}", name));
}
}
When I navigate to http://localhost:123/home/filter/mynameparam the contoller method Filter is called, but the parameter name is always null.
Could someone give a pointer as to the correct way for me to build my custom route, so that it passes the name part in the url into the name parameter for Filter().
The Default route should be the last one.
Try it this way:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// My Custom Route.
routes.MapRoute(
"User_Filter",
"home/filter/{name}",
new { controller = "Home", action = "Filter", name = String.Empty }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
I believe your routes need to be the other way round?
The routes are processed in order, so if the first (default, OOTB) route matches the URL, that's the one that'll be used.
I have a site that uses Ninject for dependency injection and I have Routing defined within a Bootstrapper class like so:
public void RegisterRoutes()
{
Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
Routes.MapRoute(
null,
"{pageTitle}",
new { controller = "Home", action = "Page", pageTitle = "Index" }
);
Routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
I have added an Area to the project but the default AdminAreaRegistration is not registering the root
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Where or how do I register the Area with Ninject?
The sample project comming with the source code has now an area. Take a look at it. https://github.com/ninject/ninject.web.mvc/zipball/master
are you calling RegisterAllAreas()?
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
note it must be called before RegisterRoutes().
Have you resolved this issue?
I have the problem where my NinjectControllerFactory is not resolving urls that reference controllers defined in areas. I get the following message:
The IControllerFactory 'myWebSite.WebUI.Infrastructure.NinjectControllerFactory' did not return a controller for the name 'admin'.
If I move the controller to the root Controllers folder, it will resolve the url.
I'm trying to add a route that shows some data based on a string parameter like this:
http://whatever.com/View/078x756
How do I create that simple route and where to put it?
In your global.asax.cs file, you add the following lines:
routes.mapRoute(
// The name of the new route
"NewRoute",
// The url pattern
"View/{id}",
// Defaulte route data
new { controller = "Home", action = "Index", id = "078x756" });
Make sure you add them before the registration of the default route - the ASP.NET MVC Framework will look throught the routes in order and take the first one that matches your url. Phil Haack's Routing Debugger is a valuable tool when troubleshooting this.
Routes are usually configured in the Application_Start method in Global.asax. For your particular case you could add a route before the Default one:
routes.MapRoute(
"Views",
"View/{id}",
new
{
controller = "somecontroller",
action = "someaction",
id = ""
}
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new
{
controller = "home",
action = "index",
id = ""
}
);
Routes are added in the global.asax.cs
Example of adding a route:
namespace MvcApplication1
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
routes.MapRoute(
"WhatEver"
"{View}/{id}",
new {controller = "Home","action = "Index", id="abcdef"}
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
}