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.
Related
I tried to use map route on my mvc project,first route "route1" is working fine with two parameters
http://localhost:43601/records/index/1/5454546
now the second route - on the same controller - recordcontroller- is NOT working "route2"
http://localhost:43601/records/attachmentdetails/828/2
and gave an error:
The parameters dictionary contains a null entry for parameter 'attId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult AttachmentDetails(Int32, Int32)'
any help please?
//route code
routes.LowercaseUrls = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Web API
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "route1",
url: "{controller}/{action}/{libId}/{recordNo}",
defaults: new { controller = "Records", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "route2",
url: "{controller}/{action}/{attId}/{atype}",
defaults: new { controller = "Records", action = "AttachmentDetails", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default4",
url: "{controller}/{action}/{attId}/{atype}",
defaults: new { controller = "FileManager", action = "BookAttachmnt", id = UrlParameter.Optional }
);
//controllers code
public ActionResult Index(string libId, int recordNo = 0)
{
}
public ActionResult AttachmentDetails(int attId, int atype)
{
BasicSearchAttribute();
return View();
}
You are matching route1 when you really want to match route2.
To achieve this, use this route instead, and put it before route1.
routes.MapRoute(
name: "route2",
url: "Records/{action}/{attId}/{atype}",
defaults: new { controller = "Records", action = "AttachmentDetails", id = UrlParameter.Optional }
);
The reason your code isn't working is that routes are matched 'top down' (i.e. the order in which they are defined). The URL you are using meets the rules for route1 before it meets the rules for route2. Alas, route1 has different parameter names (libId rather than attId) and thus the routing fails since your action wants a attId parameter, but was given a libId parameter.
But putting the above route first it will mean that it gets used, rather than route1. Note also that I have hard-coded Records in the route, to ensure that URLs that start with Records are handled by route2 and everything else is handled by route1 (or later routes).
I have an MVC page for creating an entity. Upon completion, I want to redirect to the parent entity. I do it like this:
return RedirectToAction("Edit", new { id = vm.Parent });
When I use any other parameter name, it is interpreted as an URL param:
return RedirectToAction("Edit", new { foo = vm.Parent });
renders as /Entities/Edit?foo=234
But ASP MVC picks up a route param named id as a special case and the URL looks like: /Entities/Edit/234. This does not work for me because the routing is not set up to work with this. I am looking to get an URL like /Entities/Edit?id=234.
How do I force it to work this way? Route setup:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
By the looks of it, you're only using the default route config route, which only specified id as a defined UrlParameter. If you want a custom parameter, then you'll need to define it as such:
routes.MapRoute(
name: "ControllerName",
url: "controllername/edit/{foo}"
);
Or if you wish to use foo instead of id globally, just alter your existing route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{foo}",
defaults: new { controller = "Home", action = "Index", foo = UrlParameter.Optional }
);
Or if you don't want good looking URLs with an unnecessary query string parameter, alter your default:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
I have the following routings in my RoutingConfig.cs
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
// Not working why?
routes.MapRoute(
name: "AdminLoginRequestUrl",
url: "{controller}/{action}/{requestUrl}",
defaults: new { controller = "Admin", action = "Login", requestUrl= UrlParameter.Optional }
);
The problem is that the second routing is not working
What do i miss here? does someone has any tips or Ideas MVC is abit new for me
You cannot create different route only by differentiating parameter name, both route present similar one. Also move your custom route above default one. You can try this
routes.MapRoute(
name: "AdminLoginRequestUrl",
url: "{controller}/{action}/route2/{requestUrl}",
defaults: new { controller = "Admin", action = "Login", requestUrl= UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
you can use anything insted of route2 to differentiate from default route
You cannot differ your routs by variable names. You can create more specific route like this:
routes.MapRoute(
name: "AdminLoginRequestUrl",
url: "Admin/{action}/{requestUrl}",
defaults: new { controller = "Admin", action = "Login", requestUrl= UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Note that the order of registration is significant.
Or you can rename your parameters to something that will be appropriate for both controllers and use that.
Consider using MapHttpAttributeRoutes(), you can read about it here: https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/1.
Edit: Changed link for better article.
Then you can use attributes to define more specific rules on your actions.
Example:
public class Admin : Controller
{
[Route("admin/{requestUrl}")]
public ActionResult Login(string requestUrl) { ... }
}
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 }
);
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)