ASP.NET MVC basic routing with no View name - asp.net-mvc

This is a basic question about the routing machinery. From a new MVC project, I have this in the HomeController:
public ActionResult MyPage()
{
return View();
}
In the Views\Home folder, I have MyPage.aspx. The routing is still the default of {controller}/{action}/{id}. When I type in http://localhost:1790/Home/MyPage, it is correclty routes to MyPage.aspx. Since I haven't said anything about which view to render, how does ASP.NET MVC know to correctly route to MyPage.aspx? Looks as though the ActionResult name can also be used as the View/aspx page name...unless there is something I misunderstand in how the routing works. I can see how I end up in the Home folder, since the controller name corresponds to the View sub folder name. But does the Action name also correspond to the aspx name?
Would that work if the page was a PHP?

ASP.NET MVC subscribes to what is known as the Convention over Configuration paradigm whereas if you follow their conventions, basic things such as routing concerns will happen for you. But they also allow you to configure them if desired.

MVC implicitly assumes that if you return just View(), that you want View("MyPage") (i.e. the action name). No sense in repeating yourself unnecessarily.
It won't find a PHP file by default, but I'm sure you could override that behavior if you really wanted to. I can't imagine a sane scenario where you would be mixing PHP and ASP.NET MVC, but who knows :)

Action name is the same as the view / partial view name.
asp.net mvc doesn't work with php as far as I'm aware.

As has already been stated, ASP.NET MVC uses convention over configuration. Out of the box, your folder structure is something like this (only showing relevant portions and doing it from memory so...)
Site Root
+ Controllers
HomeController.cs
AccountController.cs
+ Views
+ Home
Index.aspx
+ Account
Index.aspx
+ Shared
The default routing handler is something similar to the following:
"{controller}/{action}/{id}"
There are default values for the route, but if you have a url that is a/b/c, it will look for action a on controller aController and pass it c as a parameter if said method on the controller accepts parameters.
A couple of things about that then need to be clarified. Again, convention over configuration:
1) All controller classes must end with Controller if you're using the default engine. That way, when a request comes in and the {controller} value is parsed, the engine adds Controller to it, looks in the Controller folder (and, thus, namespace), and locates the class.
2) By default -- this can be changed -- all views for a controller must reside in the Views/{controller} folder or in the Views/Shared folder.
3) Public methods on a controller are, by default, actions. You can hide this with an attribute to make themethod unavailable to the engine, but by default they are public.
So, when a request comes in the route is compared against all known routes (global.asax) and the first route that matches the request is accepted. The route is then parsed into the component parts to determine the controller, action, and parameters for the action.
Once the controller is identified, the engine instantiates an instance of that controller and executes the matching method (action) should it be found.
The action will return an ActionResult. View is an extensino method that actually returns ViewResult (if I remember that correctly). The default view for an action is a view of the same name as teh action residing in the Views/{ControllerName} folder.
Routing is a beast unto itself and I'd recommend a good bit of reading on it if you're going to play with it. Minutes to understand but a lifetime to master sorta thing.
To my knowledge, BTW, there is no engine that will use a php page as a view for a controller action.

Related

¿Relation between Controller's Action Method and the Views?

I've a couple conceptual questions about the relationship between the Controller Action Method and the View:
I see that the name of the view is in function of Controller's name; the name of the controller class is the same of the namespace of the view (represented by the name of the folder where is the .cshtml file) and the name of the method is the same name of the .cshtml file which is the view. Why it works so? If I miss something in the explanation, How it exactly work?
Is there a way where I can put the .cshtml files (views) outside from the folder which match the name of the Controller's class name?
Is a restriction from MVC that names of .cshtml files match the name of the controllers action methods?
What exactly is the View() method which is returned in the controller action method?
Why the methods of the controller class are called "Controller Action Methods"?
Is a restriction from MVC that the names for the controllers end with "Controller" word?
Thanks to all
I would highly suggest running through a tutorial on MVC, such as this codeproject tutorial.
Naming convention are not set in stone, but in general allows for an understandable structure.
Yes, to navigate to a View you can specify the path. return View("~/this/is/your/path/ViewName.cshtml");
No. See above, you can return any view from any methods with the correct path, assuming the return type fits the return type of the method (Explained below).
View() is a C# "method" which tells the project to navigate to the View you specify, along with any parameters you pass. A more correct and in depth answer can be found by looking at the docs. The default return View() attemps to navigate to the return View("MethodName");
Action methods are methods with a return type of ActionResult. Redirect and View are examples of such. Think of them as similar to object return types, such as void or string, but instead ActionResult will tell your project to do something, such as redirect to another method or return a ViewResult via View().
No. Try it! It is however usually good practice, as it will easily separate your files by name, since you will likely have similar filenames n your project.

Views / Controller Actions / Routes / Gobal.asax

I am new to ASP.NET MVC, coming from a web forms background in the past year and I've started working with MVC 3 recently and have questions that seem to have no good answers (none that I can find at this point) and wanted to post them here. Any help would be appreciated. My questions focus solely on controllers, controller actions, views, and the global.asax.
I understand the relationship to views, controllers, and actions within controllers. When it comes to creating a view though, does every action associated with a view that is created have to be registered in the global.asax? Example: When creating an empty project, the global.asax already creates a default route for the Home controller with an action of Index and id being optional. So, if I create another view called "AboutUs" based on the Home controller, do I need to registered that in the global.asax as a part of the Home controller?
Is there a one-to-one relationship in terms of controller / action and registration in the global.asax for routes? Can more than one controller action be added to the same statement separated by comma (like as in the using the example Home controller in the global.asax and then adding another action to the same statement or does a new statement need to be added outside of that?
Is there a "best practices" standard to use when creating controllers / views / routes?
I am asking these questions since I am converting a web forms site over to MVC 3 and not finding many good answers to my questions. Looking forward to any and all responses.
Scott Gu had a great post about how MVC routing works on his blog, you should check it out!
There to be a matching pattern in the Global.asax for every route, but not necessarily an explicit match. For your example, if you have a view called 'AboutUs', if you have a controller action named that it will just work due to the pattern matching:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
The row: "{controller}/{action}/{id}" is the pattern that is being matched by the routing engine. It says that any URL path that matches above will be sent to the correct view. For your example if you were to follow the url: Home/AboutUs then it would take you to the Home Controller, About us view, with no parameter.
Regarding your 2nd question, the controller that is selected is also part of the pattern. If you added a second controller, called Contact, and then an action called email, then this url would still follow the same pattern: Contact/Email, so you would not need to add an extra route.
Here are some other great blog posts about how MVC routing works, which will point you in the right direction. One on Asp.Net, a blog post, and on MSDN
No you don't need to register every view you create in Global.asax. The routing will take care of that as long as you follow conventions (i.e routing that is defined for you or one you define yourself should you take this path)
Not again. When you create new Action inside your controller, you typically will need to create a view for that action to render what it intended to do (ajax/json actions can serve as an exception to this rule). But again, you don't need to register anything in Global.asax those. As long as you follow the routing convention defined in that Global file.
I'd say it comes with experience with MVC. In general, every problem has its own solution, so its up to task at hand, rather than general approach. You can, however, start with the default defined for you by MVC 3: I.E. redefined routing and multiple controllers with multiple actions in each. Again, following conventions.
Hope this helps.

ASP.Net MVC: same action name in different controllers

I have 2 controllers which are SearchController and SearchByStaffController respectively. They are very similar and both have an action with action name "Search". When I call View("Search") in their common super class, the confusion comes. Only the "Search" view with SearchController is rendered.
Does the MVC framework get only the first view that matches the name and ignore the rest?
I tried to pass the view path in View() and it worked. Would there be any side effect for doing so? I searched over the web and seems no one has done this before.
Thanks!
Does the MVC framework get only the first view that matches the name and ignore the rest?
Yes. The routing rules are aparsed (top to bottom) and when a rule is matched all end.
I tried to pass the view path in View() and it worked. Would there be any side effect for doing so? I searched over the web and seems no one has done this before.
You can but I don't like that because MVC is based on conventions. So, I see forcing the path of the view a way to broke a convention. Are you sure you can't simply create two routing rules for the two methods? So you can do something like this:
return RedirectToAction("Search", "Controller1");
and
return RedirectToAction("Search", "Controller2");
user932390,
mvc uses convention over configuration. this means that the 'search' view will have to be located in both the:
views/Search
and
views/SearchByStaff
folders respectively. the only way around this is to locate the search view under the views/shared folder, then the viewengine will find it there in both cases and use it (assuming they have the same model).

ASP.Net MVC redirecttoaction not passing action name in url

I have a simple create action to receive post form data, save to db and redirect to list view.
The problem is, after redirecttoaction result excutes, the url on my browser lost the action section. Which it should be "http://{hotsname}/Product/List" but comes out as "http://{hotsname}/Product/".
Below is my code:
[HttpPost]
public ActionResult Create(VEmployee model, FormCollection fc)
{
var facility = FacilityFactory.GetEmployeeFacility();
var avatar = Request.Files["Avatar"].InputStream;
var newModel = facility.Save(model, avatar);
return RedirectToAction("List");
}
The page can correctly render list view content, but since some links in this view page use relative url, the functions are interrupted. I am now using return Redirect("/Employee/List") to force the url. But I just wonder why the action name is missing. I use MVC3 and .Net framwork 4.
I am new to ASP.Net MVC, thanks for help.
Your route table definitely says that "List" action is default, so when you redirect to it as RedirectToAction("List") - routing ommits the action because it is default.
Now if you remove the default value from your routes - RedirectToAction will produce a correct (for your case) Url, but you'll have to double check elsewhere that you are not relying on List being a default action.
Well, Chris,
If you get the right content on http://{hotsname}/Product/ then it seems that routing make that URL point to List either indirectly (using pattern like {controller}/{action}) and something wrong happens when resolving URL from route or {action} parameter is just set wth default value List. Both URLs can point to the same action but the routing engine somehow takes the route without explicit action name.
You should check:
Order in which you define your routes
How many routes can possibly lead to EmployeeController.List()
Which one of those routes has the most priority
Default values for your routes
Just make the route with explicit values: employee/list to point to your List action and make sure that is the route to select when generating links (it should be most specific route if possible).
It would be nice if you provide your routes mappings here.
but since some links in this view
page use relative url, the functions
are interrupted.
Why do you make it that way? Why not generate all the links through routing engine?
When using the overload RedirectToAction("Action") you need to be specifying an action that is in the same controller. Since you are calling an action in a different controller, you need to specify the action with the alternate overload e.g. RedirectToAction("List", "Employee").

Should I be calling each of my MVC views Index.aspx?

If I'm not mistaken - the conventions of ASP.NET MVC seem to want me to do the following for a controller view.
Thats to day I create 'Products' directory into which I place my 'Index' view. I then create a 'ProductsController' and create an 'Index' method on it which returns a View. Returning just View() with no arguments will go and fetch the 'Index.aspx' page because its the same name as the method.
public class ProductsController : Controller
{
public ActionResult Index()
{
return View(); // looks for Index.aspx in Products directory
}
}
Now thats just fine. BUT I'll end up with a billion Index.aspx pages, and I'm one of these people that never closes any files so I'll end up going crazy.
Alternatively I can create Products/Products.aspx and change my controller to the following :
public class ProductsController : Controller
{
public ActionResult Index() // my default routing goes to Index (from sample project)
{
return View("Products");
}
}
I understand how that works, and that its completely fine within the MVC design pattern to do this. Its not a hack or anything like that.
My problem (after listening to this PDC video) is that convention over customizabiltity is favored in MVC (or whatever the correct phrase is).
So I'm wondering if I'm missing a third way, or if people are just fine with 50 Index tabs in Visual Studio?
Having the default action for each controller have the same name just simplifies the routing (check global.asax). Also, it all things (Products, Books, Contacts, ...) use actions/views with the same name for the same function, then the code becomes much easier to navigate and understand. This use of convention is especially important when working as part of a team as it will encourage consistent code across developers.
While looking at another question, I ran across SimplyRestfulRouting in the MVCContrib project on codeplex. This might give you some ideas.
I think you should name the method after the action and name the view (if it makes sense and it's not shared between actions, the same as the action). You should probably change your routing mechanism as Index isn't really a descriptive name. The action name should represent what it does (just like any method) and shouldn't be hardcoded to Index or something like that. Routing should be edited instead.
It's just a pattern. Use the pattern, but make it work for you. Personally, I like to have my Views named by their function and I don't have many Index.aspx pages, because I don't have many indices.

Resources