MVC 4: Multiple Controller action parameters - asp.net-mvc

Instead of just {controller}/{action}/{id} is it possible to have mulitple parameters like
{controller}/{action}/{id}/{another id}?
I'm new to MVC (coming from just plain Web Pages). If not possible, does MVC provide a helper method like the UrlData availble in Web Pages?

You will just need to map the new route in your global.asax, like this:
routes.MapRoute(
"NewRoute", // Route name
"{controller}/{action}/{id}/{another_id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, another_id = UrlParameter.Optional } // Parameter defaults
);
Then in your controller's action you can pick up the parameter like this:
public ActionResult MyAction(string id, string another_id)
{
// ...
}

Yes, you can define multiple parameters in a route. You will need to first define your route in your Global.asax file. You can define parameters in URL segments, or in portions of URL segments. To use your example, you can define a route as
{controller}/{action}/{id1}/{id2}
the MVC infrastructure will then parse matching routes to extract the id1 and id2 segments and assign them to the corresponding variables in your action method:
public class MyController : Controller
{
public ActionResult Index(string id1, string id2)
{
//..
}
}
Alternatively, you could also accept input parameters from query string or form variables. For example:
MyController/Index/5?id2=10
Routing is discussed in more detail here

Related

cant find Route when action has 2 params - Asp.Net MVC

I have a controller named Blog.
I have an action like this:
[Route("{code:int}/{title?}")]
public virtual ActionResult Index(int code, string title)
{
var postModel = _blogService.Get(code.ToUrlDecription());
return View(postModel);
}
I entered these urls, but all of them returned not found:
localhost:7708/Blog/index/12/post-title;
localhost:7708/Blog/index/12;
localhost:7708/Blog/12/post-title.
I tried to write a route like below, but the result was the same:
routes.MapRoute(
name: "showblogpost", url: "{controller}/{action}/{code}/{title}",
defaults: new {
controller = "Blog",
action = "Index",
title = UrlParameter.Optional
},
namespaces:new string[] { "Web.Controllers" }
);
One thing, you don't need to use both attribute [Route] on action and mapping route.
In your attribute [Route] you have specified only parameters, so route according to it should be localhost:7708/12
by route, specified in MapRoute it should be localhost:7708/showblogpost/12
What I suggest is - remove your attribute, name your route in MapRoute as you want to see in URL, and also you can remove "string title" parameter from action, as it's not used.

How to control which Action is used in ASP.NET MVC

I have a setup where I use one route with url's on the following format:
www.example.com/friendly-url-1
www.example.com/friendly-url-2
www.example.com/another-friendly-url
The route is defined like this:
routes.MapRoute("FriendlyUrl", "{name}",
new { controller = "FriendlyUrl", action = "Index", name = UrlParameter.Optional }
);
Name is an internal property in my application that lets me look up which controller should be used in a custom ControllerFactory, and change the name of the controller that is created (there is no actual controller called FriendlyUrl).
It works well if I only have one action per controller, but since action isn't part of the route, it always uses the default action. I want to have more than one action, but I'm not able to find a good way for me to write logic that controls which action should be used for each request. Is it possible?
If I correctly understand, you have urls in form "www.example.com/friendly-url/name" and want name to determine both controller and action, e.g.
"example.com/friendly/foo" would resolve to SomeController and XxxAction
"example.com/friendly/boo" would resolve to AnotherController and ZzzAction
I think, the easiest way would be to use custom route handler
public class MyRouteHander : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var values = requestContext.RouteData.Values;
var token = GetRequestToken(requestContext);
switch (token) {
case "friendly/foo") {
values["controller"] = "some";
values["action"] = "xxx";
break;
case "friendly/boo") {
values["controller"] = "another";
values["action"] = "zzz";
break;
...
}
return new MvcHandler(requestContext);
}
}
and then you register the handler with
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
).RouteHandler = new MyRouteHander();
You can write dedicate route for your URL's and it will call different action in that case. but if you want to use a expression to route to different actions i don't think you can do it directly by writing route in routeConfig as you need to specify somewhere the mapping of URL Segment to Action which is equivalent to creating dedicated routes in routeConfig

Specify special case handler for MapRoute in ASP.NET MVC 3

I have the following Route defined in Global.asax:
routes.MapRoute(
"IncidentActionWithId", // Route name
"Incidents/{companyId}/{action}/{id}", // URL with parameters
new { controller = "Incidents" } // Parameter defaults
);
I have a special case of request, like this one:
/Incidents/SuperCompany/SearchPeople/Ko
In this case, action should indeed map to SearchPeople action, comapnyId to this action's parameter, but only when action is SearchPeople, the Ko should not be mapped to an id parameter of the action, but to searchTerm.
My action declaration is:
[HttpGet]
public ActionResult SearchPeople(string companyId, string searchTerm)
How can I achieve Ko to be mapped to searchTerm parameter in my action method?
You can define two routes, one with id and one with searchTerm if the id is supposed to be numeric (or you can specify regex constratints) and have different pattern to searchTerm.
See here how you can define constraints.
Example:
routes.MapRoute(
"IncidentActionWithId", // Route name
"Incidents/{companyId}/{action}/{id}", // URL with parameters
new { controller = "Incidents" }, // Parameter defaults
new {id = #"\d+"} // numeric only
);
routes.MapRoute(
"IncidentActionWithId", // Route name
"Incidents/{companyId}/{action}/{searchterm}", // URL with parameters
new { controller = "Incidents" }
);
NOTE
Define the one with constraint first.

Mapping routes to controller programmatically

Is it possible to map a route to a controller programmatically? In other words, I want to create a route without a controller, and based on the values of the rest of the parameters in the url map the correct controller to the request?
An example:
url: example.com/about-us
I want to look-up in our system which controller "about-us" is using and then set the controller for the request. It can't be a default controller since there will be many different pages like the one above, that uses different controllers.
Why would you need this? Normal MVC way for handling such situations is to add different routes for different controllers, specifying values of parameters inside routes themselves or using RouteConstraints.
Another approach (if you really inist on doing routing logic yourself) might be creating a "Routing controller" with, say, a single action which processes all the queries. Inisde this action code you may check for parameter values and do return RedirectToAction(...) to redirect request to any action on any controller you need.
UPDATE: Example code
In Global.asax.cs create the following default route:
routes.MapRoute(
"Default", // Route name
"{*pathInfo}", // URL with parameters
new { controller = "Route", action = "Index"} // Parameter defaults
);
Also add a controller class RouteController.cs with the following content:
// usings here...
namespace YourApp.Controllers
{
public class RouteController : Controller
{
public ActionResult Index(string pathInfo)
{
...
// programmatically parse pathInfo and determine
// controllerName, actionName and routeValues
// you want to use to reroute current request
...
return RedirectToAction(actionName, controllerName, routeValues);
}
}
}
I would suggest using custom IRouteHandler implementation. You can restrict route matching with constraints and then rewrite a controller to be instantiated within IRouteHandler implementation.
E.g.
public class RewriteController : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// here some logic to determine controller name you would like
// to instantiate
var controllerName = ...;
requestContext.RouteData.Values["controller"] = controllerName;
return new HttpControllerHandler(requestContext.RouteData);
}
}
Then your route may be like the following:
routes.MapHttpRoute
(
name: Guid.NewGuid().ToString(),
routeTemplate: "{controller}/{action}",
defaults: new { action = "Index" },
constraints: new
{
controller = "about-us"
}
).RouteHandler = new RewriteController();

ASP.NET MVC redirection Action to Default?

I have a action on my controller (controller name is 'makemagic') called 'dosomething' that takes a nullable int and then returns the view 'dosomething.aspx'. At least this is what I am trying to do. Seems no matter I get routed to the Default() view.
public ActionResult dosomething(int? id)
{
var model = // business logic here to fetch model from DB
return View("dosomething", model);
}
There is a /Views/makemagic/dosomething.aspx file that has the Inherits System.Web.Mvc.ViewPage
Do I need to do something to my routes? I have just the 'stock' default routes in my global.aspx.cs file;
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
I am calling the action via a href like this in another page;
Click Me!
Seriously driving me nutso. Any suggestions on how to troubleshoot this? I attempted to debug break on my route definitions and seems a break there doesn't happen as one would expect.
Change it so the parameter isn't nullable so it will match the default route, or change the name to something other than id and supply it as a query parameter. An example of the latter would be:
public ActionResult dosomething(int? foo)
{
var model = // business logic here to fetch model from DB
return View("dosomething", model);
}
Click me
The it will work with the default routing implementation. Alternatively, you could do something that would distinguish it from the default route and then you would be able to have a route for it and not have to use query parameters.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/foo/{id}", // URL with parameters
new { controller = "makemagic", action = "dosomething", id = "" } // Parameter defaults
);
Click Me!

Resources