I am working on asp.net mvc 3. I am trying to implement the project with areas. i am facing problems with routing. I have folder structure like, projectName/areas/Dashboard/ and in my DashboardAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Default_Dashboard",
"Dashboard/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
so my routing looks like, localhost:56788/Dashboard/Dashboard/Index here i need my routing should looks like localhost:56788/Dashboard/Index for that i have written like,
context.MapRoute(
"Default_Dashboard",
"Dashboard/{action}/{id}",
new { area = "Dashboard", controller = "Dashboard", action = "PatientPortal", id = UrlParameter.Optional },
new[]{typeof(Controllers.DashboardController).Namespace}
);
context.MapRoute(
"Default_Dashboard",
"{controller}/{action}/{id}",
new { area = "Dashboard", controller = "Dashboard", action = "PatientPortal", id = UrlParameter.Optional },
new[]{typeof(Controllers.DashboardController).Namespace}
);
but no use none of them doesnt work for me that means it shows resource not found error. please guide me.
Try install the Route Debugger nuget package it may help you see why things aren't matching
Related
I have an MVC 5 site with this structure:
example.com
example.com/area1 (index for whole section)
example.com/area2/item5 (specific item for section)
For SEO reasons I'd like to change every URL to this:
example.com/keyword (redirected from example.com)
example.com/keyword/area1
example.com/keyword/area2/item5
The keyword is fixed and always the same, though at some point in the future there may be a site with the same structure but different content with a different keyword in. That is probably at least a few months off though.
What is the quickest / easiest way to implement the above. Being able to get the name of keyword would be an advantage later though isn't essential right now.
I could use attribute routing, though I'd have to update A LOT of ActionMethods to do this - and most currently don't even use attribute routing.
thx.
Update
I've tried adding the below to RouteConfig.cs, but none of the Url's work for some reason:
routes.MapRoute(
name: "Default",
url: "keyword/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
string keyword = "keyword";
// keyword route - it will be used as a route of the first priority
routes.MapRoute(
name: "Defaultkeyword",
url: "{keyword}/{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
keyword = keyword
});
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
also you need to add this Defaultkeyword route with few changes into your Area1AreaRegistration.cs file
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Area1_defaultKeyword",
"{Keyword}/Area1/{controller}/{action}/{id}",
new { Keyword = "Keyword", controller = "HomeArea1", action = "Index", id = UrlParameter.Optional }
);
context.MapRoute(
"Area1_default",
"Area1/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
I created two areas (with controllers, views, registration, etc) with VS's scaffolding process. One for homecontroller and one called account.
I added a single line "route.DataTokens" to the routeconfig.cs file to connect to the homecontroller on startup.
var route = routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional }
);
route.DataTokens["area"] = "Home";
Here is my HomeAreaRegistration.cs RegistrationArea method
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Home_default",
"Home/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
But in the url of the browser I see
https://localhost:44301/Home/Home/Index
What I want to see is
https://localhost:44301/Home/Index
What do I modify to get this?
Edit - Solved! I think.
Here is what I did.
In HomeArearegistration.cs I removed the Home/
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Home_default",
"{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
Is this the proper way to go about doing this because something doesn't seem right here, if I type
https://localhost:44301/Home/Index.cshtml
which I would expect to take me to the home page, I get a HTTP 404 error not found but if I type
https://localhost:44301/Home/Index
It take me to the home page
To say that routing is not my strong suite is an understatement, so please bear with me.
I have this link in one of my pages and I need my MVC route to pick this up and map it to the
"MyArea" area
"MessagesController" controller
"Inbox" method
http://localhost/MyArea/messages/list.asp?pjid=&box=in&sf=mesibox
What I've come up with so far does not cut it.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("favicon.ico");
routes.MapRoute(
"Messages",
"messages/list.asp",
new
{
controller = "Messages",
action = "Inbox"
});
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new
{
controller = "Account",
action = "LogOn",
id = UrlParameter.Optional
}
);
Any help would be appreciated.
Thank you,
Stephen
UPDATE:
Darin answered a similar question here How to route legacy QueryString parameters in ASP.Net MVC 3? so that takes care of the query string parameters. Now to figure out the main segments.
You seem to have defined an area, so it is inside the routing configuration of this area that you may try adding that route and not inside global.asax:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/messages/list.asp",
new { controller = "messages", action = "inbox" }
);
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
Perhaps I do not understand correctly how MVC Areas work, but this has got me a little confused.
Add an Area called "MyArea" using right-click "Add Area" in Visual Studio on the MVC3 project
Create a controller for MyArea: "AnArea" with matching view in the MyArea area.
Add "controller = "AnArea" to context.MapRoute's defaults parameter in MyAreaAreaRegistration.RegisterArea method.
So at this point if you start the application and navigate to /MyArea/ it should load the AnArea controller with it's matching view. If you navigate to /MyArea/AnArea, it will show the same result.
But, if you navigate to /AnArea/, the controller is still found and the following error message is displayed:
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/anarea/Index.aspx
~/Views/anarea/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/anarea/Index.cshtml
~/Views/anarea/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
Is this the correct behaviour? I would have thought an area's controller could only be accessed via it's own area and not globally.
Whenever I create an project with areas, I change my Default route as follows:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // defaults
null, // constraints
new string[] { "MyApplication.Controllers" } // namespaces
);
The final parameter limits the default route to the controllers in the MyApplication.Controllers namespace. This insures that the Default route is limited to actions outside of any areas.
UPDATE
After a deep dive into the code, I discovered where the issue arises, and have a solution. Change your Default route to the following:
routes.Add(
"Default",
new Route("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
),
null,
new RouteValueDictionary(
new {
Namespaces = new string[] { "MyApplication.Controllers" },
UseNamespaceFallback = false
}
),
new MvcRouteHandler()
)
);
The key is in adding the UseNamespaceFallback token. This will prevent the Default route from looking into any other namespaces.
This is unexpected behavior, and it was a problem I was unaware of which affects a project I am working on. I will list it as an issue at aspnet.codeplex.com. I would not call this a bug, but the behavior definitely appears to breach the convetions for MVC routing.
You have to apply a namespace restriction in both area and general route.
In global.asax.cs you should edit RegisterRoutes method just like this
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "MyProject.Controllers" }
);
}
That will restrict "//" only to the namespace "MyProject.Controllers"
But also you´ll have to apply the namespace restriction to the Area to restrict "//" only to the namespace "MyProject.Areas.MyArea.Controllers"
For that you´ll have to edit "RegisterArea" method of "MyAreaAreaRegistration.cs" like below ("MyAreaRegistration.cs" is located at "/MyProject/Areas/MyArea" folder ) :
//Some default code stuff
...
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new string[] { "MyProject.Areas.MyArea.Controllers" }
);
}
Hope it helps!!
You seem to be navigating to /AnArea whereas your area is called MyArea so you should navigate to /MyArea/. Here's how the area route registration looks like:
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { controller = "AnArea", action = "Index", id = UrlParameter.Optional }
);
AnArea is the name of the controller, not the area. If you want to navigate to some controller of this area you should always prefix your url with MyArea which is the name of the area.
I have a MVC 2 site with an area, let's say the area name is {Admin}
The areas and the site works fine.
What I am trying to do is to have different default page for the area.
When I am calling http://webSiteName works with no problem
but for http://webSiteName/Admin I am getting the error
The resource cannot be found
I tried it out the solutions from ASP.NET MVC 2 RC 2 returns Area-specific controller when no area specified
but with no luck.
I tried also
routes.MapRoute(
"Admin",
"{controller}/{action}/{id}",
new { controller = "AdminHome", action = "index" },
new[] { "Web.Areas.Admin.Controllers" }
);
and
routes.MapRoute(
"Admin",
"Admin",
new { controller = "AdminHome", action = "index" },
new string[] { "Web.Areas.Admin.Controllers" }
);
but I am still getting The resource cannot be found.
What am I doing wrong?
Try this. Make sure it will be in /Areas/Admin/AdminAreaRegistration.cs when your Area is named Admin.
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "AdminHome",action = "Index", id = "" }
);
}
You don't have to add anything to your Global.asax.