Map Custom Route ASP.NET MVC5 - c#

I haven't used .NET Routing before.
I have a URL: http://myurl.com/Account/Login/?IsIPA=true.
I want to be able to hit this URL with the following: http://myurl.com/IPA
This is the only custom route I want hit.
Can I create a route just for a single URL like this?
My code that isn't working is:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute("IPA", "Account/Login/{IsIPA}", new { controller = "Account", action = "Login", IsIPA = "true" });
}
I get the error:
The constraint entry IsIPA on the route with route template Account/Login/{IsIPA}=True must have a string value or be of a type which implements System.Web.Routing.IRouteConstraint.

Route matching is similar to a switch case statement. The url parameter and any default values and constraints are all considered to determine whether or not it is a match with the incoming URL. If the route matches, it will then create a dictionary of route values based on the configuration. If the route does not match, the next route in the collection is tried until a match is found (or not).
This means the order that routes are specified is important. The default route matches any URL with 0, 1, 2, or 3 segments. Therefore, in most cases you will need to define your custom route before the default route.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "IPA",
url: "IPA",
defaults: new { controller = "Account", action = "Login", IsIPA = "true" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
The above configuration will route http://myurl.com/IPA to the Controller named Account and Action method named Login, and pass the additional route key IsIPA. This same URL will be built for the Controller/Action/IsIPA combination because it is the first one that matches in the list.
Note that the original URL http://myurl.com/Account/Login/?IsIPA=true will still work and still route to the same location. This configuration just adds an extra route to that resource.

Without testing it, I think that you want this:
routes.MapRoute("IPA", "Account/Login/{IsIPA}",
new { controller = "Account", action = "Login", IsIPA = "true"});

Related

Why does an ASP.NET MVC route have a name?

In an ASP.NET MVC 5 web application, there is a RouteConfig class that registers many routes. In all of the examples I have seen so far, only the "Default" route has a non-empty name. The URL pattern and default route values seem to be sufficient to correctly associate any URL to the controller and action to execute. So, is there any benefit to naming a route? For debugging or logging? Just for self-documenting the code?
For example:
public class RouteConfig
{
public static void RegisterRoutes( RouteCollection routes )
{
routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );
// Most pages.
routes.MapRoute( name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "home", action = "index", id = UrlParameter.Optional }
// A special page.
// Should the route have a name?
routes.MapRoute( name: "",
url: "special",
defaults: new { controller = "special", action = "index", HttpVerbs = HttpVerbs.Get } );
}
}
The main reason to name a route is so that if you need a link to a route from somewhere in the app, you can reference the name. That way if the actual URL/path changes you don't break everywhere in the code that references that route.

Not receiving get parameters

I'm using ASP.NET MVC 5
I'm having issues with both routes and parameters.
I have this function in my ControllerBase
[HttpGet]
[Route("~/obtenerAngulos/{Conex_AT}/{Conex_BT}")]
public JsonResult obtenerAngulos(string Conex_AT, string Conex_BT)
{
return Json(
new
{
AT = Conex_AT,
BT = Conex_BT
}
, JsonRequestBehavior.AllowGet);
}
And I start having problems receiving the second parameter Conex_BT the Url.Action() returns this route http://localhost:53645/Base/obtenerAngulos?Conex_AT=Y&Conex_BT=y the problem, is Conex_BT is always null
Then I try to work with route and add the Data Anotation for it [Route("~/obtenerAngulos/{Conex_AT}/{Conex_BT}")] but with Url.Action() I keep getting the same route as before.
Even if I try to write it manually like http://localhost:53645/Base/obtenerAngulos/AA/BB I get
HTTP Error 404.0 - Not Found
I mention both problems because I'm pretty sure they are relationated.
Here is the route configuration
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Make sure you have enabled attribute routing on the route collection.
//enable attribute routes
routes.MapMvcAttributeRoutes();
//convention-based routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This now means that the following should match obtenerAngulos/y/x
public class ControllerBase: Controller {
//Matches obtenerAngulos/y/x
[HttpGet]
[Route("~/obtenerAngulos/{Conex_AT}/{Conex_BT}")]
public JsonResult obtenerAngulos(string Conex_AT, string Conex_BT) {
//...
}
}
The tilde (~) on the method attribute is used to override any route prefixes if needed.
Routes are matched in the route table in the same order they are added. In your example you had convention based routes registered before attribute routes. Once a route is matched it no longer looks for other matches.
Reference Attribute Routing in ASP.NET MVC 5

ASP.NET MVC routing task

I have the following route table:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "UserRoute",
url: "{username}",
defaults: new { controller = "User", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
so, when we have url like : http://mysite/abcde it calls UserController, action Index, if we have url like : http://mysite/dashboard/Index it calls DashboardController, action Index. Ok. But when I try to call the following:
return RedirectToAction("Index", "Dashboard");
It calls UserController, action Index with username parameter equals "Dashboard". Why and how to solve?
Your routing is correct (at least for the URLs you provided). But you are not calling the redirect correctly.
When you generate an outgoing route, it doesn't match a URL, it matches the route values that are passed. Your UserRoute contains 3 route values:
username
Controller
Action
So, in order to generate a URL (or redirect) based on this route, you need to pass all 3 parameters.
return RedirectToAction("Index", "Dashboard", new { username = "Fred" });
That said, MVC will automatically reuse route values if they are in the current request. So, if your route already has a username value (for example, you are already at the URL /Fred), it will be able to match the route without specifying the route value explicitly.
return RedirectToAction("Index", "Dashboard");

How to remove question marks in Asp.net MVC routes multiple parameters

When I pass multiple parameters to a controller action, I get question marks in the parameters like this:
http://localhost:57728/Home/AddAndManageProperties?BaseCategoryId=11&SubCategoryId=14
I want to remove the question marks to be like this:
http://localhost:57728/Home/AddAndManageProperties/BaseCategoryId=11/SubCategoryId=14
here is my code:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "MyRout",
url: "{controller}/{action}/{BaseCategoryId}/{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties", BaseCategoryId = UrlParameter.Optional, SubCategoryId = UrlParameter.Optional }
);
}
}
And here is the Action Method:
public ActionResult AddAndManageProperties(int? BaseCategoryId, int? SubCategoryId)
{
}
And i call the method AddAndManageProperties by this method
[HttpPost]
public ActionResult AddSubCategory(SubCategory subCategory)
{
return RedirectToAction("AddAndManageProperties", new { BaseCategoryId = subCategory.BaseCategoryId, SubCategoryId = subCategory.SubCategoryId });
}
I am new to ASP.NET MVC so please help me!
Move the MyRout to be before the Default route and change it to
routes.MapRoute(
name: "MyRout",
url: "Home/AddAndManageProperties/{BaseCategoryId}/{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
Note that only the last parameter can be marked UrlParameter.Optional so the method needs to be
public ActionResult AddAndManageProperties(int BaseCategoryId, int SubCategoryId)
for the above route, or
public ActionResult AddAndManageProperties(int BaseCategoryId, int? SubCategoryId)
if you modify the above route definition to
defaults: new { controller = "Home", action = "AddAndManageProperties", SubCategoryId = UrlParameter.Optional }
Note, if you also want to include the text "BaseCategoryId" and "SubCategoryId" in the route, use
url: "Home/AddAndManageProperties/BaseCategoryId/{BaseCategoryId}/SubCategoryId/{SubCategoryId}",
That question marks are used for query strings, and they are required because this is how data is assigned to parameters your actions expect. You should not try to remove them, but you could use the [FromBody] attribute, not to send the parameters in query string.
Firstly, and most importantly, your routes are in the wrong order and you have multiple possible URLs that result in calling the wrong route. See Why map special routes first before common routes in asp.net mvc for an explanation.
Secondly, routes cannot contain more than one UrlParamter.Optional.
Third, the = sign is only valid within a query string, unless it is encoded. But IMO, you should not use unsafe characters in a URL to avoid all of the headaches that come with them. A better alternative in this case would be to replace the = with a -.
Finally, if you want to truly make the parameters optional, one approach is to provide multiple routes that allow the parameters in certain routes but not others.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "BaseCategoryAndSubCategoryId",
url: "{controller}/{action}/BaseCategoryId-{BaseCategoryId}/SubCategoryId-{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "BaseCategoryIdOnly",
url: "{controller}/{action}/BaseCategoryId-{BaseCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "SubCategoryIdOnly",
url: "{controller}/{action}/SubCategoryId-{SubCategoryId}",
defaults: new { controller = "Home", action = "AddAndManageProperties" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
NOTE: Stephen's answer is also a good alternative to this approach if your parameters are required to be passed in the URL. IMO, it makes more sense to use required parameters if your action method requires both of them in order to function.
But by far the simplest option is to simply use the query string. The parameters can naturally be optional and appended in any order if you do it that way, and you don't need anything more than your Default route.

RouteConfig setup to accept an optional parameter

I am having problems setting up the RouteConfig file to accept an optional record ID as part of the URL like in the examples below.
http://localhost/123 (used while debugging locally)
or even
http://www.foobar.com/123
Ideally, I would like to have the record ID (123 as in the examples above) be passed in as a parameter to the Index view of the Home controller. I had thought that the default routeconfig would suffice for this (using the ID as an optional element), but apparently the application is apparently trying to direct the browser to a view called '123' which obviously doesn't exist.
My current RouteConfig.cs looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Any assistance on this would be greatly appreciated.
Your routing says:
{controller}/{action}/{id}
that's your site then your controller, then your action and then an id.
You want just site then id:
routes.MapRoute(
name: "Default",
url: "{id}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);
This would then hit a controller at
public class DefaultController : Controller
{
public ActionResult Index(int id)
{
}
}
"{controller}/{action}/{id}" tells MVC that a route may have a controller name, or it may have a controller name followed by an action name, or it may have those two followed by an ID. There's no way, given just an ID, for the routing to understand that it's supposed to be an ID and not an action or a controller name.
If you're never planning to have any other controllers or actions, something like this might work:
routes.MapRoute(
name: "Default",
url: "{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
But that's probably a bad idea. Pretty much every site has at least one key word to indicate what the ID represents. For example, StackOverflow has "/questions/{id}".

Categories

Resources