i need some help.
I'm working with MVC 5, in VS 2015, and i want to configure some routes in my project.
First, i have a "Default" route, that is it:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Tipoou.Controllers" }
);
This route is used for the common actions, like:
localhost/auth/login or **localhost/sell/`
But, I have an Area, that the name is Company. And, I want to get the name company in the url, like this: localhost/companyname/{controler}/...
So, I did something like this (in the CompanyAreaRegistration.cs) :
context.MapRoute(
"Company_default",
"{company}/{controller}/{action}/{id}",
new { controller = "home", action = "Index", id = UrlParameter.Optional }
);
But, the Default route just stop working (thrown the 404 error). And, ALL the name that I put after localhost, it's calling the Company Area.
Can someone help me?
Can i do something like: try the Company route, if fail, try the Default?
Remove curly braces from company name in the template of route:
context.MapRoute("company_default",
"company/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
Also your controller class needed the following RouteAreaAttribute:
[RouteArea("company", AreaPrefix = "company")]
public class MyTestController : Controller
{
...
}
Related
I have hosted a ASP.NET MVC website on IIS 7.5. The problem is that the site name and controller name are same, due to this I have to enter the controller name twice.
I am not allowed to change the name of the site or controller. My current URL for eg.
local/home/home/action
but I have shared as
localhost/home/action
now I need to configure the application so that the application routes properly for
localhost/home/action
If you are using MVC5 you can use the Route attribute. Like so:
[Route(“yourroot”)]
public ActionResult Index() { … }
More information can be found here Attribute Routing in ASP.NET MVC 5
Hope this helps
Try to add a new route to RouteConfig.cs before others routes like:
routes.MapRoute(
name: "DefaultHome",
url: "{action}/{id}",
defaults: new { controller = "Home", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
...
I have a HomeController and it has many Actions in it. I would like users to visit my actions without typing Home. Here is the Route below
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I would like users not to enter controller name, which is Home in this case. How can I do that? Or is it mandatory?
You can add custom route before defult route like this:
routes.MapRoute(
"OnlyAction",
"{action}",
new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Solution 01 (attribute routing)
Add below line on the top of the other routes in RouteConfig
routes.MapMvcAttributeRoutes();
Then add an attribute route on top of each action as you want. (actions in the home controller in this case)
eg. Below code sample will remove "/Home" from http://site/Home/About and be available on http://site/About
[Route("About")]
public ActionResult About()
{
Solution 02 (using a Route constraint) [ Source ]
Add a new route mapping to RouteConfig as below. (Remember to add these specific routes before the default (generic) routes.
routes.MapRoute(
"Root",
"{action}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { isMethodInHomeController = new RootRouteConstraint<HomeController>() }
);
This will remove "Home" from all the actions (routes) of the Home controller
RootRouteConstraint class
public class RootRouteConstraint<T> : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var rootMethodNames = typeof(T).GetMethods().Select(x => x.Name.ToLower());
return rootMethodNames.Contains(values["action"].ToString().ToLower());
}
}
Optional Info: This line (constraint) will make sure to apply this routing only for the HomeController
new { isMethodInHomeController = new RootRouteConstraint<HomeController>
I've updated my code to use Area as suggested but the problem still exist. /dashboard is still available.
My Controllers folder has HomeController and AccountController. I have Areas/Admin/Controllers/DashboardController.cs
Problem:
My area admin controller can be accessed like this /admin/dashboard, but the problem is it can also be accessed using /dashboard -> this should show 404
here is my RouteConfig:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "project.Controllers" }
);
AdminAreaRegistration:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "project.Areas.Admin.Controllers" }
);
}
The /dashboard call is routed by the Default routing rule.
You can make the Default not to process the calls made to the dashboard controller by adding a constraint.
For example:
In the default routing rule you can add a constraint like the following:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "project.Controllers" },
constraints: new { controller = new Constraints.IsNotDashboard() }
);
Then, you can declare the constraint like this:
using System.Web;
using System.Web.Routing;
public class IsNotDashboard : IRouteConstraint
{
public IsNotDashboard()
{
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string controller = values["controller"].ToString().ToLower();
return controller != "dashboard";
}
}
With this constraint, all calls that match the dashboard controller will not be processed by the Default routing rule.
Thanks guys.
After searching the net, I finally found what works best for my problem.
The problem was that all controllers are being handled as well in Default route, so I just added controller constraints to Default. This way Default route will only accept request on specified controllers. Below is my new RouteConfig
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { controller = #"(Account|Manage|Home)" }
);
I have an action in my HomeController like this:
public ActionResult HowItWorks()
{
return View();
}
I can access this by going to /Home/HowItWorks as you might expect.
How can I make it so that it will go to the same place if I go to /HowItWorks (omitting the "Home" prefix)?
I know I can change this in RouteConfig.cs but I was wondering if there was an attribute or something like that.
routes.MapRoute(
name: "HowItWorks",
url: "HowItWorks",
defaults: new { controller = "Home", action = "HowItWorks", id = UrlParameter.Optional }
);
You can do it as above. and yes, you need to put it in RouteConfig.cs
If you want all your methods work like that you can use following:
routes.MapRoute(
name: "HomePages",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
In this case though, you can use a single controller only, if and only if you dont define a custom route as follows:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Note that precedence of routes matters. ie: whichever is matched first will be embraced.
I know I can change this in RouteConfig.cs but I was wondering if
there was an attribute or something like that.
Take a look at AttributeRouting, it's pretty cool.
I would like to specify my routing tables such that they would feel much more "natural"
/Products
/Product/17
/Product/Edit/17
/Product/Create
Close to the defaults configuration but such that "Index" action would be mapped to the multiples form of the controller name and "Details" action would be mapped directly with an id of the item directly following the controller name.
I know I can achieve this by explicitly defining special routing mappings like this:
routes.MapRoute(
"ProductsList",
"Products",
new { controller = "Product", action = "Index" }
);
routes.MapRoute(
"ProductDetails",
"Product/{id}",
new { controller = "Product", action = "Details" }
);
/*
* Ditto for all other controllers
*/
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The code above is way too verbose for my tastes and has the downside that each controller needs to be mentioned at least twice to prevasively apply this url pattern.
Is there some way to generalize this or am I bound to manual labour in this case?
You can try something like this:
routes.MapRoute(
"ProductsList",
"{pluralizedControllerName}",
new { controller = "Home", action = "Index" },
new { pluralizedControllerName = new PluralConstraint() }
);
routes.MapRoute(
"ProductDetails",
"{controller}/{id}",
new { controller = "Home", action = "Details" },
new { id = #"\d+" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Notice the constraint in second route, it ensures that /Product/Create doesn't get picked by second route so that it gets mapped as third.
For route testing you can use routedebugger, and for writing unit test for routes try MvcContrib-TestHelper. You can get both with NuGet.
EDIT:
You can use this simple pluralizer and then implement something like this:
public class PluralConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
List<string> names = GetControllerNames();//get all controller names from executing assembly
names.ForEach(n => n.Pluralize(n));
return names.Contains(values[parameterName]);
}
}