Default Controller for an Area? - c#

This is sort of a duplicate of Trouble setting a default controller in MVC 2 RC Area
But his answer doesn't satisfy me, because it doesn't work.
I have the following
/Areas/TestArea/Controllers/HelloController
/Areas/TestArea/Views/Hello/Index
/Controllers/HomeController
/Views/Home/Index
With the following routes:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default2", // Route name
"TestArea/{controller}/{action}/{id}", // URL with parameters
new { controller = "Hello", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
I added the second one to try and get http://servername/TestArea to work as if it were http://servername/TestArea/Hello but was met with no success. The basic http://servername/ works as intended.
So the question is: how do you return a default controller in an area?
Edit: I have uploaded a sample project to show what I mean: http://beginningasp.net/TestAsync.zip

Try to register Default2 route before the default route and set area=yourareaname in the default values
routes.MapRoute(
"Default2", // Route name
"TestArea/{controller}/{action}/{id}", // URL with parameters
new { controller = "Hello", action = "Index",area="TestArea", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

Related

Routing config issue cannot be resolved

Given this URL's
http://localhost:51095/Person // This is equivalent to this one Person/Index
http://localhost:51095/Person/Allan
I setup a route config for it as follows :
routes.MapRoute(
"Person",
"Person/{personName}",
new { controller = "Person", action = "Person", personName = UrlParameter.Optional }
)
;
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
First URL should follow the Default route and the second should follow the Person route.
This is not working because the first config seems to catch all these URL's
The first thing I'd do is remove personName = UrlParameter.Optional in the first Route. This would allow only urls that provide a personName value to access this Route. If no value is provided, it should fall through to the default Route.
But you'd want to think about the future with this strategy: if you implement new actions on that Person controller, you'd need to add a new Route for each of them. If you had a new 'Edit' action for example:
routes.MapRoute(
"Person_Edit",
"Person/Edit/{personName}",
new { controller = "Person", action = "Edit" }
)
You'd want to add these new Routes before the first one though - ordering/precedence of Routes is important.

How do I force a redirect with a parameter?

I have a parameter value which I have to URL encode. Therefore my understanding is that it must be sent as a query string on the end of the URL rather than part of the main URL. I have successfully tested this by directly pasting the URL into the browser.
I am trying to redirect to a URL of:
Server/Application/Area/Controller/Action/?id=xyz
But when I use
return RedirectToAction("Action", "Controller", new { area = "Area", id = Url.Encode(uniqueId) });
I am sent to
Server/Application/Area/Controller/Action/xyz
How do I stop this happening?
It happens because of your default route is;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Site", action = "Index", id = UrlParameter.Optional }
);
if you want to keep using this route, you should be have to change your id parameter in your url.
But if id parameter is omitted from the default route, your action redirected as you expect.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Site", action = "Index"}
);
Remove id from Default Route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
or change the name of your parameter from id to something else.
I hope this will help.

MVC 4 routing "finding" controllers inside an Area

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
);

Add routing rules in MVC app

I am trying to write a rule to map a URL but so for I did not get the results I want. I have this rule so far:
routes.MapRoute(
"Search", // Route name
"{controller}/{action}/{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", product = UrlParameter.Optional, page = UrlParameter.Optional } // Parameter defaults
);
using this I can achieve this result so far:
localhost:8493/home/search/myproduct
localhost:8493/home/search/myproduct/2
but i want to do something like this:
localhost:8493/myproduct
so this will route to home/search/myproduct
I have tried the following but it didn't work:
routes.MapRoute(
"DirectSearch", // Route name
"{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", } // Parameter defaults
);
Is there a way to do this?
Add:
So Here i added the specific route to map to another action but it doesn't work:
routes.MapRoute(
"Tuna",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Tuna", id = UrlParameter.Optional }
);
You're close I think. This should work;
routes.MapRoute(
"Search", // Route name
"{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", product = UrlParameter.Optional, page = UrlParameter.Optional } // Parameter defaults
);
Just remember that the framework will read the route data from top to bottom and use the first one it finds that matches. So make sure the more specific routes are listed before the more general ones
Edit
Here's a link to a discussion on custom routing

MVC3 Routes with areas... a little confusion

I have an MVC3 site with 2 areas plus the common area. I also have a route specified for paginating lists of items. My Register_Routes method looks like so:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Paginate", // Route name
"{controller}/Paginate/{itemsPerPage}/{pageNumber}/{searchString}", // URL with parameters
new { controller = "Home", action = "Index", itemsPerPage = SiteSettings.ItemsPerPage, pageNumber = 1, searchString = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
What I've noticed (and don't understand) is if I log out from my home page, the redirect from my login page looks like
http://localhost:62695/Account/LogOn?ReturnUrl=%2fHome%2fPaginate
... and upon logging in, I end up on my home page, except with a URL of:
http://localhost:62695/Home/Paginate
I'm fairly certain at this point that I've screwed something up with the route map, but it seems right to me. What am I doing wrong?
UPDATE
per suggestion, I changed my routes to look like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Paginate", // Route name
"{controller}/Paginate/{itemsPerPage}/{pageNumber}/{searchString}", // URL with parameters
new { controller = "Home", action = "Index", searchString = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
... and the home index pages do indeed seem to work properly, but now the paginates don't:
return RedirectToAction("Paginate", new { itemsPerPage = SiteSettings.ItemsPerPage, pageNumber = 1, searchString = string.Empty });
in a Admin\HomeController yields the URL:
http://localhost:62695/Admin/Users/Paginate?itemsPerPage=25&pageNumber=1
so I'm still doing something wrong here.
UPDATE 2
OK, this is how I got it to work the way I wanted it to:
My RegisterRoutes method now looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
null,
"{area}/{controller}/Paginate/{itemsPerPage}/{pageNumber}/{searchString}", // URL with parameters
new {area = string.Empty, controller = "Home", action="Paginate", searchString = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{area}/{controller}/{action}/{id}", // URL with parameters
new {area = string.Empty, controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
... but this was not enough to fix the routing issues. Additionally to this, I needed to add the route to my area registrations. My AdminAreaRegistration looks like this:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
null,
"Admin/{controller}/Paginate/{itemsPerPage}/{pageNumber}/{searchString}", // URL with parameters
new { controller = "Home", action = "Paginate", searchString = UrlParameter.Optional } // Parameter defaults
);
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
This, in addition to changing to RedirectToRoute for my connections, made my URLs all pretty and working at the same time. All the answers helped to get to my goal, I +1'd everyone and chose the answer that got me closest to the path.
Routes are evaluated in the order they are registered. The redirects are being generated by the first route that you registered, especially since you declared default values for all of the segments. You might want to consider defining a more specific route
UPDATE
Use RedirectToRoute instead of RedirectToAction to get your desired URL generation
RedirectToRoute("Paginate", new { itemsPerPage = SiteSettings.ItemsPerPage, pageNumber = 1, searchString = string.Empty });
routes.MapRoute(null, // do not name your routes, it's a "magic string"
"{controller}/Paginate/{itemsPerPage}/{pageNumber}/{searchString}",
new
{
controller = "Home",
action = "Index",
searchString = UrlParameter.Optional
}
);
// instead of RedirectToAction, try RedirectToRoute, and do not use the route name
return RedirectToRoute(new
{
controller = "Home",
area = "AreaName",
itemsPerPage = SiteSettings.ItemsPerPage,
pageNumber = 1,
searchString = string.Empty,
}
);
Well, the reason you return to the URL http://localhost:62695/Home/Paginate is because when you log in you return to the URL specified, namely the ?ReturnUrl=%2fHome%2fPaginate part of http://localhost:62695/Account/LogOn?ReturnUrl=%2fHome%2fPaginate. Is that not the URL of your home page? You never specified.
It could be that the first definition takes precedence also, not sure where I heard that, so maybe if you put the default definition first it will grab that.

Categories

Resources