This is a point of curiosity rather than an actual problem I'm having: how does the ASP.NET MVC framework create the appropriate controller and view objects from the string name in the RouteCollection? I've tried searching through the actual ASP.NET MVC2 code to figure this out but get lost in the controller factory class.
When I register my routes, I map the first block to the controller, the second to an action, the third to an ID, but how does the program take string names and create new objects?
/Users/Update/15354 = New UserController, executes Update() - how?
The only thing I can imagine working is reflecting through all the classes in the project and creating one that matches the requested name, but then how would you resolve a conflict in class names without knowing which namespace to use?
The standard naming convention "FooController" dictates that all controllers should have the suffix "Controller"; thus, when your current route indicates the controller "Foo", ASP.NET MVC examines the types within your application which inherit from Controller and looks for one whose name matches "Foo" + "Controller".
You are correct to assume that ASP.NET MVC is using reflection to find the desired controller, but it is a relatively low impact because the reflection data is cached by the application during its initial startup.
If you have two controllers with the same name and different namespaces, you can use the alternative form of MapRoute() to indicate which controller you intend to resolve.
routes.MapRoute(
"Error_ServiceUnavailable",
"error/service-unavailable",
new { controller = "Error", action = "ServiceUnavailable" },
new[] { "Controllers" }
);
routes.MapRoute(
"Admin_Error_ServiceUnavailable",
"admin/error/service-unavailable",
new { controller = "Error", action = "ServiceUnavailable" },
new[] { "Areas.Admin.Controllers" }
);
Related
Here is my controller
public class SpecializationsController : Controller
{
public ActionResult Action1()
{
//body
}
public ActionResult Action2()
{
//body
}
Default url for Action1 is of course /Specialization/Action1. I want to add prefix to all Actions in my controller to make my ulr like /prefix/Specialization/Action1.
I tried to add [RoutePrefix("prefix")] to my controller but it doesn't work. I would like to avoid adding [Route] attribute for each action in my controller. So how can I add this prefix?
I would create Areas:
Areas are an ASP.NET MVC feature used to organize related functionality into a group as a separate namespace (for routing) and folder structure (for views). Using areas creates a hierarchy for the purpose of routing by adding another route parameter
I know you may think this is an overkill for simply having a "prefix" but the reason I suggest this approach is because if you have the need to add a "prefix", chances are you have the need to separate the views, models etc. as well.
You need to add a route to your route collections instead of using route attributes
routes.MapRoute(
"Route",
"prefix/{controller}/{action}",
new { controller = "Specializations", action = "Index" });
I am developing one application in the ASP.NET MVC C# on the .NET 4 framework.
I confused in routing and I do the research and developed the one demo version It works as I want but I want to know is which method is best practice for developing application.
First I register the route like this:
routes.MapRoute(
name: "RoutesTesting",
url: "{controller}/{action}/{a}/{b}/{c}/{d}/{e}",
defaults: new { controller = "Home", action = "Test", e = UrlParameter.Optional }
);
I have one class that have the properties and it's name same as the route's parameter.
class MyClass{
public string a{get;set;}
public string b{get;set;}
public string c{get;set;}
public string d{get;set;}
public string e{get;set;}
}
Now I created the tow methods that works find and get the data from the URL successfully.
Method 1:
public ActionResult Test(MyClass objMyClass){
}
Method 2:
public ActionResult Test(string a,string b,string c,string d,string e=String.Empty){
}
My question is:
Is routing doing that conversation in my action method? Like it convert the parameter values in the `MyClass' object's properties?
Which method is best practice to use?
Is method 1 will throw any error or exception when the conversation is not possible ?
Thanks in advance...
The behavior you are seeing is a part of ASP.NET's Model Binding. It's the magic that lets you send across a JSON object of {"firstName":"Jonathon","lastName":"Chase"} and have to automagically be mapped to a model Person that looks like so:
public class Person {
public string FirstName {get;set;}
public string LastName {get;set;}
}
The fact that you can create a route like that is merely a consequence of this. Model Binding is a complex subject, but I can touch on some aspects of how you're forming your route, especially if the action you're creating is going to have a side-effect, such as writing to a database.
Typically if you're going to have a method that will effect state, you should use an Http verb other than Get, and send the model across in the body of the request, rather than in the query/url string. The Model Binding will take care of the mapping for you either way.
You should prefer to use a strong model rather than multiple primitives as parameters, especially in cases where the information will be sent in the body of a request over the query string.
These points are debatable, however, and shouldn't be considered hard or fast rules for the most part.
As to your last point, if the parameters are incorrect enough that the Route can't identifier the action or controller, you should get a 404. However, if you have a valuetype that isn't nullable as an expected routed property that isn't properly sent across, you should expect a 500 with an InvalidOperationException.
Take a look at How model binding works
Is routing doing that conversation in my action method? Like it
convert the parameter values in the `MyClass' object's properties?
The framework model binder is doing the conversion based on the actions parameter.
Which method is best practice to use?
That is an opinionated question. Depends on which one suits your needs. The framework handles both.
Is method 1 will throw any error or exception when the conversation is
not possible ?
Model binder will pass null to the action parameter for the properties that don't match.
I'm developing a sport based web site with Asp.Net Mvc 4.
The site is being developed to show just one sport data at a time.
The sports have similar datas in common but also they have different datas.
Site supports many sports that’s why, I do not want to use common controllers/views by seperating sports with if statements.
I tried this one:
I have created an area for each sport. I described the controllers in area which are related to that sport.
For example, in Route, name of the controller and area will be stated, firstly it will be searched in area, if it is not there, it will be searched in default(/Controllers).
Because the controllers share the same names, Mvc DefaultControllerfactory throws "Ambiguous Controller Name Exception". First I’m searching area, if it cannot be found then I’m searching in default by writing my own Controller factory. You can reach the project by the aid of the this link
In this case, my biggest deficiency is; without indicating namespace in route making the same thing in views. So it will search view in area, if it will not be found then it will search in default. Because the project is theme-supported, I use my own themable razor view engine, not default razor view engine. It can be reached by the aid of this link
base.AreaViewLocationFormats = new[]
{
_themeService.Current.BasePath + "/Views/Areas/{2}/{1}/{0}.cshtml",
_themeService.Current.BasePath + "/Views/{1}/{0}.cshtml",
_themeService.Current.BasePath + "/Views/Shared/{0}.cshtml","~/Themes/Default/Views/{1}/{0}.cshtml"
};
I updated the object of AreaViewLocationFormats of RazorViewEngine like this but regardless of the fact that I state area in route, it searches ViewLocationFormats instead of AreaViewLocationFormats if I do not state namespace.
In this case, how should I separate sports?
What I have done in a similar scenario is creating a base generic controller like this:
public abstract class BaseController<TModel> : Controller where TModel : class, new()
{
// Controller Actions to be shared by all the controllers that inherit form this one...
}
And, then your controllers will be like this:
public class TennisController : BaseController<Tennis>
{
}
I was just wondering whether its possible to have something like this: I have an Area named Admin and a Controller named 'Edit'. Within this controller I have my Index() which simply lists a bunch of hyperlinks that is treated by the 'Brand' action.
Therefore my url so far is: Admin/Edit/{Brand}.
My question is whether it is possible to have for example: Admin/Edit/{Brand}/Create (as well as edit and delete). This isn't to delete brands, its just to create things within those brands?
I approach that my approach may be misguided and this may necessitate being split into multiple controllers or whatever so don't think that I would like a workaround to make it work this way.
You could define the following route in your area registration:
context.MapRoute(
"Admin_default",
"Admin/{controller}/{brand}/{action}",
new { action = "Index" }
);
And if you wanted to have other controllers than Edit in this area which have the default route, you could register 2 routes but you will have to define a constraint for the {brand} token or the routing engine won't be able to disambiguate between a brand and a controller action name.
I'm new to MVC and EF and I am experimenting a bit with its functionaltiy. I have a problem with my URL. I have 3 entity classes generated from existing DB with the EF. Those properties get filled but I keep seeing them in my URL even though I changed my routing.
routes.MapRoute(
null,
"Article{articleID}",
new { controller = "Article", action = "Article" }
);
My URL looks like this :
http://localhost:3629/Article2?User=System.Data.Entity.DynamicProxies.User_4AC672CE1F2946F8B58690EA73EF956F43E30746526AD255691FA5ABFC32BBFF&BlogComments=System.Collections........
So everything after the /Article2 should be removed,
can anyone tell me what's going on?
When you make your ActionLink, are you certain that you only send the ID as parameter, and not the entire Article instance?