I have the following routes and typing them in the browser works fine and routes correctly, but if I use a Html.ActionLink, it tries using the DefaultStuff Route.
Routes
_routes.MapStuffRoute(
"DefaultStuff",
"stuff/{controller}/{id}",
new { id = UrlParameter.Optional },
new[] { typeof(BaseApiController).Namespace });
_routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { typeof(BaseController).Namespace });
Page
#Html.ActionLink("Job Queues", "Index", "Job") // generates http://localhost/stuff/job?action=Index
What am I missing to allow ActionLink to generate http://localhost/stuff/index. Reversing the routes the ActionLink is correct but the Stuff does not work. Just a note, the StuffRoute sets the action name based on the information in the request.
It seems as though you actually are trying to map the controller "Job" to stuff. Currently your "DefaultStuff" route does not resolve an action, so it is putting it in as a query string value.
_routes.MapRoute(
"DefaultStuff",
"stuff/{action}/{id}",
new { controller="Job", id = UrlParameter.Optional },
new[] { typeof(BaseApiController).Namespace });
Related
I have two controller in my MVC application. One is Home controller and other is User controller. I am using following RouteConfig settings.
routes.MapRoute(
"actiononly",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I want abc.com/Blog
abc.com/Login
Instead of abc.com/Home/Blog
abc.com/User/Login.
Above configuration works fine with abc.com/Blog but it is not working with abc.com/Login.
How to remove controller name from the link for both controllers?
Also how can I only show abc.com when website launches instead of abc.com/index? I am using following code in my webpage to access the particular page.
#Html.ActionLink("Home", "Blog", "Home")
#Html.ActionLink("Login", "Login", "User")
Your default route should automatically cater for wanting to nav to abc.com without requiring the index part of the URL
You need to ensure that your main route is specified as the default:
context.MapRoute(
"Site_Default",
"{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
If you want to map short routes you can do exactly what you've done above. I use this helper function in my own project to map short routes:
void ShortRoute(string action, string controller)
{
ShortRoute(action, controller, action);
}
void ShortRoute(string action, string controller, string route)
{
_context.MapRoute(route, route, new { action, controller });
}
With usage:
ShortRoute("About", "Home");
Which allows me to navigate to mywebsite.com/about instead of mywebsite.com/home/about
If it's not working for certain URLs it may be that the route handler is matching a different route - I believe it does depend on the order you register them
There's a good route debugging plugin you can use
https://www.nuget.org/packages/routedebugger/
It gives you a summary of all routes and which ones matched the current URL - very useful
Without bringing in additional packages, you simply need to add an additional route. To create the new route, you first must define what you want your URL to be. In this case, you have said you want to be able to go to /Login which is on the user controller. Ok - let's create a new route. This route should be located ABOVE your default route.
routes.MapRoute(
"UserLogin",
"Login/{id}",
new { controller = "User", action="Login", id = UrlParameter.Optional }
);
The first parameter is simply the route name. The second parameter is the format of the URL that I want this route to match. Given we know what action we want to match to this route, we don't need the {action} or {controller} catchall placeholders that are in the default route. Also note that we can declare what controller this route will hit without having to specify the controller in the URL.
Last note, you don't have to have the {id} be part of the route if you will never be passing an ID parameter to that function. If that is the case, then you can safely remove any references to id in the UserLogin route.
As I re-read your question, you should be able to do this for some of your other examples as well. Let's take the /About URL and demonstrate the removal of the {id} parameter.
routes.MapRoute(
"AboutUsPage",
"About",
new { controller = "Home", action="About"}
);
This is very simple. You just need to create a route for each of your expected URLs.
Keep in mind that if you don't pass the controller or action as a URL placeholder, you will need to do so manually by providing them as default values.
routes.MapRoute(
"Blog",
"Blog/{id}",
new { controller = "Home", action = "Blog", id = UrlParameter.Optional }
);
routes.MapRoute(
"Login",
"Login/{id}",
new { controller = "User", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
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
);
I have an MVC website which used to use URLs in the standard format of: Controller/Action.
Recently, I have changed it to: Site/Controller/Action.
The problem is, there are several links to my site out there which follow the old format, and I want to redirect them accordingly.
for example: mydomain.com/Home/CustomerSearch now should go to mydomain.com/Online/Home/CustomerSearch
whereas: mydomain.com/AffiliatesHome/CustomerSearch now should go to mydomain.com/Affiliate/AffiliatesHome/CustomerSearch
How can I get it to handle the redirecting by putting in the extra routing, depending on the link they came in by?
The current routing I am using is:
routes.MapRoute(
"Default", // Route name
"{site}/{controller}/{action}/{id}",
new {site="IS", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Since I do not really see an schema in your old to new URL mapping I would suggest to add routes that match the old Controller/Action Schema and map them to the new Site/Controller/Action route schema.
So you could add the following routes
routes.MapRoute(
"LegacyHome",
"Home/{action}/{id}",
new { site="Online", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"LegacyAffiliates",
"AffiliatesHome/{action}/{id}",
new { site="Affiliate", controller = "AffiliatesHome", action = "Index", id = UrlParameter.Optional }
);
From an SEO standpoint this is not ideal because you have different URLs for the same page. A permanent redirect via status code 301 and the new URL passed in the location is better suited.
You could build a redirect controller and use the legacy routes to map legacy URLs to the redirect controller somehow like this
routes.MapRoute(
"LegacyHome",
"Home/{newAction}/{id}",
new { controller = "Redirect", action = "Redirect", newSite = "Online", newController="Home", newAction = "Index", id = UrlParameter.Optional }
);
Code of the redirect controller
public class RedirectController : Controller
{
public ActionResult Redirect(string newSite, string newController, string newAction)
{
var routeValues = new RouteValueDictionary(
new
{
site = newSite,
controller = newController,
action = newAction
});
if (RouteData.Values["id"] != null)
{
routeValues.Add("id", RouteData.Values["id"]);
}
return RedirectToRoutePermanent(routeValues);
}
}
I am having trouble trying to get a route working in an area I have.
My area is called ABC and I have a controller called Home within the area. I am able to hit the breakpoint with Home/Index if I browse "http://localhost:8000/abc" however when I try hit another action called details like "http://localhost:8000/ABC/details" I get a 404.
I have tried
context.MapRoute(
"details",
"ABC/Home/{action}/{id}",
new { action = "details", id = UrlParameter.Optional },
constraints: null,
namespaces: new[] { "WebApplication.Areas.ABC.Controllers" }
);
context.MapRoute(
"ABC_Home",
"ABC/{controller}/{action}/{id}",
new { controller = "home",action="Index", id = UrlParameter.Optional },
constraints: null,
namespaces: new[] { "WebApplication.Areas.ABC.Controllers" }
);
This allows me to hit the action if I use "http://localhost:8000/ABC/Home/Details"
context.MapRoute(
"details",
"Home/Home/{action}/{id}",
new {controller="home", action = "details", id = UrlParameter.Optional },
constraints: null,
namespaces: new[] { "WebApplication.Areas.ABC.Controllers" }
);
Ideally I don't want to use home within the url if possible. What am I doing wrong?
Any help would be awesome!
I think you would just need a single route for this. Don't include the controller in the route, since it seems to be implied by starting with /ABC; just assign the controller as a default value:
context.MapRoute(
"ABC_Home",
"ABC/{action}/{id}",
new { controller = "home", action="Index", id = UrlParameter.Optional },
constraints: null,
namespaces: new[] { "WebApplication.Areas.ABC.Controllers" }
}
Per your requirements, this will route /abc to /home/index, and will route /abc/details to /home/details.
Then, if you need to access other controllers you can add another rule for that, something like the default one:
context.MapRoute(
"Default_Route",
"{controller}/{action}/{id}",
new { id = UrlParameter.Optional }
}
I don't think you can default a controller with a variable action name, otherwise there's no way to tell from the routes that it is an action or controller and which route to match. I think you could hard-code the action though:
Context.MapRoute(
"ABC_Home_Details",
"ABC/Details/{id}",
new { controller = "home", action="details", id = UrlParameter.Optionsl },
constraints: null,
namespaces: new [] { "WebApplication.Areas.ABC.Controllers" }
);
I have a controller that has an action called RedirectLogin, it basically sets a TempData var to redirect back to when the login is finished.
After this, it simply calls:
return RedirectToRoute("Login");
However, the when it redirects, it goes to /login/RedirectLogin - it is tacking on the calling action's name for some reason. I think it should just be returning the defaults, not adding actions, especially actions not part of the destination controller.
If I call:
return RedirectToRoute("Login", new { action = "Index" });
Then it properly makes the path /login, but again, shouldnt it be doing that by default, without the extra bit?
I have a slightly non-standard routing setup. Basically I am creating virtual subfolders for my clients, so www.domain.com/clienturl but I still want www.domain.com/join or www.domain.com/about to redirect to non-client data. I do this by adding the name of the controller directly in the path, and add it before the more generic one called Landing. Could this be the problem, or is there a better way to do it :)
// Root paths
routes.MapRoute("About", "about", new { controller = "Home", action = "About" });
routes.MapRoute("Info", "info", new { controller = "Home", action = "Info" });
routes.MapRoute("Privacy", "privacy", new { controller = "Home", action = "Privacy" });
routes.MapRoute("Terms", "terms", new { controller = "Home", action = "Terms" });
// Root controllers
routes.MapRoute("Join", "join/{action}/{id}", new { controller = "join", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Login", "login/{action}/{id}", new { controller = "login", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Account", "account/{action}/{id}", new { controller = "account", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Goodbye", "goodbye/{action}/{id}", new { controller = "goodbye", action = "Index", id = UrlParameter.Optional });
// Organization
routes.MapRoute("Landing", "{organization}/{controller}/{action}/{id}", new { controller = "Landing", action = "Index", id = UrlParameter.Optional });
// Default
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
It's reusing the data from the current request. since you have the optional parameter 'action' it is taking the action parameter from your current request who's action is RedirectLogin and it attaches that to the url. I'd make a specific route entry without the optional parameters to your login page or redirect to action and not used named routes. There is a page in the book Pro ASP.NET MVC 2 that explains what's happening in more detail.
Alternatives you may wish to try are as follows:
RedirectToAction(String, String, RouteValueDictionary);
RedirectToAction(String, RouteValueDictionary);
Redirect("~/login"); // Note, this works but if you move around the urls for your routes you'll need to fix it everytime... not recommended
The MSDN article here shows all of the available Methods on a Controller: http://msdn.microsoft.com/en-us/library/system.web.mvc.controller_methods%28v=VS.98%29.aspx
Don't use the RedirectToActionPermanent or RedirectToRoutePermanent for this purpose though...