How does the URL match a Controller class in MVC? - asp.net-mvc

Suppose I create a Controller named Login, the IDE generates a file like
Public Class LoginController
Inherits System.Web.Mvc.Controller
'
' GET: /Login
Function Index() As ActionResult
Return View()
End Function
End Class
So when I run my app and enter the following URL
http://localhost:49599/Login
The controller fires, the view is served, etc. But wow does the word "Login" get wired to this LoginController class? What happens if I want to have the option of using a different language and I want to change "Login" to "Logzmein". I'm suspecting resource files should be involved somewhere.

This is part of the convention-based design of ASP.NET MVC. By default, there are default routes defined that route (or convert) a URL into a controller action method.
By default, routes are defined using the following convention:
{controller}/{action}/{id}
So given a URL like this:
User/View/1
It break down like this:
User ({controller}) maps to UserController controller class.
User/View ({controller}/{action}) routes to UserController.View action method.
User/View/1 ({controller}/{action}/{id}) routes to UserController.View action method, passing in 1 as the id parameter.
You can also define custom routes to create your own patterns for routing.
Check out this article for an overview or routing, because it's too much to cover in a single post.

Related

MVC asp.net Resource cannot be found

I am new to asp.net MVC. I have added one controller and view and set route to view my index page. But it is giving me following error.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or
one of its dependencies) could have been removed, had its
name changed, or is temporarily unavailable. Please review
the following URL and make sure that it is spelled
correctly.
Requested URL: /
From your comments I take it, that you misunderstood how the basics of MVC work. (You can read it all here: https://www.asp.net/mvc)
By default MVC has a lot of conventions, so it knows how a route maps to a controller amongst other things. When you issue a request to an url, the default implementation of the MvcHandler receives a controller instance from the default ControllerFactory implementation, which has a convention, that a controller must end on the name Controller. That means, that /Home1Controller/ in your example, lets the controller factory look for a controller class named Home1ControllerController, which most likely does not exist.
For completeness, here are the criteria by which thew default controller factory identifies the correct controller:
class scope must be public
class must not be abstract
class must not take generic parameters
class name must end on "Controller"
class must implement IController interface.
So if you keep the default route, which you have and you have created a controller called Home1Controller, then the route on which you can access the Index method is: /Home1/Index.
If your controller would be namend FooController, then the url would be /Foo/

Html.RenderAction with Route Name

I am trying to utilize the Route attribute naming (ex: [Route(Name = "Abc123")]) in a controller action, and likewise be able to call that via Html.RenderAction, but it appears that this does not support route names. I assume this is because route names are reserved only for ones requested via HTTP and not called directly, but somewhat new to MVC so I'm at a loss.
I'm using MVC Attribute Routing entirely, and I do not have routes configured otherwise. It seems that I must define the route name, and the route name has to match the action method name. In doing so, however, I am getting naming conflicts when I try to name more than one Index.
I'm basically trying to support multiple partial views, each having their own controller, which serve as plugins/widgets on my site. So ideally each would have an action called Index.
Do you have a recommendation on how I can maintain the same naming? This allows me to call Html.RenderAction("Index", [ControllerName], [Model]) without the render name changing.
You can use attribute routing with Html.RenderAction just you have to make sure that the action name in attribute is actual Name :
[Route("Home/About")]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
and in HTML you can have
#{Html.RenderAction("About", "home");}
It will work fine.
You should be able to do what you are trying to do with attribute routing. If you are trying to render a partial view you should be using RenderPartial instead of RenderAction.
Are you doing this between areas? I believe there are some gotcha's with making that work correctly.
Can you please post example Controller code and RouteConfig?

Rendering action from base controller, getting route not defined error

I have a base controller all my other controllers inherit from, inside the base controller are 2ActionResult that is common to every page on my site. When I try to use Html.RenderAction to call either of these actions from a View I get the error
No route in the route table matches the supplied values.
I have checked and the Action is set to public and the names are spelled right. What am I doing wrong?
The call: #{ Html.RenderAction("SectionNavigation"); }
The Action:
[Route("SectionNavigation")]
public ActionResult SectionNavigation()
As you can see I am also using Attribute Routing as well. I also tried updated the call to specify Base as the controller but that did not change anything.
The first parameter of the RenderAction method is the action name, not the route name.
If you're rendering a View that is being generated using a Controller other than the one that defines the SectionNavigation Action, you'll have to specify the Controller name as well:
#Html.RenderAction("SecondNavigation", "YourControllerName").
If you're using Areas, you'll have to include the Area name as well:
#Html.RenderAction("SecondNavigation", "YourControllerName", new { Area = "MyAreaName" }).
See Documentation

ASP.NET MVC Routes: Conflicting action names with custom route

i all,
In a previous question, I asked how to define a custom route to handle the following URL:
http://www.example.com/User/Profile/Edit/{userProfileID}
I have a User object and a UserProfile object, but only a UserController that I want to be able to use for actions on both objects. I already have a method in UserController called Edit that handles edits on a User. But I also need a method for edits on a UserProfile. The answer to my routing question was the following route:
routes.MapRoute(
"ProfileleRoute", // Route name
"User/Profile/{action}/{userProfileID}", // URL with parameters
new { controller = "User", action = "Index" } // Parameter defaults
);
But given that custom route, where should I be declaring the edit action for a UserProfile, and what should it be called? It seems like I couldn't write another method in UserController called Edit because I already have one that handles User edits.
So I feel like I would end up with a need for two Edit actions to handle the following routes: "User/Edit" and "User/Profile/Edit". How do I get around this?
Thanks very much.
When the framework it's going to select what action to execute it first check the actions with the name required with a HttpPost ot HttpGet attribute that match the request, if not action is selected this way, then it select any action that match the name.
So, if you have two actions with the same name with no HttpPost or HttpGet attributes, you can't control with action is going to get executed.

ASP.NET MVC basic routing with no View name

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.

Resources