How can i rewrite URL IN ASP.NET MVC? - c#

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})

Related

MVC RouteConfig Style

In my table I have two links:
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Events", "LocationEvents", "Events", new {locationId = item.Id}, null)
Now my goal is when I hover over the links I want the url to look like this for both:
/Locations/Edit/4
/Events/LocationEvents/4
However, I am getting this:
/Locations/Edit?id=4
/Events/LocationEvents/4
Here is my RouteConfig.cs
routes.MapRoute(
name: "Events",
url: "{controller}/{action}/{locationId}",
defaults: new {controller = "Locations", action = "Index", locationId = UrlParameter.Optional}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Locations", action = "Index", id = UrlParameter.Optional }
);
How do I make this work?
Simply, you can't have two routes like this. They're both functionally the same, taking a controller, action and some sort of id value. The fact that the id param names are different is not enough to distinguish the routes.
First, you'd need to distinguish the routes by hard-coding one of the params. For example, you could do something like:
routes.MapRoute(
name: "Events",
url: "Events/{action}/{locationId}",
defaults: new {controller = "Locations", action = "Index", locationId = UrlParameter.Optional}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Locations", action = "Index", id = UrlParameter.Optional }
);
Then, the first route would only match the URL begins with "Events". Otherwise, the default route will be used. That's necessary to handle the routing properly when the client requests the URL. It still doesn't help you in terms of generating the route, as UrlHelper doesn't have enough information to determine which one to choose. For that, you'd need to use the route name to explicitly tell it which one to use:
#Html.RouteLink("Default", new { controller = "Edit", action = "edit", id = item.Id })
Frankly, the RouteConfig-style routing is a huge pain. Unless, you're dealing with a very simple structure that can pretty much just be handled by the default route, then you'd be much better off using attribute routing, where you describe the exact route each action should have. For example:
[RoutePrefix("Events")]
public class EventsController : Controller
{
...
[Route("LocationEvents", Name = "LocationEvents")]
public ActionResult LocationEvents(int locationId)
{
...
}
}
Then, it's absolute explicit, and if you want to make sure you're getting exactly the right route, you can just utilize the name (in conjunction with Html.RouteLink, Url.RouteUrl, etc.).

MVC5 Url.Action returns null inside area

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=""})

MVC 4 custom routing str and int

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.

Asp.NET Mvc 4 Routing

I'm making a blog in mvc 4 and trying make a route .
Here is how it looks now:
/About/Index
But I'd like it to look like:
/About/Firstname-Lastname
The firstname and lastname is always the same; it's not supposed to be dynamic. Here is what I have so far. I know it is because it needs to know what view show. So is there a way to say if /About/Firstname-Lastname then show Index?
routes.MapRoute(
name: "About",
url: "{controller}/{name}/",
defaults:
new
{
controler = "About",
action = UrlParameter.Optional,
name = "firstname-Lastname"
}
);
This should do the trick
routes.MapRoute(
name: "About",
url: "About/Anne-Refsgaard/",
defaults:
new
{
controler = "About",
action = "Index",
}
);
This route needs to be added before the standard route
routes.MapRoute(
name: "FirstnameLastname",
url: "about/Andre-Calil",
defaults: new { controller = "About", action = "Index" }
);
Remember that the order of the routes matter. The first route that accepts the request will be used.

How do I map the root directory to a controller in c# using web api?

I have a c# web api (.net 4) web application. I have several controllers. I'd like to map a new controller to the root directory for the web app.
So, I have http://localhost/listproducts
I'd like the url to be http://localhost
But I don't know how to tell the controller to use the root directory. It seems to be configured based on the name.
The solution I went with is:
config.Routes.MapHttpRoute(
name: "ListProductsApi",
routeTemplate: "",
defaults: new { controller = "ListProducts" } // Parameter defaults
);
The trick is the defaults: new { controller = "ListProducts" } line. (I need a POST action so I just left action out. Apparently when you want the root route "/" you need to explicitly name the controller.
You simply need to change the default route you already have. It should currently look something like this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
Change controller = "Home" to controller = "listproducts".
It should be fairly easy, just change a default route in your global.asax.cs and instead of
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
change it to
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "ListProducts", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

Categories