I couldn't get any good information on how to define a route to a contrete action in the selected controller. MSDN doesn't provide clean information on this. There is a mention of action parameter but it doesn't seem to be working.
What I want to achive is to route path like /vehicles/check*** to Check method in the VehiclesController.
A concrete invokation is /vehicles/check?licencePlate=XYZ =>
VehiclesController -> Check(string licenePlate)
I have this map but it does not work:
config.Routes.MapHttpRoute("VehicleTransactions", "Vehicles/Check",
new { controller = "Vehicles", action= "Check" });
Can it be done with MVC?
Thanks, Radek
MapHttpRoute is used for mapping Web API routes. For MVC Controller routes we tend to use MapRoute
So Assuming
public class VehiclesController : Controller {
public ActionResult Check(string licenePlate) {
//...
return View();
}
}
The route would be mapped to
routes.MapRoute(
name: "VehicleTransactions",
url: "vehicles/check",
defaults: new { controller = "Vehicles", action= "Check" }
);
Try this:
routes.MapRoute(
name: "VehicleTransactions",
url: "Vehicles/Check/{licencePlate}",
defaults: new { controller = "Vehicles", action = "Check", licencePlate = UrlParameter.Optional });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
Set "VehicleTransactions" routing before of "Default" routing, because otherwise "Default" overwrite the other.
Special routes is set always before default routing.
Related
I am having an issue while dealing with routing in MVC.
I have defined the following routes in Route.Config
routes.MapRoute(
name: "Test",
url: "{controller}/{action}/{param}",
defaults: new { controller = "Home", action = "FirstAction" }
);
routes.MapRoute(
name: "Testy",
url: "{controller}/{action}/{secondparm}",
defaults: new { controller = "Home", action = "SecondAction" }
);
routes.MapRoute(
name: "Test2",
url: "{controller}/{action}/{encodedparam}",
defaults: new { controller = "User", action = "UserInfo" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Problem is that the first route is working fine but in second and third I got null values for the respective parameter.
Did I miss something?
Thanks in advance
You must match the parameter name for the third. If you write :
{id}
You must write
public ActionResult AnyAction(int id)
id could be of any type
i think there is conflict beetween your routes. You need only this mapping :
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
if you need custom routing for other elements don't put "{controller}/{action}/..." inside, because he will take the first route config that is matching with.
You can call all your routes precising the name of your parameter if its different from "id" :
http://localhost/home/firstaction?param=123
http://localhost/home/secondaction?secondparam=123
http://localhost/user/userinfo?encodedparam=123
As you want to use the URL in such way: localhost:portnumber/home/secondaction/value instead of localhost:portnumber/home/secondaction?secondparam=value.
You have to follow the below approach, which would behave as generic for all your Action Methods, whether they are containing parameters or not.
Declare default route in RouterConfig.cs as:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then Parameter name in method must be same as in default route:
public ActionResult SecondAction(string id)
{
return View();
}
Paramter type could be any type.
In this way you do not need to declare other routes.
I have the following controller:
public class MyController : BaseController
{
public ActionResult Index(string id) { /* Code */ }
public ActionResult MyAjaxCall(string someParameter) { /* Code */ }
}
I have also added the following in the RouteConfig.cs
routes.MapRoute(
name: "MyController",
url: "MyController/{id}",
defaults: new { controller = "MyController", action = "Index" }
)
So my idea is to be able to go directly to the index action using this url /MyController/{Id}, and that seems to work.
However when on the Index page I need to make an Ajax call to /MyController/MyAjaxCall/{someParameter}. However this url is pointing to the Index controller, and is interpreting MyAjaxCall as the id in the Index action.
Any ideas how I can exclude this action from following the newly added route config setting?
If that your id can only be integer number, you can add a constraint to your id field, which specifies that your id can only be numbers:
routes.MapRoute(
name: "MyController",
url: "MyController/{id}",
defaults: new { controller = "MyController", action = "Index" },
constraints: new { id = #"\d+" } // <- constraints of your parameters
)
Here you can use any regular expression that works for your business logic.
Also make sure to register this route before your default route registration, in that case MVC will first try to match this route, and only if it doesn't match it will try to match the default route.
It sounds like you have the routes in the wrong order. When using MVC routing, the first match always wins, so you must place the most specific routes first before general routes.
routes.MapRoute(
name: "MyControllerAJAX",
url: "MyController/MyAjaxCall/{someParameter}",
defaults: new { controller = "MyController", action = "MyAjaxCall" }
)
routes.MapRoute(
name: "MyController",
url: "MyController/{id}",
defaults: new { controller = "MyController", action = "Index" }
)
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
When I pass multiple parameters to a controller action, I get question marks in the parameters like this:
http://localhost:57728/Home/AddAndManageProperties?BaseCategoryId=11&SubCategoryId=14
I want to remove the question marks to be like this:
http://localhost:57728/Home/AddAndManageProperties/BaseCategoryId=11/SubCategoryId=14
here is my code:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "MyRout",
url: "{controller}/{action}/{BaseCategoryId}/{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties", BaseCategoryId = UrlParameter.Optional, SubCategoryId = UrlParameter.Optional }
);
}
}
And here is the Action Method:
public ActionResult AddAndManageProperties(int? BaseCategoryId, int? SubCategoryId)
{
}
And i call the method AddAndManageProperties by this method
[HttpPost]
public ActionResult AddSubCategory(SubCategory subCategory)
{
return RedirectToAction("AddAndManageProperties", new { BaseCategoryId = subCategory.BaseCategoryId, SubCategoryId = subCategory.SubCategoryId });
}
I am new to ASP.NET MVC so please help me!
Move the MyRout to be before the Default route and change it to
routes.MapRoute(
name: "MyRout",
url: "Home/AddAndManageProperties/{BaseCategoryId}/{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
Note that only the last parameter can be marked UrlParameter.Optional so the method needs to be
public ActionResult AddAndManageProperties(int BaseCategoryId, int SubCategoryId)
for the above route, or
public ActionResult AddAndManageProperties(int BaseCategoryId, int? SubCategoryId)
if you modify the above route definition to
defaults: new { controller = "Home", action = "AddAndManageProperties", SubCategoryId = UrlParameter.Optional }
Note, if you also want to include the text "BaseCategoryId" and "SubCategoryId" in the route, use
url: "Home/AddAndManageProperties/BaseCategoryId/{BaseCategoryId}/SubCategoryId/{SubCategoryId}",
That question marks are used for query strings, and they are required because this is how data is assigned to parameters your actions expect. You should not try to remove them, but you could use the [FromBody] attribute, not to send the parameters in query string.
Firstly, and most importantly, your routes are in the wrong order and you have multiple possible URLs that result in calling the wrong route. See Why map special routes first before common routes in asp.net mvc for an explanation.
Secondly, routes cannot contain more than one UrlParamter.Optional.
Third, the = sign is only valid within a query string, unless it is encoded. But IMO, you should not use unsafe characters in a URL to avoid all of the headaches that come with them. A better alternative in this case would be to replace the = with a -.
Finally, if you want to truly make the parameters optional, one approach is to provide multiple routes that allow the parameters in certain routes but not others.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "BaseCategoryAndSubCategoryId",
url: "{controller}/{action}/BaseCategoryId-{BaseCategoryId}/SubCategoryId-{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "BaseCategoryIdOnly",
url: "{controller}/{action}/BaseCategoryId-{BaseCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "SubCategoryIdOnly",
url: "{controller}/{action}/SubCategoryId-{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
NOTE: Stephen's answer is also a good alternative to this approach if your parameters are required to be passed in the URL. IMO, it makes more sense to use required parameters if your action method requires both of them in order to function.
But by far the simplest option is to simply use the query string. The parameters can naturally be optional and appended in any order if you do it that way, and you don't need anything more than your Default route.
I have a URL request in the following format: http://localhost/activate?activationCode=X
I would like this request to be handled in the Home controller, by the Activate action.
I am not sure how to proceed. I have looked at RouteConfig.cs and see the way routes are defined here:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
But how can I make Home/Activate handle URL's of the following format? http://localhost/activate?activationCode=X
...so as to add a special case where activate proceeding the host name goes to the Home controller, and Activate action?
You need to create a specific route
routes.MapRoute(
name: "Activate",
url: "Activate/{id}",
defaults: new { controller = "Home", action = "Activate", id = UrlParameter.Optional }
);
and place this one before the default route.
In addition if you want http://localhost/activate/X rather than http://localhost/activate?activationCode=X, then change it to
routes.MapRoute(
name: "Activate",
url: "Activate/{activationCode}",
defaults: new { controller = "Home", action = "Activate", activationCode = UrlParameter.Optional }
);
and make the method in HomeController
public ActionResult Activate(string activationCode)
I want to change this
localhosht:3220/MyController/MyAction?id=1
to this
localhosht:3220/myText/MyController/MyAction?id=1
So that it works any time, even in redirection, routing or other cases.
Thanks.
Just add the text to the route url:
routes.MapRoute(
name: "Default",
url: "myText/{controller}/{action}"
);
You can do it with a custom route to match your desired uri. In the RegisterRoutes method of RouteConfig, add the following.
The order is important here, if you add the "Default" route before the "MyText" route, then MyText route will not be hit.
//for your custom route that starts with "myText"
routes.MapRoute(
name: "MyText",
url: "myText/{controller}/{action}/{id}",
defaults: new { controller = "MyController", action = "MyAction", id = UrlParameter.Optional }
);
//for other normal routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
While adding a route with the url parameter of myText/{controller}/{action}/{id} (above your default route) will certainly work, if your intention is to use the myText frequently, you might also want to take a look at the concept of areas.
By default, in your Global.asax, in your Application_Start() function, you have a call for the method:
AreaRegistration.RegisterAllAreas();
What this does is to look for a special Areas folder in your project, and register each folder under it that has a class that extends from AreaRegistration and overrides the RegisterArea function. Similar to your RouteConfig.cs, this class can look like this:
public class MyTextAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "MyText";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "MyText_default",
url: "MyText/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
note: you can create Areas in your MVC project by scaffolding: Just right click on your project and Add.. -> Area. Everything will be done for you automatically.
In the end, Areas provide a more permanent solution to your MyText/SomeController/SomeAction needs. For a detailed article, you can check this.
routes.MapRoute(
name: "Default",
url: "{myText}/{controller}/{action}/{id}"
defaults: new {
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
myText= UrlParameter.Optional
);
It will work for you if you want to use parameter like myText to make your Url Seo friendly.