Remove or replace existing routes in RouteTable - asp.net-mvc

I got a ASP.NET MVC 2.0 Preview 1 app and started to create some areas which contains their own routes.
I want to have a way to overwrite these routes in the main project. I can of course not add a new route with the same name. I can see the RouteTable.Routes.Remove(RouteBase item) but not sure how to use it.
//Need to remove "PostIndex" before adding it again
routes.MapAreaRoute(
"OurAreaNameSpace",
"PostIndex",
"post/index/{currentPage}",
new { controller = "Post", action = "Index", currentPage = "" },
new string[] { "OurAreaNameSpace.Controllers" }
);

How do in this?
RouteTable.Routes.Remove(RouteTable.Routes["PostIndex"]);

Related

Mvc, Register area on the fly without using AreaRegistration

I try create a framework that work with multiple MVC project. I want to add each project as an area.
I can't use AreaRegistration in each project so I try simulate area in my code like this :
foreach (var module in InstalledModules)
{
routeCollection.MapRoute(
name: "Default_" + module.AreaName,
url: module.AreaName + "/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional },
namespaces: new[] { module.Namespace }
);
}
The InstalledModules is a list of all modules that contain area name like Module1 and root namespace of module assembly like MvcProject.Module1. The above code MapRoute all installed modules but it isn't work. For all request first registered rout hit and MVC try find controller in wrong assembly (location).
Is there any way to register project assemblies as area on the fly?
Or
How I can customize the find matching route method?
Do you specified Controllers in namespace? your InstalledModules list must be like this :
var InstalledModules = new List<InstalledModule>
{
new InstalledModule() { AreaName = "Main", Namespace ="MainWeb.Controllers"},
new InstalledModule() { AreaName = "Web1", Namespace = "WebApplication1.Controllers"},
new InstalledModule() { AreaName = "Web2", Namespace = "WebApplication2.Controllers"},
};
I found my problem. Route collection always contains a default route. When I remove this every this work fine.

redirect creating unwanted text in path

I'm working on an existing project that is not routing redirects as I would expect.
my redirect is like this:
return RedirectToAction("Display", "Ladder", new { DisplayDate = DateTime.Now.ToString("yyyyMMdd"), #id = details.CommunityId, slug = details.Slug, InnerId = activityId });
The url it takes me to is: http://localhost:8050/the-staples-club/communitydocuments/161/ladder-display/opq6l4et4bd7/20160429
The url is almost correct, except that a mysterious 'communitydocuments' has been inserted which causes the url to fail. When I remove that part, it works fine. As you can probably tell, I don't understand too much about routing, but where in the project could I investigate to stop it creating 'communitydocuments'?
edit: In routeconfig.cs there are a couple custom routes, but nothing explaining where 'communitydocuments' is coming from. I tried creating a custom route as follows but it still does the same thing:
routes.MapRoute(
name: "LadderDisplay",
url: "{slug}/{id}/{controller}-{action}/{innerid}/{displayDate}",
defaults: new
{
controller = "Ladder",
action = "Display",
displayDate = UrlParameter.Optional,
}
,
constraints: new
{
displayDate = #"\d{8}"
}
);

Using one similar route url for two different parameter types

So I have following routes in place in my project, what I want to do here use one similar looking route url but direct it to two different actions based over the parameter provided, if the given parameter is a string it should pick the Search route and if the parameter is a digit/integer than it should pick the GetCategory route and to achieve this I have written the following code after seeking some existing online help here over SO, but this doesn’t seems to be working as expected.
No matter what the parameter value is it always picks whichever route appears first in the list.
//routes.MapRoute("GetCategory", "{pId}", new { controller = "Student", action = "Post", pId = #"^\d{1,3}$" });
routes.MapRoute("Search", "{category}", new { controller = "Student", action = "Search", category = UrlParameter.Optional });
routes.MapRoute("GetCategory", "{pId}", new { controller = "Student", action = "Post", pId = #"^\d{1,3}$" });
Can anybody help me out with what am I missing here?
Just tested this approach
routes.MapRoute("GetCategory", "{pId}", new { controller = "Student", action = "Post" },new {pId = #"\d"});
routes.MapRoute("Search", "{category}", new { controller = "Student", action = "Search", category = UrlParameter.Optional });
You should apply restrictions on your params within constraints argument, not in defaults section.
Have you tried moving the GetCategory route up above the other one. The problem with the Search route is you don't have a constraint on it so it would match anything. If you moved the GetCategory route to the top and provided a string, it wouldn't match since it is not a digit and would move to the next one.

Generic ASP.NET MVC Route Conflict

I'm working on a Legacy ASP.NET system. I say legacy because there are NO tests around 90% of the system. I'm trying to fix the routes in this project and I'm running into a issue I wish to solve with generic routes.
I have the following routes:
routes.MapRoute(
"DefaultWithPdn",
"{controller}/{action}/{pdn}",
new { controller = "", action = "Index", pdn = "" },
null
);
routes.MapRoute(
"DefaultWithClientId",
"{controller}/{action}/{clientId}",
new { controller = "", action = "index", clientid = "" },
null
);
The problem is that the first route is catching all of the traffic for what I need to be routed to the second route. The route is generic (no controller is defined in the constraint in either route definition) because multiple controllers throughout the entire app share this same premise (sometimes we need a "pdn" sometimes we need a "clientId").
How can I map these generic routes so that they go to the proper controller and action, yet not have one be too greedy? Or can I at all? Are these routes too generic (which is what I'm starting to believe is the case).
My only option at this point (AFAIK) is one of the following:
In the contraints, apply a regex to match the action values like: (foo|bar|biz|bang) and the same for the controller: (home|customer|products) for each controller. However, this has a problem in the fact that I may need to do this:
~/Foo/Home/123 // Should map to "DefaultwithPdn"
~/Foo/Home/abc // Should map to "DefaultWithClientId"
Which means that if the Foo Controller has an action that takes a pdn and another action that takes a clientId (which happens all the time in this app), the wrong route is chosen.
To hardcode these contstraints into each possible controller/action combo seems like a lot of duplication to me and I have the feeling I've been looking at the problem for too long so I need another pair of eyes to help out.
Can I have generic routes to handle this scenario? Or do I need to have custom routes for each controller with constraints applied to the actions on those routes?
Thanks
Add constraints to your routes by removing the null and replacing it with the constraint needed for that route:
For PDN, use a regular expression for digits:
routes.MapRoute(
"DefaultWithPdn",
"{controller}/{action}/{pdn}",
new { controller = "", action = "Index", pdn = "" },
new { pdn = #"\d+" }
);
For ClientID, use a regular expression for all characters:
routes.MapRoute(
"DefaultWithClientId",
"{controller}/{action}/{clientid}",
new { controller = "", action = "index", clientid = "" },
new { clientid = #"[A-Za-z]+" }
);
Since I don't keep the minutia of regular expression stuff in my head, I generally use a cheat sheet.
You should add some route constraints that say the PDN route matches numbers and the ClientId matches strings
I usually create a series of matches to use throughout my route declaration like so:
readonly static string ALPHA_MATCH = #"[\da-zA-Z]";
readonly static string DIGIT_MATCH = #"\d+";
then add the constraints to the routes like this:
routes.MapRoute(
"DefaultWithPdn",
"{controller}/{action}/{pdn}",
new { controller = "", action = "Index", pdn = "" },
new { pdn = DIGIT_MATCH }
);
routes.MapRoute(
"DefaultWithClientId",
"{controller}/{action}/{clientId}",
new { controller = "", action = "index", clientid = "" },
new { clientId = ALPHA_MATCH }
);

ASP.NET MVC view locations and routing

I have a base controller that I use to return basic views like this.
public ActionResult Index(string pageName)
{
return View(pageName);
}
public ActionResult LanguageSpecific(string ul, string pageName)
{
var result = View("sv/" + pageName);
return View(result.ViewName);
}
The controller's name is home is there a way that for it not to look for the sv content in /home but just in /sv
"EnglishRoute", // Route name
"{pageName}.aspx", // URL with parameters
new { controller = "Home", action = "Index", pageName = "" } // Parameter defaults
);
routes.MapRoute(
"SwedishRoute", // Route name
"{ul}/{pageName}.aspx", // URL with parameters
new { controller = "Home", action = "LanguageSpecific", ul = "",pageName = "" } // Parameter defaults
);
It looks in these locations:
~/Views/Home/sv/index.aspx
~/Views/Home/sv/index.ascx
When you call the View method you can pass in an app-relative path that starts with "~/" and then ASP.NET MVC will use the exact path you specify:
return View("~/UseExactlyThisFile.aspx");
That way it won't do its search in the various paths and locations that are pre-configured.
Please keep in mind that this doesn't have very much to do with routing (though it does a little bit).
If you try to localize your pages, why don't you use resources? With the pattern above you don't really take the advantages of mvc. Or do i misunderstand you? A simple solution would be to use an action filter which picks up the language identifier from the route and sets the UICulture. The Views then may use resources to localize their content.

Resources