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.
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
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
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 }
);
Does any body knows how to hide some parameters in url?
For example you have a url parameter "culture". It can be "en, fr, it".
By default your site renders in "en" culture and we don't wont to show default culture in the URL but in cases of other cultures parameter "culture" must appear in URL.
http://myrendersite.net/barbikueue
http://myrendersite.net/fr/barbikueue
This is same pages in different cultures.
How to do what basing on default asp.net mvc routing system?
This will help:
ASP.NET mvc, localized routes and the default language for the user
asp.net mvc localization
Set Culture in an ASP.Net MVC app
You have to register two routes:
routes.MapRoute(
name: "DefaultLang",
url: "{language}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { language = "[a-z]{2}"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Create an Attribute that inherits ActionFilterAttribute:
public class LanguageActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var routeDataKey = "language";
var defaultLang = "en";
var defaultCulture = "EN";
// if no language route param received
if (filterContext.RouteData.Values[routeDataKey] == null /* && currentCulture != "en-EN" */)
{
// change culture to en-EN
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", defaultLang, defaultCulture));
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", defaultLang, defaultCulture));
}
else
{
/*if (currentCulture != "whatever")
{
//set culture to whatever
}*/
}
base.OnActionExecuting(filterContext);
}
}
After that create a BaseController with the previous created attribute:
[LanguageActionFilter]
public abstract class BaseController : Controller
{
}
And all your Controllers will inherit BaseController now, instead of Controller
The following RouteConstraint might help,
public class CultureConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.UrlGeneration)
{
return values[parameterName] != null &&
(route.Defaults[parameterName] == null ||
values[parameterName].ToString().ToLower() != route.Defaults[parameterName].ToString().ToLower());
}
return true;
}
}
Use it as,
routes.MapRoute(
name: "Culture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new {culture = "en", controller = "Home", action = "Index", id = UrlParameter.Optional},
constraints: new {culture = new CultureConstraint()}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
Here the constraint only works on outbound url and discard the route for candidacy when 'culture' in route information equals to default.
I used the simplest implementation because you have not posted your route code, but the idea should work.
hope this helps.
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