Route to controller - c#

I have a controller called Admin with a number of Actions. In the URL, they look like this:
http://www.website.com/Admin/Users/1
http://www.website.com/Admin/Roles/123
Is there anyway to alias out so that:
http://www.website.com/Users/1
http://www.website.com/Roles/123
Automatically goes to the right controller?
Regards.

Not without interfering with the default route, unless you are not going to use the names Users or Roles anywhere else. If that is the case, you can just add
routes.MapRoute(
"AdminUsers",
"Users/{id}",
new { controller = "Admin", action = "Users", id = "" });
routes.MapRoute(
"AdminRoles",
"Roles/{id}",
new { controller = "Admin", action = "Roles", id = "" });
to your Global.asax.cs file.

Related

How can I specify the namespace for which controller to call in HtmlHelper.Action(string, string, object)?

I have two controllers with identical names, one of which lives in the "Admin" area and one in the default area (which I believe resolves as an empty string for area).
The following call:
HtmlHelper.Action("Action", "DuplicateController", new { parameterValue = "test" } );
Doesn't appear to be able to resolve the difference between my ProjectA.Controllers.DuplicateController and ProjectB.Controllers.DuplicateController, even if I specify the area as "" by adding it as follows:
HtmlHelper.Action("Action", "DuplicateController", new { parameterValue = "test", area = "" } );
I know I should be able to resolve this by specifying a route when I register them on application startup, but is it possible to specify a fully-qualified namespace directly to the controller I know I need to call right in the action method?
e.g. something like the following would solve my problem:
HtmlHelper.Action("Action", "ProjectB.Controllers.DuplicateController", new { parameterValue = "test" } );
Like you suggested, I believe you'll have to add namespaces to the routes for both of your ambiguous controllers in your RouteConfig.cs file and your AdminAreaRegistration.cs file. For an example, see this StackOverflow post.
So, you can either add the "namespaces" argument to the default route as in the above post or create a route for each "Duplicate" controller.
In your RouteConfig.cs:
routes.MapRoute(
name: "Duplicate",
url: "Duplicate/{action}/{id}",
defaults: new { controller = "Duplicate", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MyMvcApplication.Controllers" }
);
And in your AdminAreaRegistration.cs:
context.MapRoute(
"Admin_Duplicate",
"Admin/Duplicate/{action}/{id}",
new { controller = "Duplicate", action = "Index", id = UrlParameter.Optional },
new[] { "MyMvcApplication.Areas.Admin.Controllers" }
);

Removing route element in .net mvc

What is the way to remove this route from the routecollection ? I have modular system and one module needs to override the route but when I write a new route with same name, it says
A route named 'HomePage' is already in the route collection. Route names must be unique.
Parameter name: name
//home page
routes.MapLocalizedRoute("HomePage",
"",
new { controller = "Home", action = "Index"},
new[] { "Test.Web.Controllers" });
This is module
*So first I need to remove HomePage route if it exists and add new one like below ? But I dont know how to remove it
routes.MapLocalizedRoute("HomePage",
"",
new { controller = "TwoStepCheckout", action = "Index" },
new[] { "Test.Plugin.TwoStepCheckout" });
You can remove it by doing:
RouteTable.Routes.Remove(RouteTable.Routes["HomePage"]);

How do I redirect to an other area in MVC3?

I have 3 areas at the moment (more will come when I get this working): Login, User and Admin. The Default route in Global.asax go to the index action of the index controller in the login area (Login\Index\Index) which works fine, this is how I mapped that:
routes.MapRoute(
"Default", // Route name
"{area}/{controller}/{action}/{id}", // URL with parameters
new { area = "Login", controller = "Index", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new[] { typeof(AppName.Areas.Login.Controllers.IndexController).Namespace }
);
each of the 3 areas is registered like this in the AreaRegistration files:
context.MapRoute(
"Admin_default",
"{area}/{controller}/{action}/{id}",
new { area = "Admin", controller = "Index", action = "Index", id = UrlParameter.Optional },
new[] { typeof(AppName.Areas.Admin.Controllers.IndexController).Namespace }
);
The Login controllers index action takes the users login details, looks up the type of user and redirects them to the appropriate area...... at least it should do. From what I can gather searching google, the correct way to redirect to a specific area is this:
return RedirectToAction("Action", "Controller", new { area = UserType });
which doesn't seem to work, it just redirects to Login\Controller\Action and I can't work out why.
In my attempts to work out what was happening I used this:
var url = Url.Action("Action", "Controller", new { area = "Admin" });
which produced the same Login\Controller\Action url.
Any help fixing this would be greatly appreciated
In the routes parameter, you just set new { area = "OtherAreaName" }.
EDIT
Oh, I see you already tried that. I suppose the name of that area is correctly referenced and correctly named in the class AreaRegistration class, like this?
public class AuthorAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Author";
}
}
// ...
}
Could it also be that you need authentication and you are being redirected to the login page?

ASP.NET MVC Routing using ID or action name

I have an ASP.Net application which has an area called 'Customers'. This area has a controller with the same name with a single method called Index.
I have the following route defined:
context.MapRoute(null,
"Customers/{controller}/{action}",
new { controller = "customers", action = "Index" }
);
This allows my to navigate to use the following URL to navigate to the index method on my Customers controller.
MyDomain/Customers
In my customer area I also have another controller called products. This has a number of methods that allow me to work with product entities (mostly auto-generated by Visual Studio at the moment).
With my current route I can navigate to the products controller using URL's like this:
MyDomain/Customers/Products (shows the index page of the products
controller) MyDomain/Customers/Products/Create (Shows a page to add
new products). MyDomain/Customers/Products/Details?id=1234 (Show the
product with the id of 1234)
Now what I want to be able to do is navigate to the details page with a much more user friendly URL such as:
MyDomain/Customers/Products/1234
I have defined a new route that look like this:
context.MapRoute(null,
"Customers/Products/{id}",
new { controller = "Products", action = "Details" }
);
The route is defined before the first route I demonstrated.
This allows me to navigate to the products page as I want, however I can no longer navigate to other methods on my products controller.
E.G. The following URL
MyDomain/Customers/Products/Create
Gives me the following error:
The parameters dictionary contains a null entry for parameter 'id' of
non-nullable type 'System.Int32' for method 'System.Web.Mvc.ViewResult
Details(Int32)'
If I change the order of the routes then I can navigate to all the methods on my products controller but my details URL reverts to the old format of having a query parameter.
If I update the route to look like this:
context.MapRoute(null,
"Customers/Products/{id}",
new { controller = "Products", action = "Details", id = UrlParameter.Optional }
);
Then I still get the same problem.
Can anyone tell me how to structure my routes to get the result I want? In summary:
If I navigate to the Customers area I want my URL to look like 'MyDomain/Customers'
If I navigate to the product details page I want my URL to look like "MyDomain/Customers/Products/1234".
If I navigate to any other product page I want my URL to look like 'MyDomain/Customers/Products/Create'
If the ID is always going to be an int then you can add a constraint to the route like this:
context.MapRoute(null,
"Customers/Products/{id}",
new {controller = "Products", action = "Details", id = UrlParameter.Optional},
new {id = #"\d+"} // Constraint to only allow numbers
);
Try something like this:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Products_Details",
"Customers/Products/{id}",
new { controller="Products", action="Details" },
new { id = #"\d+" }
);
context.MapRoute(
"Customers_default",
"Customers/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
Update: added constraint on route.
Explanation: The first route maps to your details page and forces the user to provide an id that has the format of numbers (the last parameter in the first MapRoute). If the id doesn't have the format \d+ it will not match the route and the default will be used. This will give you the following routes:
Customers\Products (index)
Customers\Products\1234 (details of 1234)
Customers\Products\Create (create page for products)
Customers\Products\Edit\1234 (edit page for 1234)
try this
context.MapRoute(
"Customers_Products",
"Customers/Products/{productId}",
new { controller = "Products", action = "Details", productId= UrlParameter.Optional }
);
context.MapRoute(null,
"Customers/{controller}/{action}",
new { controller = "customers", action = "Index" }
);
If you want to keep your existing routes, try doing this:
context.MapRoute(null,
"Customers/Products/{id}", // id is optional, so Customers/Products might reasonably return all products
new { controller = "Products", action = "Details", id = UrlParameter.Optional },
new {id = #"\d+"} // must be numeric if present
);
context.MapRoute(null,
"Customers/Products/{action}/{id}", // Id is optional, so this needs an action.
new { controller = "Products", action = "Details", id = UrlParameter.Optional }
// maybe the id is not numeric for all actions? I don't know so I won't constrain it.
);
context.MapRoute(null,
"Customers/{controller}/{action}", // Default Customers route
new { controller = "customers", action = "Index" }
);
The first two deal with a URL like /Customers/Products/... with one or two other parts and the last one deals with anything else starting with /Customers/

Why is the wrong route being used?

I am trying to do what SO does for its Question controller.
/Posts/{id}/{title} when viewing a post (action name not shown)
/Posts/New when you are posting something new.
/Posts/Delete/10 etc....
I have two routes set up (well, one if you don't count the default). What appears to be happening is all actions in the Post controller are being routed through the first one.
What is that? I obviously have it wrong, but I can't figure this out.
routes.MapRoute("ViewPosts",
"Posts/{postid}/{title}",
new { controller = "Posts", action = "View", postid = "", title = "" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
The first route handles all your requests which starts from /Posts.
You need to use constraints to allow {postid} be only number:
routes.MapRoute("ViewPosts",
"Posts/{postid}/{title}",
new { controller = "Posts", action = "View", postid = "", title = "" },
new { postid= #"\d+" });
In this case only if numeric Id is provided this route will handle it, otherwise "Default" route will handle.
All routes are going through the first because you have not specified that the postid field can only be numeric, or defined an earlier route that will catch /Posts/New. It is passing New as the postid with the View action.
You can add this route definition before the ones you have now:
routes.MapRoute("NewPost",
"Posts/New",
new{controller="Posts", action="New"});
Or whatever the appropriate controller/action would be.

Categories