ASP.Net MVC: Need guide line for a specific routing - asp.net-mvc

My routing code is not working.
i am showing data in tabular format with sorting and pagination. my solution is working. when i hover mouse on column then url looks like http://localhost:55831/Customers?page=2&SortColumn=CompanyName&CurrentSort=ContactName
when i click on pagination numeric link then url looks like http://localhost:55831/Customers?page=3&SortColumn=ContactName
i want my url should look like
1) http://localhost:55831/Customers/2/CompanyName/ContactName
2) http://localhost:55831/Customers/3/ContactName
so i add one routing code. here it is
routes.MapRoute(
name: null,
url: "Customers/{page}/{SortColumn}/{CurrentSort}",
defaults: new
{
action = "Index",
page = UrlParameter.Optional,
SortColumn = UrlParameter.Optional,
CurrentSort = UrlParameter.Optional
}
);
after adding the above routing code url looks bit weird. now url looks like
http://localhost:55831/Customers/1/CompanyName/CompanyName?controller=Customers
http://localhost:55831/Customers/2/CompanyName?controller=Customers
so when i click on above links then i am not redirecting to proper controller and action rather getting error.
so it means there is some problem in code which i added as routing in route.config.cs file.
so please help me to get my desired url what i mention above. thanks
EDIT
my full routing code
routes.MapRoute(
name: null,
url: "{controller}/{action}/{page}/{SortColumn}/{CurrentSort}",
defaults: new
{
action = "Index",
page = UrlParameter.Optional,
SortColumn = UrlParameter.Optional,
CurrentSort = UrlParameter.Optional
}
);
routes.MapRoute(
name: null,
url: "{controller}/{action}/{page}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
page = UrlParameter.Optional,
}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

This won't work because your routes have optional parameters which conflict with other routes.
For example take the url /MyController/MyAction/MyPage/213.
How would the routing be able to determine if you want: {controller}/{action}/{page}/{id} or {controller}/{action}/{page}/{SortColumn}/{CurrentSort}.
One solution might be to remove the optional parameters:
page = UrlParameter.Optional,
SortColumn = UrlParameter.Optional,
CurrentSort = UrlParameter.Optional
So your routes would look more like this:
routes.MapRoute(
name: "PageWithSort",
url: "{controller}/{action}/{page}/{SortColumn}/{CurrentSort}",
defaults: new { action = "Index" }
);
routes.MapRoute(
name: "PageWithId",
url: "{controller}/{action}/{page}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
However, here you are still going to get a conflict with PageWithId and the Default routes. So if you never use id in the Default routing then you might want to remove the optional parameter there. Or, if all routes with page always have an id then you could remove the optional parameter there. Alternatively, if page and id are truely optional you may consider removing the default route as PageWithId with the two optionals would handle both.
Side note: You should always name your routes as later it will allow you to do things like this:
#Html.RouteLink("Link Text", "RouteName", new { controller = "xxx" })
From your provided code you might consider changing
#Html.ActionLink("Company", "Index", new { page = ViewBag.CurrentPage, SortColumn = "CompanyName", CurrentSort = ViewBag.CurrentSort })
To
#Html.RouteLink("Company", "PageWithSort", new { controller = "Customers", action = "Index", page = ViewBag.CurrentPage, SortColumn = "CompanyName", CurrentSort = ViewBag.CurrentSort })

Related

MVC Routing Issue when trying www.example.com/id

Let say I have a website www.example.com
the default routing looks like
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
Ok that works fine but let's say I want my site when I go to www.example.com/id to go to www.example.com/login/index/id
How would I configure/add routing for this, without breaking my other pages where I am actually trying to go to www.example.com/controller?
EDIT: Unfortunately id is a string so I do not have any concrete constraints that I can think of that would work. Think of maybe instead of the id I should have said companyname or sitename so the URL would look like www.example.com/companyname .
The only solution that I have come up with so far is adding a maproute for each one of my controllers like this
routes.MapRoute(
name: "Home",
url: "Home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Settings",
url: "Settings/{action}/{id}",
defaults: new { controller = "Settings", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "companyname",
url: "{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
This will work but I have many controllers and if I add one in the future and forget to adjust the routes it will fail. Also, this is unlikely but if a companyname happens to the be same as one of my controller names it would also fail.
In controller you may redirect to another Controller/action:
public ActionResult yourAction()
{
return RedirectToAction("nameAction","nameController");
}
Did you tried adding this mapping first:
routes.MapRoute( name: "Custom", url: "{id}", defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional } );
That should work but keep in mind that routes are evaluated secuentially, so you will have to organize mappings in order to reach out all pages in your site.
For example, routes like www.example.com/Product could be redirected to /Login by mistake.
EDIT: You can add constraints, so if id is an int value, you can try with the following:
routes.MapRoute("Custom", "{id}",
new { controller = "Login", action = "Index" },
new { id = #"\d+" }
EDIT 2: Having ids as string values, the only solution I see is to manually add each controller as you said, or to add something like this:
routes.MapRoute(
name: "Default",
url: "app/{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
This way you don't need to update each route in the future.
Please try below routing
routes.MapRoute(name: "companylogin", url: "companylogin/{id}", defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
});
routes.MapRoute(name: "default", url: "{controller}/{action}/{id}", defaults: new
{
controller = "Login",
action = "Index",
id = UrlParameter.Optional
});
Remove other controller specific routing. Now you can navigate to login using
url : - www.example.com/companylogin/{id} and all other url redirect default route.

MVC: Multiple Routes for 1 Controller

I want users to be able to access the "/Linecard" page of my ASP.Net MVC site using "/Linecard" or "/Manufacturers" as the URL... so same controller, 2 different possible URLs.
I tried adding the following:
routes.MapRoute(
name: "Manufacturers",
url: "Manufacturers/{action}/{id}",
defaults: new { controller = "Linecard", action = "Index", id = UrlParameter.Optional }
);
Adding this after the "Default" route doesn't work at all and I get a 404 error when I go to "/Manufacturers". Putting it BEFORE "Default" works, but then only "/Manufacturers" shows up in the URL when I click menu links since it is the first match. I would like "/Linecard" to always show as the URL.
Any pointers? Is there a certain constraint I can use to accomplish this? Thanks!
I had the same problem when we moved to extension-less URLs. We needed to continue to support one route with extensions. I got around it by having my default route apply to everything except the old URL, then after that mapping one specifically for the exception
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
// if controller specified does not match 'manufacturers' (case insensitive)
new { controller = "^((?i)(?!manufacturers).)*$" },
new string[] { "Namespace.Of.Controllers" }
);
routes.MapRoute(
"Manufacturers", // Route name
"Manufacturers/{action}/{id}", // URL with parameters
new { controller = "Linecard", action = "Index", id = UrlParameter.Optional },
new string[] { "Namespace.Of.Controllers" }
);
You could also set an order when mapping your routes with the defaults at the end like so
routes.MapRoute(
name: "Manufacturers",
url: "Manufacturers/{action}/{id}",
defaults: new { controller = "Linecard", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

After a change to the default routing map my actionlinks stopped working

I made a change to my routing map which is following now:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{title}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, title = UrlParameter.Optional }
);
And this is the actionlinks that are not working anymore:
#Html.ActionLink("Category", "CategoryList", "Category")
When I click on this actionlink nothing happens the url stays the same http://localhost:62394/ as the page reloads. its so weird
and when I check the html it looks like this:
Category
Any kind of help or tips is appreciate alot!
note: If I remove title from the routing it works...
It's because you've got 2 optional parameters so the routing engine doesn't know which one to map the third parameter to. It feels like title is going to be used for a specific route rather than a generic one. If that's the case, why not create a specific route for it and remove it from the generic fallback route?
Something like this:
routes.MapRoute(
name: "Title",
url: "Category-List/{title}",
defaults: new { controller = "Category", action = "CategoryList", title = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Route value removed but still added as query string parameter

I am extending a model to include a link property. It is based on other properties within it to generate a link:
public partial class MyModelType
{
public string FilterLink
{
get
{
var u = new UrlHelper(HttpContext.Current.Request.RequestContext);
var route = new RouteValueDictionary(u.RequestContext.RouteData.Values);
route.Remove("other");
route.Add("other", null);
route.Add("id", this.Id);
return u.Action("Index", "ControllerName", route);
}
}
}
The link generated is /ControllerName/1?other=2. If I get rid of the route.Remove("other") I get the link based on the mapped route: /ControllerName/1/2. How can I prevent it being used as a query string parameter when it is removed from the route? The UrlHelper seems to be adding it somehow, even though it is not a route value.
Check your routing configuration.
MVCs routing will append any unkown parts of your route in that way, so as long as you define it up front it should work just fine.
You probably just have this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Try adding the option like this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}/{option}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, option = UrlParameter.Optional }
);
The issue is discussed here: http://erraticdev.blogspot.com/2011/03/removing-route-values-from-linksurls-in.html
However, the blogs proposal is convoluted compared with a simple solution in the comments: add "other = null as object" to the defaults values on your DEFAULT route.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, other = null as object }
);

In ASP.NET MVC, why doesn't this url match a route when using /id but ?id= works?

First, here's the route:
routes.MapRoute("PlaceRoutes", "{b}/Places/Show/{id}/{subaction}",
new { b = "yokota-ab-japan", controller = "Places", action = "Show", id = UrlParameter.Optional, subaction = UrlParameter.Optional }
);
This url: localhost/yokota-ab-japan/Places/Show/4b5bfc7ef964a520332029e3
does not match it,
this url: localhost/yokota-ab-japan/Places/Show?id=4b5bfc7ef964a520332029e3
does.
In fact somehow when /id is used, it simply routes back to the root homepage. When I run it in the debugger, it never even touches the Places/Show action, it simply routes back. However, if I use ?id= it routes fine.
I've never had this happen before... very confused. I tried to use Phil Haack's route debugger, but since it's not even touching the route and just loops back to the homepage, the debugger doesn't help.
Edit - Here's the full routes list
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("PlaceRoutes", "{b}/Places/Show/{id}/{subaction}",
new { b = "yokota-ab-japan", controller = "Places", action = "Show", id = UrlParameter.Optional, subaction = UrlParameter.Optional }
);
routes.MapRoute("BaseRoutes", "{b}/{controller}/{action}/{id}",
new { b = UrlParameter.Optional, controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "Home|Member|Places|Search|Admin" }
);
routes.MapRoute(
"NullBase",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "Home|Member|Places|Search|Admin|Auth" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
if its asp.net mvc 3.0, its a known bug with two consecutive optional params
http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx
After much digging, it turns out it was only that one url. Somehow it had gotten a HTTP 301 code in the past, redirecting it back to the homepage... I guess browsers remember that. ;)

Resources