ASP.NET MVC class that represents a controller+action set? - asp.net-mvc

Is there a class in the ASP.NET MVC framework that represents a controller name and an action name?
I'm writing a method that will return a collection of URLs and I want them to be returned as objects that contain a 'Controller' and 'Action' property or something similar.
This is because sometimes I'll need to isolate just the controller name or just the action name.
There's the Route object, but it seems way too heavyweight for what I'm trying to do.
Is there a simpler abstraction in ASP.NET MVC?

There is a Controller Base class not a name though, an action name is simply an string which the ActionInvoker will use to find the correct action via reflection.
I think you'll have to use the Route Values Dictionary of key/value pairs to represent the route.
RouteValueDictionary myValues = new RouteValueDictionary();
myValues.Add("Controller", "myController");
You could use a normal dictionary and then convert it in code to a RouteValueDictionary if you don't want/can't have to have access to the Routing namespace.
In this approach you can then using the keys of the either a standard dictionary or the routeValue Dictionary to do the isolation of the controller or action.
String ControlString = myValues["Controller"]
Then do what you want with it. Maybe use constants for the keys you wish to access.

Related

What is the purpose of MVC passing the current "controller" and "action" as parameter values

I had to pass an extra parameter with my action links to indicate where they came from (as I needed to change a back link in the pages accordingly).
As it was a controller name, I decided to name it controller.
e.g. a sample link might be:
#Html.ActionLink(item.Name, "Options", "Questionnaire", new {
id = item.QuestionnaireId,
controller = "templates" }, null)
The receiving action in QuestionnaireController looked like:
public ActionResult Options(int id, string controller)
When the action was hit I noticed the controller value was not template, but instead was the name of the current controller (i.e. QuestionnaireController).
As an experiment I added an action parameter e.g.:
public ActionResult Options(int id, string controller, string action)
the action value was the current action too (i.e. Options).
My work-around for this was simply to rename my parameter to source, but why does MVC bother to map the names controller and action to action parameters? I assume that would apply to any/all Route Mapping values, but what is the purpose of this?
Why does MVC bother to map the names controller and action to action parameters?
I believe it's done as part of the QueryStringValueProvider or one of the other ValueProviders (maybe the RouteDataValueProvider). ASP.Net MVC uses Convention over Configuration, so the framework uses the values provided to populate method parameters. The Controller name, Action name and even the Area name are all values provided in the Url.
I assume that would apply to any/all Route Mapping values, but what is the purpose of this?
The ValueProvider is used for Routing data to determine the matching route to use, it also happens to be the same object that provides the data to populate method parameters. The side affect you are experiencing is most likely not a feature they were trying to implement.
The DefaultModelBinder.GetValue uses the ValueProviders to locate a value and bind it to the model (or method paramater).

Map Area, Controller and Action names to default values if empty

I am given 3 strings: area, controller and action. Some of them could have empty values, as there are default values defined in my routes. For example, if action is empty it will be mapped to Index.
I wish to pass these 3 strings through the routing of my application and get their actual values after any empty values where mapped to default values. Is this possible?
Maybe it is doable by doing something like this
RouteTable.Routes.GetRouteData(context)
but is there a way to do it without constructing a whole HttpContext object?
The first thing you will have to do is take your three strings and convert that into a URL that can be passed thru the routing system. How you do this depends upon what routes you have created. Let's assume you have the typical default route in your route table:
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller="Home", action = "Index", id = UrlParameter.Optional }
);
Then you would have to use the URL pattern "{area}/{controller}/{action}/{id}" to build up your URL. In your case, some of the strings could be empty, so your URL would not have all of the segments. For example, if Area="Admin" and Controller and Action are empty, your URL, based on this route, would be:
~/Admin
Of course, this raises the question of if you already know the routes in your system, why can't you just get the defaults by looking at the routes.
Once you have the URL that you want to test, you will need to create a mock of the HttpContentBase object and then run it thru RouteTable.Routes.GetDate(httpContext). There is straightforward boiler plate code to do this, since you really do not need to mock much of the constituent HttpRequestBase or HttpResponseBase classes. For example, see here for an example of mocking an HttpContextBase object using the Moq mocking framework.

Combining values in ASP.Net Routes for MVC

Can anyone suggest a way to accomplish the following in ASP.Net Routing (for MVC 3)?
I want to have URLs where the value which determines the controller is actually part of the id for the page:
/{id}-{controller}/{action}/{further-values}
But I need the id value to include the value used for the controller as well, so in the above if we have the following URL:
/chelsea-football-team/view/2010-2011
I want the {id} value to, ideally, be "chelsea-football-team", the controller to be "football-team", the action to be "view" and the additional value to be "2010-2011".
I have no issues having several routes with the controller value hard coded into the route definition, but I need to be able to have several controller values.
I know that I can simply combine the values in the controller, but that adds a lot of additional, repeated code - so is this accomplishable in any other way?
Why do I want to do this? Because I need to have the team name in full, but part of the team name will always match the controller name so why not combine them in the route?
I want the {id} value to, ideally, be "chelsea-football-team", the controller to be "football-team", the action to be "view" and the additional value to be "2010-2011".
...MapRoute(null, "{id}/{action}/{*furtherValues}",
new {
controller = "FootballTeam",
});
Update after comment 1
You can't combine route parameters in a URL such that a single parameter represents both a variable (id) and a controller, using the standard routing implementation. If you want the id to be "chelsea-football-team", that has to be a self-contained route parameter. You can't combine it in a way that MVC extracts the controller name from the id.
To meet this requirement, you may have to create a custom RouteBase implementation:
public class MyCustomRoutingPattern : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
// do your coding and return an instance of RouteData
}
}
You would then use it like so:
routes.Add(new MyCustomRoutingPattern(
"{id}/{action}/{*furtherValues}"));
Your RouteBase implementation can then extract the controller from the id parameter. The Pro ASP.NET MVC3 Framework book by Steve Sanderson and Adam Freeman has a section on how to override the RouteBase class.

MVC3 RouteUrl inside a ViewModel

I need to create a route URL based on parameters as a part of a JSON return values.
What is the equivalent of Url.RouteUrl but to be used inside the controller code,
So I can return a string in my Json result that contains the routeurl .
I need this done outside of the controller class, in a separate class, can this be done at all?
You can still use Url.RouteUrl, but in a slightly different way.
Place a using System.Web.Mvc; at the top of your class (of course, you might need to Add Reference to System.Web.Mvc).
Then get the Url object by:
UrlHelper Url = new UrlHelper(HttpContext.Current.Request.RequestContext);
and access as usual: Url.RouteUrl.

ASP.NET MVC - Passing a parameter to my action method?

public ActionResult RenderMyThing(IList<String> strings)
{
return View("RenderMyView");
}
How do I pass in strings?
routes.MapRoute("MyRoute", "RenderMyThing.aspx", new { controller = "My", action = "RenderMyThing" });
Is there a way I could pass in strings here?
Secondly, how does ASP.NET MVC know that action is my action, and controller is my controller. Like I saw this in samples, and it does work, but isn't it just an anonymous object with no type?
This is the provenance of model binding: the framework needs to have some instruction as to how to turn a "request", which comes out of the routing context, query string, forms collection, etc., into the parameters that your action method wants.
The DefaultModelBinder will generate a list if it sees that you have multiple key-value pairs with the same key (and appropriately typed/convertible values) - for the details, Phil wrote a good post about this:
If you need fancier binding requirements, you can implement a custom model binder and explicitly define how route values and the other bits get translated into objects (or collections of objects).

Resources