Routes are simultaneously valid, yet broken - c#

I asked a previous question here, in which I attempted to use a blank URL to catch a default page.
After some more digging, and some trial and error, I stumbled upon the use of {*url} to catch the root URL. I also attempted to use a constraint to manage the "tidy" url that I want to use. My RouteConfig now looks like so:
routes.MapRoute(
name: "LoginRoute",
url: "{login}",
defaults: new { controller = "LoginController", action = "Index", id = UrlParameter.Optional },
constraints: new { login = "login" }
);
routes.MapRoute(
name: "Default",
url: "{*url}",
defaults: new { controller = "authController", action = "routingsuccess" }
);
However, neither of these routes result in a web page. Instead, they still result in 404. Curiously, however, Phil Haack's RouteDebugger reports that the URL I am using is valid, as demonstrated here:
To clarify, accessing the root url (in this case, localhost:3000) results in the same issue.
There is a valid controller, and a valid view behind it with the appropriate action. What could possibly be wrong?

You can just use the normal default routing.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "authController", action = "Index", id = UrlParameter.Optional }
);
This just mean, if a controller isn't passed in the url then it will use MainController. If an action isn't passed then it will use Index. This mean http://website.com will go to MainController action Index.

Maybe you are using [Authorise] attribute, or something else for authentication.
I will just make a guess : -
Your route is registred, and there is no problem in it. Problem occurs when you try to access it. There might be some kind of authorisation, like an [Authorise] attribute, that would block non access users to get to your route.
Or there might be something else, that would be causing your code to not be able to reach the ActionResult.
To confirm this, put a breakpoint in the constructor of the COntroller.Remove all attributes from the COntroller. If your debugger stops at the breakpoint in constructor, then the issue is not is registering the route, but access related.
Let me know if it helps.

Related

Problems identifying with 'mysterious' calls to action index methods in controllers

I have an issue with calls to action methods being made before, during and after the 1st valid routing path is being processed by VS.
It's difficult for me to provide code because the issue is not related to any particular call I make to these action methods. If I put breakpoints on these known calls, they are never hit, only the actual action method is called.
I can give the routing I use though. If can see the thread in VS that calls these actions but how can I track what is creating these threads? It seems to want to try to load all controllers that match the routes but I thought it stops when it finds the 1st good route.
How can I stop VS from going beyond the unknown good route?
I'd be grateful for any hints at things I can check for.
I have searched for ways to show what calls action methods in controller but I'm not finding anything. Tried playing with Request.UrlReferrer but that always returns null.
What makes no sense is why the action index methods get called including the return call to load a view but these views never get shown in the end.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Root",
url: "",
defaults: new { controller = "Dashboard", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Dashboard", action = "Index", id = UrlParameter.Optional }
);
No error msg.

Is there a way to make URL parameter in MapRoute being take into account in ActionLink?

I built an web application where the RouteConfig.cs was the default one.
Now I received a task where I need to append a customer tracking ID in the beginning of the URL but keeping the same functionality it has when it is not present too.
http://localhost:60202/Home/Index //Generic customer
http://localhost:60202/Location/123/Home/Index //URL with the customer tracking id
This code 123 is a tracking ID where my customer knows the location he originates the call to my page. I have no power to ask them to change this since they use across the globe.
I tried to achieve this with this custom route:
routes.MapRoute(
name: "Route",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "Location/{trackingId}/{controller}/{action}",
defaults: new { trackingId = 0, controller = "Home", action = "Index" }
);
In this case I can access my application with both URL schema I provided above but I couldn't manage to make ActionLink and BeginForm take this into account.
#Html.ActionLink("InĂ­cio", "Index", "Home") //this should have full URL info
Is there a way to achieve this without the need to change every ActionLink, Url.Content and BeginForm and surround them with if in every case?
How could I use both URL schema without change every navigation code?
Our currently implemented approach is to duplicated the folders in IIS since there is only 4 as of today but in near future it can be a pain to maintain.
I don't know why but based on this question it should work out of the box.
Edit 1
Looks like changing position of these two MapRoute are making the ActionLink work as I expected. Unfortunately Url.Content still is buggy.
Well, it's embarrassing but looks like the order you add routes make difference. So I changed to this:
routes.MapRoute(
name: "Default",
url: "Location/{trackingId}/{controller}/{action}",
defaults: new { trackingId = 0, controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Route",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
With this change every ActionLink started to work as I expected. I still had the problem with Url.Content I was using in Ajax calls.
In this case I figured out that I should use Ulr.Action for this instead.
Referenced js and css still used the second MapRoute (or don't even care about the route at all) but this is not a problem.

How to hide controller name in URL when using multiple controllers in MVC?

I have a question regarding routing in ASP.NET, MVC. If I use two or more controllers, how can I go about routing to hide both the controllernames in the URL? I've managed to hide the first controllername, but it gets tricky when I want to hide the second one.
I figured it might not be possible since the webserver needs to know what controller to look for, therefor they require different routes in the URL, but it should be possible for the API to find the appropriate controller by just having the action-name data availible?
RouteConfig.cs:
routes.MapRoute(
name: "proj",
url: "p/{action}",
defaults: new { controller = "Project" }
);
routes.MapRoute(
name: "Default",
url: "{action}",
defaults: new { controller = "Access", action = "login" }
);
The urls look as follows depending on which controller I'm in:
http://localhost:56590/create <- AccessController
http://localhost:56590/p/overview <- ProjectController
This is how I want it to look when I browse the site:
http://localhost:56590/create <- AccessController
http://localhost:56590/overview <- ProjectController
How can I achieve this using routing, if even possible?
Thanks alot for any explanation :)

MVC4 MapRoute for CMS

Am building a CMS using MVC4. My experience with MVC is limited and trying to create a MapRoute that can handle the page structured created by the CMS. URLs for the pages would be along the lines of website.com/About
To handle this I have come up with the following
routes.MapRoute(
name: "Default",
url: "{p}",
defaults: new { controller = "Home", action = "Index", p = UrlParameter.Optional }
);
This works fine for root level pages but if I want sub pages like website.com/About/OurTeam
I get a 404. Ideally what I would like is just be able pass either the whole url after the .com bit as a string and sort it out in the controller or to split the levels up as an array of parameters and pass that through as 'p'.
Hope that makes sense. Any ideas?
You can use:
routes.MapRoute(
name: "Default",
url: "{*p}",
defaults: new { controller = "Home", action = "Index", p = UrlParameter.Optional }
);
The asterisk indicates that it's a catch-all route. Keep in mind that these routes are extremely greedy, make sure that this stays below any specific routes.
You could also add a route constraint to this route which can determine whether the page exists in the database or something. See this post for more info.

MVC routing with "optional" routes

I'm a bit baffled by how MVC is figuring out my routing details. Let me see if I can explain this right.
So ... given that I have the default route ...
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "CMS", action = "GetPage", id = UrlParameter.Optional }
);
And my app is a content management system so I want to create nice urls from the site structure so i'll map a wildcard url that lets me determine if i need to render a 404 based on what's in my database ...
routes.MapRoute(
"CMS",
"{*path}",
new { controller = "CMS", action = "GetPage", path = string.Empty }
);
Herein lies the problem.
MVC will basically match everything to the default route because technically no params are required assuming "GetPage" on the "CMS" controller requires no params, which is not what i want.
What i'm trying to say to it is something like "given 2 or 3 url parts, look for a controller and action match with an optional id parameter but for all other urls including ones that you can't match to this route fall down in to the CMS route".
The only "easy" way I found to do this is to change the first route to something like this ...
routes.MapRoute(
"Default",
"Get/{controller}/{action}/{id}",
new { controller = "CMS", action = "GetPage", id = UrlParameter.Optional }
);
Then any url that starts "Get/" will match that route and all other routes automatically fall down in to the second route, but that doesn't sit right somewhere in my head and I can't figure out quite why yet (i think it's because it doesn't really solve the problem it simply moves it).
My problem is that I don't really want a route that says "given no values match this route anyway" so I changed it to this ...
routes.MapRoute(
"Default",
"{controller}/{action}/{id}"
);
Now for some odd reason literally every request is hitting the catch all (not quite what i want but close).
So any ideas guys?
EDIT:
I came a touch closer with this ...
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { id = UrlParameter.Optional}
);
... but that now matches all urls with 2 parts "foo/bar" rather than dropping through like it should to the other route because there is no "foo" controller.
Ok I have a solution, it works for me because 99% of requests need to map to the CMS route but in your case it may not if you have a lot of controllers you need to map to.
I was hoping to find an ideal solution for all but this is merely an ideal in my scenario ...
So assuming you have (like me) only a cms controller and a an accounts controller you can do this:
routes.MapRoute("Account", "Account/{action}", new { controller = "Account" });
routes.MapRoute(
"Default",
"{*path}",
new { controller = "CMS", action = "GetPage", path = string.Empty }
);
That way only urls starting with "Account" get caught by the first rule, and everything else falls through to the default route and gets handled by the cms controller.
I plan to simply add more routes as I add more controllers. It's not an ideal solution because it could mean i end up with a lot of route mappings in the long term but its a good enough solution to meet my needs.
Hope it helps someone else out there.
Maybe I don't understand your problem fully but why not have this route:
routes.MapRoute(
"CMS",
"CMS/{action}/{path}",
new { action = "GetPage", path = string.Empty }
);
and add it into the route collection before your default path...

Categories