Custom Url Routing - c#

For www.demo.com/city/hotel-in-city
routes.MapRoute(
name: "Search",
url: "{city}/{slug}",
defaults: new { controller = "Demo", action = "Index", city = UrlParameter.Optional}
);
For default
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
But when I call the index method of home controller www.demo.com/home/index it points to 1st route(index method of default controller).
How to handle default route ?

The problem is that your "Search" route captures basically everything. One way of handling this is to create more-specific routes for the home controller, and put those first:
routes.MapRoute(
name: "Home1",
url: "/",
defaults: new { action = "Index", controller = "Home" }
);
routes.MapRoute(
name: "Home2",
url: "Home/{action}/{id}",
defaults: new { id = UrlParameter.Optional, action = "Index", controller = "Home" }
);
routes.MapRoute(
name: "Search",
url: "{city}/{slug}",
defaults: new { controller = "Demo", action = "Index" }
);
This will filter out any URL with "Home" as the first parameter, and allow everything else through to the search.
If you have a lot of controllers, the above approach may be inconvenient. In that case, you could consider using a custom constraint to filter out either the default route, or the "Search" route, whichever one you decide to put first in the route config.
For example, the following constraint declares the match invalid, in case the routing engine has attempted to assign "Home" to the "city" parameter. You can modify this as needed, to check against all your controllers, or alternately, against a cached list of available city names:
public class SearchRouteConstraint : IRouteConstraint
{
private const string ControllerName = "Home";
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return String.Compare(values["city"].ToString(), ControllerName, true) != 0;
}
}
This will allow URLs starting with "/Home" through to the default route:
routes.MapRoute(
name: "Search",
url: "{city}/{slug}",
defaults: new { controller = "Demo", action = "Index" },
constraints: new { city = new SearchRouteConstraint() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { id = UrlParameter.Optional, action = "Index", controller = "Home" }
);

Related

How to use multiple route in mvc5

Check the RouteConfig.cs file code bellow on mvc5 project. The first Default route which is configured for return home page is works fine. But the second one which i made to send traffic to Product controller is not working. The way i am trying to hit the controller is- http://localhost:50070/Product/somepage/good-product
The error i am getting is:
The resource cannot be found.
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: "Product",
url: "Product/{pagename}/{slug}",
defaults: new { controller = "Product", action = "Index", slug = UrlParameter.Optional },
namespaces: new[] { "Demo.Controllers" }
);
}
}
You problem is in order of route mappings. Routes are matched in mapping order - in your case Product/somepage/good-product matches default route template and it is chosen. But you don't have action Somepage on Product controller.
Default route mapping should be the last mapping (just change the order):
routes.MapRoute(
name: "Product",
url: "Product/{pagename}/{slug}",
defaults: new { controller = "Product", action = "Index", slug = UrlParameter.Optional },
namespaces: new[] { "Demo.Controllers" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Please change second routes like that
Use controller in order to pagename
routes.MapRoute(
name: "Product",
url: "Product/{controller}/{slug}",
defaults: new { controller = "Product", action = "Index", slug = UrlParameter.Optional },
namespaces: new[] { "Demo.Controllers" }
);

Route Configuration in MVC

The current Route Config for me is this, which I think is the default one
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
When I write
www.mypage.com
www.mypage.com/home
I get the same page
How Can I make it so that they are two individual pages
www.mypage.com
is the homepage, and
www.mypage.com/home
is another page
www.mypage.com can be handler by a root controller and all the other routes will be handled by the default route.
routes.MapRoute(
name: "Root",
url: "",
defaults: new {controller = "Root", action = "Index"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
the explicit defaults allow for the behavior you are currently seeing.
You will still need to create a controller to handle your root site calls
public class RootController : Controller {
public ActionResult Index() {
return View();
}
}
And don't forget to create the related View for your controller.
No need to create a new controller. you can use the same home controller. In Home Controller, create 2 actions - Default and Index. In the routeconfig, use -
routes.MapRoute(
name: "RootDef",
url: "",
defaults: new { controller = "Home", action = "Default", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

How to omit controller name for Home views

Let's say I have this structure:
Home/
Index
About
Project/
Index
Details
How can I omit the controller name for Home views?
I want to write {root}/About instead of {root}/Home/About.
I also want {root}/Project/Details/2 to work.
Here is what I tried in RegisterRoutes:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "DefaultRoute",
url: "{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new
{
controller = "Home",
action = "Index"
}
);
Edit: I also tried swapping the order of my MapRoute calls but it still doesn't work.
What I need is:
{root}/Home/Index > HomeController.Index
{root}/Home > HomeController.Index
{root} > HomeController.Index
{root}/Home/About > HomeController.About
{root}/About > HomeController.About
{root}/Project/Index > ProjectController.Index
{root}/Project > ProjectController.Index
{root}/Project/Details/12 > ProjectController.Details
Just change the order of your MapRoute calls:
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The 'Default' route has to be defined last, otherwise it matches all Url patterns and no further routes are evaluated.
Update:
As per your edit, since you want to preserve the 'controller-name-only' route as well. Try this:
public class ActionExistsConstraint : IRouteConstraint
{
private readonly Type _controllerType;
public ActionExistsConstraint(Type controllerType)
{
this._controllerType = controllerType;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var actionName = values["action"] as string;
if (actionName == null || _controllerType == null || _controllerType.GetMethod(actionName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase) == null)
return false;
return true;
}
}
Then:
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { exists = new ActionExistsConstraint(typeof(HomeController)) }
);
See MSDN

Set custom parameter in Route

I have 2 routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Plugin",
url: "{pluginName}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I would like to use Html.Action helper and set "pluginName" parameter of my second Route.
I am try to use next code
#Html.Action("Index","Person",new RouteValueDictionary { { "pluginName", "myPlugin" } });
and to get link like
http://mydomain/myplugin/Person/index
but I've getting
http://mydomain/Person/index?pluginName="myPlugin"
How can I get first link pattern?
Register your more specific route first. The routing engine evaluates routes in the order you register them. So if you have a fairly generic route registered early on (which you do), the routing engine will use it and append other values as QueryString parameters (which your seeing).
Try this:
routes.MapRoute(
name: "Plugin",
url: "{pluginName}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

MVC4 RouteConfig params return null

My Booking Controller have the following code
public ActionResult Index(string id, string name)
{
return View();
}
and my routeConfig have the below route mappings
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: "Search",
url: "{controller}/{location}/{checkIn}/{checkOut}/{no}",
defaults: new { controller = "Search", action = "Index", location = UrlParameter.Optional, checkIn = UrlParameter.Optional, checkOut = UrlParameter.Optional, no = UrlParameter.Optional }
);
routes.MapRoute(
name: "booking",
url: "{controller}/{action}/{id}/{name}",
defaults: new { controller = "Booking", action = "Index", id = UrlParameter.Optional, name=UrlParameter.Optional }
);}
but when I access the page http://localhost:59041/booking/index/1/libin both params returns null.
see this book
As your application becomes more complex you are likely going to
register multiple routes. When you do this its important that you
consider the order that that you register them. When the routing
engine attempts to locate a matching route, it simply enumerates the
collection of routes and it stops enumerating as soon as it find a
match.
Add a comment This can cause plenty of problems if you’re not
expecting it. Let’s look at an examples where this can be a problem:
routes.MapRoute(
> "generic", // Route name
> "{site}", // URL with parameters
> new { controller = "SiteBuilder", action = "Index" } // Parameter defaults );
>
> routes.MapRoute(
> "admin", // Route name
> "Admin", // URL with parameters
> new { controller = "Admin", action = "Index" } // Parameter defaults );
The snippet above registers two routes. The first route
contains a single placeholder segment and sets the default value of
the controller parameter to SiteBuilder. The second route contains a
single constant segment and sets the default value of the controller
parameter to Admin.
Both of these routes are completely valid, but the order in which they
are mapped may cause unexpected problems because the first route
matches just about any value entered, which means that it will be the
first to match
http://example.com/Admin and since the routing engine stops after
finding the first match, the second route would never get used.
So, be sure to keep this scenario in mind and consider the order in
which you define custom routes.
You should write booking routes at first
routes.MapRoute(
name: "booking",
url: "{controller}/{action}/{id}/{name}",
defaults: new { controller = "Booking", action = "Index", id = UrlParameter.Optional, name=UrlParameter.Optional }
);}
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: "Search",
url: "{controller}/{location}/{checkIn}/{checkOut}/{no}",
defaults: new { controller = "Search", action = "Index", location = UrlParameter.Optional, checkIn = UrlParameter.Optional, checkOut = UrlParameter.Optional, no = UrlParameter.Optional }
);

Categories

Resources