On the Index.cshtml view of EuroController i have an ActionLink that i want to use the "IndexByYear" action of Euro controller:
#Html.ActionLink("Year 2006", "IndexByYear","Euro", new { id = "", year = 2006 }, null)
But the problem is that it goes to the Index() method, even though it's everything set on RouteConfig:
routes.MapRoute(
name: "Default",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Euro",
url: "{controller}/{year}/{id}",
defaults: new { controller = "Euro", action = "IndexByYear", year = DateTime.Now.Year, id = UrlParameter.Optional }
);
Here's the EuroController:
public ActionResult Index(int? id)
{
...
}
public ActionResult IndexByYear(int? id, int year)
{
...
}
Also this don't work, as it also goes to Index() method:
#Html.RouteLink("Ano 2006","Euro",new { id = "", year = 2006 },null)
If i manually navigate to domain/Euro/2016/1, then it uses the correct route. Seems like with no parameters it goes through the Default route.
My question is, why does the ActionLink don't use the IndexByYear as specified, or the RouteLink use the specified default (Euro) route?
If you want just the EuroController to have a "special" routing, you would want to do something like:
routes.MapRoute(
name: "Euro",
url: "euro/{year}/{id}",
defaults: new { controller = "Euro", action = "IndexByYear", year = DateTime.Now.Year, id = UrlParameter.Optional }
);
routes.MapRoute(
name: "DefaultNoController",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { isMethodInHomeController = new RootRouteConstraint<Controllers.HomeController>() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Where the constraint is defined like so:
public class RootRouteConstraint<T> : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var rootMethodNames = typeof(T).GetMethods().Select(x => x.Name.ToLower());
return rootMethodNames.Contains(values["action"].ToString().ToLower());
}
}
This will match
domain/euro/1 to the Index action on EuroController
domain/euro/2008/1 to the IndexByYear action on EuroController
domain/ to the Index action on HomeController
domain/about to the About action on HomeController
domain/someothercontroller to the Index action on whatever other controllers you define
You may want to read https://msdn.microsoft.com/en-us/library/cc668201.aspx and https://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/creating-a-custom-route-constraint-cs
Related
routes.MapRoute(
name: "MyRoute",
url: "{Product}/{name}-{id}",
defaults: new { controller = "Home", action = "Product", name = UrlParameter.Optional , id = UrlParameter.Optional }
);
my routemap and i want my url in product action be like = http://localhost:13804/Wares/Product/name-id
but now is like =
http://localhost:13804/Wares/Product/4?name=name
When defining a route pattern the token { and } are used to indicate a parameter of the action method. Since you do not have a parameter called Product in your action method, there is no point in having {Product} in the route template.
Since your want url like yourSiteName/Ware/Product/name-id where name and id are dynamic parameter values, you should add the static part (/Ware/Product/) to the route template.
This should work.
routes.MapRoute(
name: "MyRoute",
url: "Ware/Product/{name}-{id}",
defaults: new { controller = "Ware", action = "Product",
name = UrlParameter.Optional, id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Assuming your Product action method accepts these two params
public class WareController : Controller
{
public ActionResult Product(string name, int id)
{
return Content("received name : " + name +",id:"+ id);
}
}
You can generate the urls with the above pattern using the Html.ActionLink helper now
#Html.ActionLink("test", "Product", "Ware", new { id = 55, name = "some" }, null)
I know its late but you can use built-in Attribute Routing in MVC5. Hope it helps someone else. You don't need to use
routes.MapRoute(
name: "MyRoute",
url: "{Product}/{name}-{id}",
defaults: new { controller = "Home", action = "Product", name = UrlParameter.Optional , id = UrlParameter.Optional }
);
Instead you can use the method below.
First enable attribute routing in RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
}
Then in WaresController
[Route("Wares/Product/{name}/{id}")]
public ActionResult Product(string name,int id)
{
return View();
}
Then to navigate write code like this in View.cshtml file
Navigate
After following above steps your URL will look like
http://localhost:13804/Wares/Product/productname/5
I am getting url like http://localhost:49671/TestRoutes/Display?f=hi&i=2
I want it like http://localhost:49671/TestRoutes/Display/hi
I call it from Index method.
[HttpPost]
public ActionResult Index(int? e )
{
// return View("Display", new { f = "hi", i = 2 });
return RedirectToAction("Display", new { f = "hi", i = 2 });
}
Index view
#model Try.Models.TestRoutes
#using (Html.BeginForm())
{
Model.e = 5 ;
<input type="submit" value="Create" class="btn btn-default" />
}
Display Action method
// [Route("TestRoutes/{s}")]
public ActionResult Display(string s, int i)
{
return View();
}
Route config file
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Professional", // Route name
"{controller}/{action}/{id}/{name}", // URL with parameters
new { controller = "TestRoutes", action = "Display", s = UrlParameter.Optional, i = UrlParameter.Optional
});
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional
});
You need to change your route definition to
routes.MapRoute(
name: "Professional",
url: "TestRoutes/Display/{s}/{i}",
default: new { controller = "TestRoutes", action = "Display", i = UrlParameter.Optional }
);
so that the names of the placeholders match the names of the parameters in your method. Note also that only the last parameter can be marked as UrlParameter.Optional (otherwise the RoutingEngine cannot match up the segments and the values will be added as query string parameters, not route values)
Then you need to change the controller method to match the route/method parameters
[HttpPost]
public ActionResult Index(int? e )
{
return RedirectToAction("Display", new { s = "hi", i = 2 }); // s not f
}
change your route as
routes.MapRoute(
"Professional", // Route name
"{controller}/{action}/{name}", // URL with parameters
new
{
controller = "TestRoutes",
action = "Display"
} // Parameter defaults
);
and your action as
public ActionResult Display(string name)
{
//action goes here
}
Remove the maproute code:
routes.MapRoute(
"Professional", // Route name
"{controller}/{action}/{id}/{name}", // URL with parameters
new { controller = "TestRoutes", action = "Display", s = UrlParameter.Optional, i = UrlParameter.Optional
});
Use attribute routing code:
[Route("TestRoutes/{s}/{i?}")]
public ActionResult Display(string s, int? i)
{
return View();
}
You can also try using Attribute Routing. You can control your routes easier with attribute routing.
Firstly change your RouteConfig.cs like that:
public class RouteConfig
{
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 }
//);
}
}
After that change your controller files like that:
namespace YourProjectName.Controllers
{
[RoutePrefix("Home")]
[Route("{action}/{id=0}")]
public class HomeController : Controller
{
[Route("Index")]
public ActionResult Index()
{
return View();
}
[Route("ChangeAddress/{addressID}")]
public ActionResult ChangeAddress(int addressID)
{
//your codes to change address
}
}
You can also learn more about Attribute Routing in this post:
https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/
Another way to solve this problem is to put the proper route before the default route, as follows:
routes.MapRoute(name: "MyRouteName", url: "Id", defaults: new { controller= "Home", action = "Index",id= Id });
Default route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{Id}",
defaults: new { controller = "Home", action = "Index",id= Id }
);
I have two route with same signature but only the parameter names are different how to fix this issue.
Following is my code
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "DefaultRoute2",
url: "{controller}/{action}/{formSubmissionId}",
defaults: new { controller = "Employee", action = "Index", formSubmissionId = "formSubmissionId" }
);
The routes are meant to accept different URL structures. Both of your routes have same structure, so the first one will always match, and the second will never be tested.
Instead of using a different route, in /Employee/Index you should just use the parameter id.
public class EmployeeController : Controller
{
public ActionResult Index(string id)
{
string formSubmissionId = id;
}
}
The URL for that action would be the same that (I believe) you wanted to achieve with the second route: Employee/Index/id
UPDATE
I've just realized. If you only need the parameter formSubmissionId for the action /Employee/Index you could do this:
// Note the order of the routes:
routes.MapRoute(
name: "DefaultRoute2",
url: "Employee/Index/{formSubmissionId}",
defaults: new { controller = "Employee", action = "Index", formSubmissionId = "formSubmissionId" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
public class EmployeeController : Controller
{
public ActionResult Index(string formSubmissionId)
{
// ...
}
}
Now i fix this issue as
routes.MapRoute(
name: "DefaultActivity",
url: "{controller}/LoadActivity/{formSubmissionId}",
defaults: new { controller = "{controller}", action = "LoadActivity", formSubmissionId = UrlParameter.Optional }
);
this is work around of my scenario.
Is it possible to create a different default route for a different user role?
e.g.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Admin", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "totalrewardstatement", action = "Details", id = UrlParameter.Optional } // Parameter defaults
);
}
Have the default route above for normal users but use the admin one if an admin user logs in?
Role based routing is not supported in MVC. What you do is have default controller which checks for the roles and redirect to that controller
public ActionResult Index()
{
if (User.IsInRole("Supervisor"))
{
return RedirectToAction("Index", "InvitationS");
}
return View();
}
http://forums.asp.net/t/1994888.aspx?role+based+routing+asp+net+mvc
Using a custom RouteConstraint did the trick for me on mvc 5.
public class RoleConstraint : IRouteConstraint
{
public bool Match
(
HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection
)
{
return httpContext.User.IsInRole(parameterName) ;
}
}
RouteConfig.cs
routes.MapRoute(
name: "Reader_Home",
url: "",
defaults: new { controller = "Reader", action = "Index", id = UrlParameter.Optional },
constraints: new { reader_role = new RoleConstraint() }
);
routes.MapRoute(
name: "Author_Home",
url: "",
defaults: new { controller = "Publication", action = "Index", id = UrlParameter.Optional },
constraints: new { author_role = new RoleConstraint() }
);
I'm using the parameterName (author_role and reader_role) as the role name to check for simplification.
I would like to map http://localhost/Guid-goes-here to ResellerController and fire Index action of that controller only when Guid-goes-here is not the empty Guid.
My routing table looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Reseller",
"{id}",
new { controller = "Reseller", action = "Index", id = Guid.Empty }
// We can mark parameters as UrlParameter.Optional, but how to make it required?
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
The action on the ResellerController looks like this:
public ActionResult Index(Guid id)
{
// do some stuff with non-empty guid here
}
Once the application has started, navigating to http://localhost routes me to the ResellerController with the empty Guid as the argument to the Index action's id parameter.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Reseller",
"{id}",
new { controller = "Reseller", action = "Index", id = UrlParameter.Optional },
new { id = #"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
or if you want a more robust constraint than some cryptic regex:
public class GuidConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var value = values[parameterName] as string;
Guid guid;
if (!string.IsNullOrEmpty(value) && Guid.TryParse(value, out guid))
{
return true;
}
return false;
}
}
and then:
routes.MapRoute(
"Reseller",
"{id}",
new { controller = "Reseller", action = "Index", id = UrlParameter.Optional },
new { id = new GuidConstraint() }
);
You need to include a constraint in the routing definition. Have a look on this post: http://blogs.microsoft.co.il/blogs/bursteg/archive/2009/01/11/asp-net-mvc-route-constraints.aspx