I have done a route configuration with MVC. The route is so defined:
routes.MapRoute(
name: "Box",
url: "boxes/{id}",
defaults: new { controller = "Boxes", action = "Index", id = UrlParameter.Optional }
);
The problem is that when i call a javascript function from the view Boxes, all the function i call are redirected to the Index function.
For example, if i call var url = "/Boxes/ReturnPrice"; the site don't call this function but the index function.
The index function in boxesController is so defined:
public ActionResult Index()
{
//Code here
return view();
}
When you call /Boxes/ReturnPrice , It matches your "Box" route definition. the framework will map "ReturnPrice" from the url to the id parameter !
You need to define a route constraint which tells that your id property is of type int ( I assume it is int in your case) . Also you need to make sure that you have a generic route definition exists to handle your normal requests with the format controllername/actionmethodname.
You can define the route constraint when defining the route using regex.
routes.MapRoute(
name: "Box",
url: "boxes/{id}",
defaults: new { controller = "Boxes", action = "Index", id = UrlParameter.Optional },
constraints: new { id = #"\d+" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
With this Boxes/ReturnPrice will go to ReturnPrice action method while Boxes/5 will go to Index action method with value 5 set to Id param.
Related
routes.MapRoute(
name: "Home",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Process",
url: "Process/{action}/{id}",
defaults: new { controller = "Process", action = "", id = UrlParameter.Optional }
);
1. Could you please help me in understanding why I get HTTP 404 error when I hit http://localhost:7841/Process
However, I am able to see my page when I hit
http://localhost:7841/Process/list
Also, if i hardcode controller( url: "Home/{action}/{id}") in both the routes URLs(see below) why I get “HTTP Error 403.14 - Forbidden” error.
routes.MapRoute(
name: "Home",
url: "Home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Process",
url: "Process/{action}/{id}",
defaults: new { controller = "Process", action = "", id = UrlParameter.Optional }
);
Kindly help me in understanding Routes.
Because when you request yourBaseUrl/Process/, It matches the route pattern {controller}/{action}/{id} which is the url pattern for your first route defined(the one called Home). So it will try to send the request to the action method and since you do not have the action method segment in the request url, it will try to use the default one defined in that route registration, which is Index. You are getting a 404 because you do not have an Index action method inside your ProcessController. If you add an Index() action method to your ProcessController, It will execute that and return the result from that.
Ideally, you should define all your specific route definition before the generic route definition. If you want /Process to return the response returned by the List method, set that as the default action in the route registration.
routes.MapRoute(
name: "Process",
url: "Process/{action}/{id}",
defaults: new { controller = "Process", action = "List", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Another option is to use the default generic route registration as it is in the RouteConfig and use attribute routing to make List method to be handled by /Process/ request.
public class ProcessController : Controller
{
[System.Web.Mvc.Route("Process")]
public ActionResult List()
{
return Content("process list action method :)");
}
}
Im trying to get my urls to look nice and seo friendly with slugs. I tought I suceeded but then my default routing stopped working.
When I go to this example.com/location/viewlocation/528 then the url ends up like example.com/528/a-nice-location
So thats good!
But now my normal stuff dosent work.
Typing in example.com/home/index results in the error
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult ViewLocation(Int32, System.String)' in 'Oplev.Controllers.LocationController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
I have tried different solutions but I a missing something. Cant get it to work.
My code:
RouteConfig
routes.MapRoute(
name: "view_location",
url: "{id}/{slug}",
defaults: new { controller = "Location", action = "ViewLocation", id = UrlParameter.Optional, slug = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Location controller
public ActionResult ViewLocation(int id, string slug)
{
if (string.IsNullOrEmpty(slug))
{
slug = "a-nice-location"; // testing..
return RedirectToRoute("view_location", new { id = id, slug = slug });
}
return View();
}
Home controller
public ActionResult Index()
{
return View();
}
Your first route matches anything with 0, 1 or 2 segments in the url. For example it matches ../Home/Index. You need some way to distinguish it, for example you could make it
routes.MapRoute(
name: "view_location",
url: "ViewLocation/{id}/{slug}",
defaults: new { controller = "Location", action = "ViewLocation", slug = UrlParameter.Optional }
);
or you could add a route constraint
Note also that only the last parameter can be marked as UrlParameter.Optional, but in your case the id is not optional anyway
Ok so I somehow ended up with something that works!
Changed routing for view_location to this:
routes.MapRoute(
name: "view_location",
url: "{id}/{slug}",
defaults: new { controller = "Location", action = "ViewLocation", slug = UrlParameter.Optional},
constraints: new { id = #"\d+" }
);
This is meant to supplement the already given answers. Attribute routing with route constraints will also work.
First make sure attribute routing is enabled in RouteConfig
//Attribute routing
routes.MapMvcAttributeRoutes(); // placed before convention-based routes
//convention-based routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Next use the necessary Route attributes on the controller
[HttpGet]
[Route("{id:int}/{*slug?}", Name = "view_location")] // Matches GET 528/some-nice-location
public ActionResult ViewLocation(int id, string slug) {
if (string.IsNullOrEmpty(slug)) {
slug = "a-nice-location"; // testing..
return RedirectToRoute("view_location", new { id = id, slug = slug });
}
return View();
}
I have Controller name: District and Action name: Incharges But I want the URL to be like this (action name with some paremeter)
www.example.com/district/incharges/aaa
www.example.com/district/incharges/bbb
www.example.com/district/incharges/ccc
But, while debugging teamName always return as NULL in the action parameter.
Routing
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"DistrictDetails",
"District/Incharges/{teamName}",
new { controller = "District", action = "Incharges" }
);
Controller
But, while debugging teamName always return as NULL in the action parameter.
public class DistrictController : Controller
{
public ActionResult Incharges(string teamName)
{
InchargePresentationVM INPVM = new InchargePresentationVM();
INPVM.InitializePath(teamName, string.Empty);
return View("", INPVM);
}
}
View
#{
ViewBag.Title = "Index";
}
<h2>Index About</h2>
specific route you have to declare the first
routes.MapRoute(
"DistrictDetails",
"District/Incharges/{teamName}",
new { controller = "District", action = "Incharges", id = UrlParameter.Optional }
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
););
ASP.NET MVC DefaultModelBinder will try and do implicit type conversion of the values from your value provider , eg. form, to the action method parameters. If it tries to convert a type from the value provider to the parameter and it is not able to do it, it will assign null to the parameter.
Regarding routing, ASP.NET MVC has the concept of conversion over configuration. If you follow the conversion, then instead of configuration. You can keep your default route and always have the route you want by naming your controllers, action methods and parameter names.
With the convention over configuration you must keep the default HomeController which is the entry point of the application and then name other controllers as below. These can conform to the route names you want.
namespace ConversionOverConfiguration
{
public class DistrictController: Controller
{
public ActionResult Incharges(int aaa)
{
//You implementation here
return View();
}
}
}
The route will look as below if you have this conversion implementation
//Controller/ActionMethod/ActionMethodParameter
//District/Incharges/aaa
And this will give you domain URI:www.example.com/district/incharges/aaa . If action method parameter type is a string, then domain URI is:www.example.com/district/incharges/?aaa=name
is a string. Then you can keep the ASP.NET MVC default routing
routes.MapRoute
(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional
});
Here's an example of my set up:
public class UserController : Controller
{
public ActionResult Index(int? id) { ... }
[HttpPost]
public ActionResult DoSomething(int id) { ... }
public ActionResult Search([params]) { ... }
}
and I want to be able to access them via these routes:
/app/User/{id}
/app/User/DoSomething/{id}
/app/User/Search/
I tried setting up my routes like this, but then if I try to navigate to /app/User/Search/ or post to /app/User/DoSomething/, the Index Action is hit instead.
routes.MapRoute(
name: "UserWithoutIndex",
url: "User/{id}",
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
How can I do this? I think it would work to just specify each specific action in it's own route before the UserWithoutIndex route above, but I have multiple actions and I don't want to have to create a route specific to each action in the controller.
The problem is your first route will match any two-segment URL which includes the examples you provided; /app/User/Search/ and /app/User/DoSomething/ and the values Search and DoSomething will be placed in the id place holder respectively. Then because the first route is being matched you are receiving Index for the action. If your id will take on some format specifically you could specify a constraint for it in the first route like so:
routes.MapRoute(
name: "UserWithoutIndex",
url: "User/{id}",
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
constraints: new { id = "your regex here" }
);
If you constraint can be specific enough to the format of the id than things like Search and DoSomething won't match and the route won't match so the next route will be tried.
Also, if there will always be an id specified in the scenarios where you want the first route to be targeted you should remove the id = UrlParameter.Optional default so that way the id will be required and the route will ONLY match two-segment URLs because as it is now with the id being optional the route will also match one-segment URLs.
I have this URL:
/controller/action/value
and this action:
public ActionResult Get(string configName,string addParams)
{
}
How do I set up my routing table to get the routing engine bind the value to the configName parameter for any action in the Config controller?
Well, first off, that is incomplete. You don't have a method name.
Secondly, this will already work with URLs of the format:
/controller/action?configName=foo&addparams=bar
Here's how to do it with pretty routes:
routes.MapRoute(
"YourMapping",
"{controller}/{action}/{configName}/{addParams}");
or
routes.MapRoute(
"YourMapping",
"{controller}/{configName}/{addParams}",
new {
controller = "YourController",
action = "YourAction"
},
new {
controller = "YourController" // Constraint
});
if you want to exclude the action from the URL.
You could add a new route above the default
routes.MapRoute(
"Config",
"config/{action}/{configName}/{addParams}",
new { controller = "Config", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Which will allow you to use the route /config/actionName/configName/addParamsValue. Your other routes should be unaffected by this.
routes.MapRoute(
"ValueMapping",
"config/{action}/{configName}/{addParams}",
new { controller = "Config", action = "Index", configName= UrlParameter.Optional, addParams = UrlParameter.Optional } // Parameter defaults);
Setting default Controller to Home, with a Default Action of Index
So the Url:
/config/get/configNameValue/AddParamValue
would match this Method:
public ActionResult Get(string configName,string addParams)
{
//Do Stuff
}