I am new in mvc and I have a situation where I am convinced that I am mapping a route correctly although it is not.
it is a very basic login form with the option of passing in parameters.
this is the html
<li>Login</li>
and this is the action method in the 'Home' controller
public ViewResult LoginForm(string userName)
{
return View();
}
This is how is my attempt at mapping the route
routes.MapRoute(
null,
"Login/{userName}",
new { controller = "Home ", action = "LoginForm", UrlParameter.Optional }
);
The url is however displaying as follow
/Home/LoginForm?loginUser=user
my aim would be the following
Login/user
Advice perhaps as to why it is not mapping correctly. I have already registered a number of routes in the Global.asax.cs file. Could it have something to do with the order with which they were registered?
Try this:
<li>Login</li>
change the parameter loginUser to userName.
Use userName instead of loginUser
<li><a href='#Url.Action("LoginForm", "Home", new {userName="user"})'>Login</a></li>
You are hitting a different address than the one specified in MapRoute. The mapped route will not fire. Change both the parameter and the action name.
<li>Login</li>
You need to access /Home/Login not /Home/LoginForm. The routing is done automatically if the right address is accessed.
EDIT:
Following your address edit:
As far as I know, you cannot generate a link such as Login/{userName} using Url.Action; if you don't specify a controller, this defaults to Home controller
You can however access the Login/{userName} link directly from the browser (due to the mapped route)
You can create a "static" (i.e. classic) link, passing a hard-coded address:
<li>Login</li>
Please note that the userName added/removed per JavaScript.
Related
I can't find out how to solve this. I have two URLs. These are /my-url-1 and /my-url-2. Both going to different views.
The thing is that I have an ActionLink on /my-url-1's view which should make /my-url-2 and go to that view.
The problem is that ActionLink makes /my-url-1/my-url-2 as the URL and not just /my-url-2.
I was searching two days about how to fix it but couldn't find anything.
PD: I'm not using Areas so please don't tell me that I just should put the "area" parameter as a "".
These are two urls which goes to different controllers and different actions.
View which has the ActionLink (URL:/my-url-1) :
<div class="btn-index-container">
#Html.ActionLink("Url 2", "MyAction", "MyController")
</div>
This ActionLink should render:
Url 2
But it's rendering:
Url 2
where /my-url-1 is my current URL
Route Config
routes.MapRoute(
name: "route1",
url: "my-url-2", //without parameters
defaults: new { controller = "MyController", action = "MyAction" },
);
routes.MapRoute(
name: "route2",
url: "my-url-1", //without parameters too
defaults: new { controller = "MyController2", action = "MyAction2" }
);
So, when I go to localhost:port/my-url-1 it loads MyAction2 which renders a view. This view has inside an ActionLink(described above) which should render a /my-url-2 link.
Well, I've worked inside the MVC framework and I could told you about how Url.RouteUrl or Html.RouteLink works. At the end, the method which create the URL is GetVirtualPathForArea (this method is called before UrlUtil.GenerateClientUrl, which receive the VirtualPathData.cs created by GetVirtualPathForArea, as a parameter) from System.Web.Routing.RouteCollection.cs.
Here I left a link to the MVC source code:
https://github.com/aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc
I found that, my Request.ApplicationPath was changing when I loaded /my-url-1. It was crazy because the application path was /.
At last, the problem was that the /my-url-1 was pointing to a virtual directory created on the IIS some time ago by error.
To know where your IIS configuration file is, please follow the link below:
remove virtual directory in IIS Express created in error
The solution was remove the .vs directory (which contains the config .vs\config\applicationhost.config) and rebuild
I think most of the Helpers that render URLs works more or less in the same way, so I hope it'll useful for all of you!
In your case, maybe no its necesary, just pass the parameters with null values, E.G.
#Html.ActionLink("Español", null, null, new { Lng = "es" }, null)
In this way, the parameters change, and the view is relative, depending on where you are.
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToRoute("Home");
}
I expect this action to redirect the user to the homepage but instead, a redirect loop occurs (according to Chrome).
The aforementioned action belongs to a controller in the "admin" area as where the "Home" route is defined for the default area - I suspect this to be relevant.
Here is the route for good measure:
routes.MapRoute(
"Home",
"{controller}/{action}/{slug}",
new { controller = "Posts", action = "Index", slug = UrlParameter.Optional },
new[] { "GoBlog.Controllers" }
);
Update
Replacing the return statement with the following will cause the action to work as expected:
return RedirectToRoute("Home", (RouteTable.Routes["Home"] as Route).Defaults);
I want to know why this is the case. Ideally I can omit the (cumbersome) second argument.
This issue is particular to the call RedirectToRoute(string) and your particular route:
routes.MapRoute(
"Home",
"{controller}/{action}/{slug}",
new { controller = "Posts", action = "Index", slug = UrlParameter.Optional },
new[] { "GoBlog.Controllers" }
);
What you expected was RedirectToRoute would populate your arbitrary route definition of {controller}/{action}/ with the route's defined defaults:
controller = "Posts", action = "Index"
But RedirectToRoute like all redirect methods, is a part of your controller, and uses your current Controller and Action as Default Values where ever possible. This is a "feature" of the ASP.NET MVC framework -- re-using routes to create new routes. This approach is valuable because your current Controller and Action are strong hints as to your intention.
A great example of this is RedirectToAction(string) which assumes your current instantiated Controller is the default.
Contrast this with:
return RedirectToRoute("Home", (RouteTable.Routes["Home"] as Route).Defaults);
Rather than directing the framework to use it's best guess about how to populate the ambiguous wild card route, you have specifically instructed the framework to use the Defaults from the RouteTable for "Home" route to construct a route and return it as a RouteObject.
When you call RedirectToRoute(string)
This method converts the route name that is passed in routeName to a URL by using the RouteCollection.GetVirtualPath method.
where pass null as parameter RouteValueDictionary. So in this case this parameters was getting from current RequestContext with values for controller, action and etc, i.e. you get url like this
"{controller}/{action}/{slug}"
"Login/Logout/"
and got redirecting loop.
when you call
return RedirectToRoute("Home", (RouteTable.Routes["Home"] as Route).Defaults);
instead RedirectToRoute(string) used RedirectToRoute(String, RouteValueDictionary) and in RouteCollection.GetVirtualPath method you pass defaults values for that route.
It is a general best practice in MVC to allow your controllers as much control as possible. There are multiple controller methods which you can use, and you should generally use the one that is the closest fit to the process you are performing.
return View(). tells the controller to generate and return the specified HTML, similar to a Server.Transfer(). Use for matching HTML with Actions, or when delivering static HTML without interest in the URL string.
Return RedirectToAction(). Tells the controller to build a new URL string based on the Action. This will parse the route dictionary for the Action, and handle the defaults. It acts as a Response.Redirect(), and will return a new generated URL. In general, this is the most commonly used redirect. This also has the benefit of not changing if the route dictionary is changed.
return RedirectToRoute(). Similar to RedirectToAction(), however tied to the Route Dictionary. This will search the Route Dictionary for an exact route match, using whatever route parameters are passed. This does not look for Actions, and thus does not build a route or inject default values. Used when an exact route with specific non-default values must be processed.
return Redirect(). This redirect requires a full URL, and will redirect to the new URL. Usually used when redirecting to a URL on a totally different domain.
I would like my ASP.NET MVC4 application to only serve the base HTML markup for a specific page, and after that I'm processing everything else on client-side with knockout.js/history.js/AJAX, including the initial page load.
So when someone refers to URL http://example.com/products/list/food/fruits, the MVC router should simply ignore everything what is behind "products/list" and route the request to ProductsController and List action. Then on client-side I will handle the rest and load the requested data accordingly.
I was playing with the route definitions, I tried to completely skip the "products/list" route, I also tried to add a "products/list/*" route, but didn't have success yet.
You can use an asterisk as part of the last variable in a route. For example, when configuring your routes:
routes.MapRoute(
"ProductRoute",
"products/list/{*otherArgs}",
new { controller = "Products", action = "List" });
You can learn more in MSDN's Documentation on routing under the section "Handling a Variable Number of Segments in a URL Pattern"
You will need to create your own route.
Something like this should do the trick:
routes.MapRoute("Products", "Products/{List}",
new {controller = "Products", action = "List"}
);
Note: I´m not sure if the other parameters are required in the route.
I set up a Route in a standard MVC router in global.asax, using MapRoutes. looks like this
routes.MapRoute(
null, //route name
"AddUnregisteredUser/{phonenumber}", //params
new { controller = "User", action = "AddUnregisteredUserFromPhoneNumber" }
);
UserController.AddUnregisteredUserFromPhoneNumber returns a View that displays two ViewData["key"] values...
whenever i debug the project, and call LOCALHOST:PORT/AddUnregisteredUser/1234567890 I get nothing. I put breakpoints in teh controller function and its not even going to the controller function. I put breakpoint in the global.asax and it never sets up the route when starting the asp.net development IIS server....
I dont see what is wrong with my code. any help would be appreciated.
Try supplying a route name instead of null.
Also, you might want to use RouteDebugger from RouteMagic to verify your route definition.
You need to supply a route name as well as add phonenumber to your route values as follows:
routes.MapRoute(
"route1", //route name
"AddUnregisteredUser/{phonenumber}", //params
new { controller = "User", action = "AddUnregisteredUserFromPhoneNumber", id = UrlParameter.Optional}
);
I want to get the url for my site as "www.ABCD.com/username" without the controller name in MVC architecture, such that when i click the name of the particular user i want to show details of the user with just the name of the user showing in url.
This should get you going in the right direction:
routes.MapRoute(
"ViewProfile",
"{username}",
new { controller = "User", action = "ViewProfile" },
// new { username = "\w+" } // consider using a username regex here
);
Note that you will need to update the controller and action values to match your application. The ViewProfile action should look something like this:
public ActionResult ViewProfile(string username) { }
Keep in mind that the above route is very greedy and you will have to make sure any other actions which need to be accessed within your application are placed higher up in the route definitions list. Also keep in mind that if a user should pick a username that conflicts with a route you've defined above the ViewProfile route, the user's profile will never be accessible via the rooted path because the other route will override it.