I have the problem where URL's are being added on the current URL for example:
Localhost/Config -> Localhost/Config/Profile
By making the call #Html.ActionLink(Resources.General.Achievements, "Index", "Profile")
When what I really want is: Localhost/Profile
I know this is possible using MVC Routes, I just can't figure out how to call them from the View. I have used Html.BeginRouteForm, but this route won't be triggered on submit.
This is my route config
routes.MapRoute(
name: "Profile",
url: "Profile/{id}",
defaults: new { controller = "Profile", action = "Index" },
namespaces: new[] { "Cobalt.Controllers" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Cobalt.Controllers" }
);
I am trying to access the Profile controller and Index action in the root directory. I have both Config and Manage Areas, which I am trying to escape from when making calls back to controllers in the root directory.
Thanks in advance for any help
When dealing with areas, if you want to move from one area to another area or out of an area into the root, you can use the overload of ActionLink which allows you to specify route data and pass an empty string (or the appropriate area name) into area:
#Html.ActionLink(Resources.General.Achievements, "Index", "Profile", new { area = string.Empty })
Use RouteLink:
#Html.RouteLink(Resources.General.Achievements, "Profile", new { id = "1234" })
Do note that since your "id" parameter is not declared optional on your Profile route it won't match unless you supply it.
Related
We have a MVC application with different areas. At moment just one area is registered (defined in config) and no route registrations is done in area registration. I have run into issues with routing as Url.Action method stopped to work. My simplified RouteConfig looks like this:
routes.MapRoute(
name: "Second",
url: "second/{action}/{id}",
defaults: new { controller = "Second", action = "Action", id = UrlParameter.Optional },
namespaces: new[] { "MvcApplication1.Areas.MyArea.Controllers" }
).DataTokens["area"] = "MyArea";
routes.MapRoute(
name: "Home",
url: "home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MvcApplication1.Controllers" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MvcApplication1.Controllers" }
);
The problem is that when I try to call #Url.Action("Index", "Home") inside Action.cshtml in Second controller in MyArea it returns null. When I call the same in Index.cshtml in Home controller it works well. I have found out that when I use #Url.Action("Index", "Home", new {Area = ""}) in Action.cshtml it works well too, but why this is happening? How can I avoid that to be able to call just #Url.Action("Index", "Home") without route values?
This is not a problem but it's actually the proper behavior.
When you use #Url.Action() or #Html.ActionLink it will by default use the area from where it's being called. If you want to link to a different area, as in this case, you need to specify the parameter area as you already found out.
In this particular case when you're trying to link to root area you need to specify the parameter as an empty string as you did. ({Area=""})
I have some files under the views of the area "admin", and i want to rewrite the url of some action like "agence" and "agences" without affecting "login", so how can i do it ?
This is a link to a print screen of my project.
http://hpics.li/764e0ea
If I understand your question correctly, you can solve this issue by creating a new route in your "RouteConfig" file (App_Start -> RouteConfig).
The default route for MVC is:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
You can use this as a template for creating a new route as well. Simply place the new route above the "Default" route. Something like the following:
routes.MapRoute(
name: "Any distinct name",
url: "{controllerName (judging by your question, probably }/{variable1}/{variable2}/{etc... if needed}",
defaults: new
{
variable1 = UrlParameter.Optional,
variable2 = UrlParameter.Optional
}
);
You can then pass your chosen variables as RouteValues in ActionLinks.
#Html.ActionLink("LinkText", "Action", new { variable1 = whatever, variable2 = whateverElse})
I need to have a custom route, like the default one, but this one should accept numeric values as strings. Like 0015. If I leave the parameter type as int, the value passed to the controller method get truncated to 15. And I need 0015.
So what I did, I created the following:
routes.MapRoute(
name: "AccRef",
url: "{controller}/{action}/{acc_ref}",
defaults: new { controller = "Company", action = "Index", acc_ref = "" },
constraints: new { acc_ref = #"^\d{1,4}$" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
And the problem is, as I understand, that when I now pass in an integer as "id"
#Url.Action("Method", "Controller", new { id = item.ref})
from the view, the routing still applies the first route to it and the call fails.
How would you go about solving this problem with routing?
Is it possible to have two same routing configurations where one accepts int and another string?
Your AccRef is too greedy.
If you look at the url generated from the Url helper it is:
Controller/Method/id
This matches your first AccRef route as well as the default route.
You have to be more specific with your routes. Also the order you define your routes are important. So you normally want to define greedier routes last.
Phil Haack has a route debugger on nuget (blog post here) which can help you identify route issues.
If you reverse the order like so:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "AccRef",
url: "{controller}/{action}/{acc_ref}",
defaults: new { controller = "Company", action = "Index", acc_ref = "" },
constraints: new { acc_ref = #"^\d{1,4}$" }
);
Your current scenario will work with above change but the url "/Home/Index/5" or "/Company/Index/0015" still matches both the routes. This is because the routes are generic (as correctly pointed out by Bigfellahull).
In your case since both the parameter is of type int, both the routes are matched.
Option 1:
You can add a extra string say "Acc" in the route url to make it more specific.
routes.MapRoute(
name: "AccRef",
url: "{controller}/{action}/{acc}/{acc_ref}",
defaults: new { controller = "Company", action = "Index", acc_ref = "" },
constraints: new { acc_ref = #"^\d{1,4}$" }
);
In this case the url will change to ".Company/Index/acc/0015".
Option 2:
If you can change the parameter type in action method like so:
public class HomeController : Controller
{
public ActionResult Index(string id)
{
}
}
The url will match only one route.
Option 1 and 2 are for example only to explain how you can make routes more specific.
there's
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
I want to make my url to allow enter company name in the beginning, e.g.:
url: "{company}/{controller}/{action}/{id}"
So I could navigate through pages and now that the base is some company.
domain.com/company-ltd
domain.com/company-ltd/products
domain.com/company-ltd/edit
domain.com/some-other-company-name-ltd/products
and so on.
How could I achieve this? Thanks.
The routes work off the back of patterns; a URL coming in is matched against patterns until one is found that it matches.
Assuming that you're not talking about optional company names, you should be able to get away with:
routes.MapRoute(
name: "Default With company",
url: "{company}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional
);
and then simply ensure that all methods take a company parameter. However, this would fail on more simple routes, so make sure you set a default for pages such as the root. If you do end up wanting additional routes that don't involve a company, those can also be catered for with controller-specific routes:
routes.MapRoute(
name: "Profile",
url: "profile/{action}/{id}",
defaults: new { controller = "Profile", action = "Index", id = UrlParameter.Optional
);
before the less-specific company one.
Note that you can test these routes quite easily in .net using NUnit and MvcContrib.TestHelper, for example:
"~/company/".WithMethod(HttpVerbs.Get)
.ShouldMapTo<Controller.HomeController>(x =>
x.Index("company"));
"~/company/products/".WithMethod(HttpVerbs.Get)
.ShouldMapTo<Controller.ProductsController>(x =>
x.Index("company"));
to ensure that they're going to the locations you'd expect.
Could someone show me how to use the MapRoute method? I have tried creating my own routes, but it's not working. What i want to accomplish is a route that routes "http://servername/home/default.aspx" into controller "Home" and action "Default". Also, would it be possible to say that if the user is browsing the default.aspx "file", it would actually point to the "Index" action?
I have tried reading the MSDN references and googling, but it didn't make me any wiser.
Probably too late to help the developer who raised the question but may help someone else. New to MVC but what I found is the map routes seem to be processed in the order they are added. I had a similar problem, my specific route was not working until I started adding the default route as the last route.
If the default map route is added before your custom one and your custom URL matches the structure defined by the default map route you will never reach your custom route.
The route you want to configure the first part of your question is:
routes.MapRoute(
"",
"home/default.aspx",
new { controller = "Home", action = "Default" }
);
Assuming you wish to 'browse' default.aspx with some sort of parameter you can do something like:
routes.MapRoute(
"",
"home/default.aspx/{param}",
new { controller = "Home", action = "Default", param = UrlParameter.Optional }
);
And you would then need to create your Default action to accept string param.
You also have to make sure the parameter name is the same as the action's parameter name.
Example:
routes.MapRoute(
name: "MyName",
url: "{controller}/{action}/{myParam}",
defaults: new { controller = "MyController", action = "MyAction", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
MyController:
public ActionResult MyAction(string myParam = "")
{
}