I have a question that I have been thinking about.
What happens from when I enter an URL in my browser and click enter to when the code in the corresponding controller actually executes?
Let's say I have an asp.net mvc application and a trivial Controller like this:
public class HomeController : Controller
{
public ActionResult About(int id = 25)
{
//code
}
}
So if I enter like myUrl/home/about?id=56 that controller gets invoked. I know there is a routing pattern like {controller}/{action}/{id} declared by default. But if an URL matches that pattern is a controller instance created then or what happens? Is there some Resolver class or similar? Is there like a List containing all the controllers so "Home" in the URL matches the HomeController?
I know the id parameter in the controller signature will be bound to the corresponding id value in the request context with the help of model binding. But there must be a lot of other magic happening here.
Hope someone can help a fresh confused asp.net mvc user
in a nutshell:
DefaultControllerFactory finds and instantiates the controller by its name using reflection (more info)
ControllerActionInvoker finds and invokes the action by its name using reflection (more info)
Good overall description can be found here.
Related
I've defined such a controller ViewProfile.
I want to use it for the next syntax to access public user info in my project.
/ViewProfile/Sammy
/ViewProfile/Billy
etc...
But I don't know how to handle the 2-nd parameter in URL.
I've tried to use:
[HttpGet]
public ActionResult Index(string query)
{
...
return View();
}
But in the debugger, string query is always empty.
I have read about routines mapping, but really don't understand how would it help me with the determination of id or other parameters.
I read in ASP.NET MVC Book that to get the parameter directly in the controller action just name it as ID.
ASP.NET MVC lets you easily do this without having to confi gure
anything extra. ASP .NET MVC’s default routing convention is to treat
the segment of a URL after the action method name as a parameter named
ID. If your action method has a parameter named ID, then ASP.NET MVC
will automatically pass the URL segment to you as a parameter.
I just tried a sample app and it worked fine for me. The string i entered in the URL did get passed on to the ID parameter in the action.
Also what i noticed is that you should provide your URL as viewprofile/index/1 or
viewprofile/index/somestring.
YOu seem to be skipping the action part.
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.
I am new to MVC. I was going through the asp.net site and found this link where it stated that public methods (actions) cannot be overloaded in controller classes. However in the site it stated that it can be only be possible if i use [AcceptVerbs(HttpVerbs.Post)] with one function.
Can you please explain how does AcceptVerbs helps in overloading the function.What it actually does behind the scene?
And in one of my sample application i am able to overload the function by using [HttpPost] in one function.What else can be used for overloading?
Basically the rule is that you can handle this when it is responding to different types of requests, so Post/Get/Delete. (Any of the items in the HttpVerbs enumeration)
It is due to the way that it does resolution of the method to call in the controller, and specifying the method allows it to handle resolution.
In ASP.NET MVC, incoming request url should match action of controller. In MVC request processing pipeline, first the controller action is selected, and then the parameters for it are inspected and populated. Imagine what happened if controller had two methods with same name but different signature (overloaded).The c# compiler does not complain, as it understands the code, because it can distinguish between methods based on its parameter signature. But ASP.NET MVC request matching mechanism, as mentioned above, cannot - it first does search for action and only after action is selected, it takes look at its parameters. Because of this, "Public actions in controllers cannot be overloaded" - if there're no difference between methods(actions) other than parameters, action selection in MVC will fail to unambiguously select one. This's where ActionMethodSelectorAttribute comes into play. This is the base mechanism for developers to affect the way MVC searches for valid action in specified controller. It has the method IsValidForRequest() that tells MVC wether action can be selected for usage or not. All of [AcceptVerbs], [HttpGet], [HttpPost], [HttpPut], [HttpDelete] and [HttpNonAction] derive from this attribute. And bingo - now the method overloading is possible - although actions have got the same name, one of the attributes above (or your custom attribute derived from ActionMethodSelectorAttribute) can tell MVC wchich action to select and which one to not. And MVC now unambigously knows wchich action is valid for request. Consider example
[HttpGet]
public ActionResult Index()
{
// The above HttpGet.IsValidForRequest() called internally
by mvc will return true only if request is made via HTTP GET
}
[HttpPost]
public ActionResult Index(MyModel model)
{
// The above HttpPost.IsValidForRequest() called internally
by mvc will return true only if request is made via HTTP POST
}
// And so forth with other ActionMethodSelectorAttibute s. As you see, only one action from same named ones is valid for single request when decorated with any of builtin ActionMethodSelectorAttibute
I'm trying to put in some new routes but not sure where to start. What I would like to do is to have my routes translate as follows:
/transport class A/23 translated to /info/classes/A-23
I understand the basics of using MapRoute but can I do things like the above?
I hope someone can give advice.
This seems to me that you're actually after something like UrlRewrite since you're going from one Url to another.
But MVC doesn't rewrite Urls - it maps them to controller actions based on route patterns you provide.
So, if you're asking if you can split up the first url to a controller/action pair (with parameters) then of course you can. You just set up a route with the necessary parameters in the right place. So you could call MapRoute with something like (I would use hyphens for the spaces):
/*route pattern:*/ "transport-class-{class1}/{class2}"
/*with route defaults:*/ new { controller = "Info", action = "ViewInfo" }
Then you could write a controller as follows:
public class InfoController : ControllerBase
{
public ActionResult ViewInfo(string class1, string class2)
{
//presumably get model data from the class parameters here
//and pass it as parameter to below:
return View();
}
}
Although it would depend also if the transport and class constants in this route are actually also variable I guess - in which case you could push those down as route parameters, and into the parameter list of your controller method.
I'm sorry to ask such a basic question, but it's kind of fundamental for me. To better understand filters, I need to understand this notions. Although I'm on ASP.NET MVC for few months now and now are doing nice demos, I'm more familiar with Action method concept than action result.
What are:
Action Method?
Action Result?
How are they related?
Let's say I've this
public ViewResult ShowPerson(int id)
{
var friend = db.Persons.Where(p => P.PersonID == id).First();
return View(friend);
}
How those concepts apply to the above code?
Thanks for helping.
In your example ShowPerson is the action. Each action needs to return an action result (In your case it returns a view). So when a controller action method is invoked it does some processing and decides what view would be best adapted to represent the model.
There are many different action results that you might use. They all derive from ActionResult:
ViewResult - if you want to return a View
FileResult - if you want to download a file
JsonResult - if you want to serialize some model into JSON
ContentResult - if you want to return plain text
RedirectResult - if you want to redirect to some other action
HttpUnauthorizedResult - if you want to indicate that the user is not authorized to access this action
FooBarResult - a custom action result that you wrote
Answer by #Darin-dimitrov is very much upto the point. But I see explanation given on MSDN also very much helpful.
Action methods typically have a one-to-one mapping with user
interactions. Examples of user interactions include entering a URL
into the browser, clicking a link, and submitting a form. Each of
these user interactions causes a request to be sent to the server. In
each case, the URL of the request includes information that the MVC
framework uses to invoke an action method.
When a user enters a URL into the browser, the MVC application uses
routing rules that are defined in the Global.asax file to parse the
URL and to determine the path of the controller. The controller then
determines the appropriate action method to handle the request. By
default, the URL of a request is treated as a sub-path that includes
the controller name followed by the action name. For example, if a
user enters the URL http://contoso.com/MyWebSite/Products/Categories,
the sub-path is /Products/Categories. The default routing rule treats
"Products" as the prefix name of the controller, which must end with
"Controller" (such as ProductsController). It treats "Categories" as
the name of the action. Therefore, the routing rule invokes the
Categories method of the Products controller in order to process the
request. If the URL ends with /Products/Detail/5, the default routing
rule treats "Detail" as the name of the action, and the Detail method
of the Products controller is invoked to process the request. By
default, the value "5" in the URL will be passed to the Detail method
as a parameter.