Appropriate use of Html.ActionLink for a specific rule - c#

I have this rule in the RouteConfig:
routes.MapRoute(
name: "UserProfile",
url: "users/{uid}",
defaults: new { controller = "Users", action = "Profile" }
);
How do I link to this action using #Html.ActionLink? It is easy enough to do it using #Html.Routelink but is it possible to do using the former?

You simply need to pass in the action name, controller name, and then an object that contains other route values, which in this case is uid
#Html.ActionLink("User Profile", "Profile", "Users", new { uid = 1 }, null)
If this doesn't translate into /users/{uid} because of how your routes are setup, then you should use #Html.RouteLink(). #Html.ActionLink() is for linking to an action directly. You provide the action and controller, and it gives a url based off of the routes that you have set up. If there are conflicting routes, you may not get the url you are expecting. In this case, linking to the route you want is the way to go.

Related

Routes are simultaneously valid, yet broken

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.

Asp.Net Core Route Default Action

I have a Asp.net Core application and i use a route like this.
routes.MapRoute(
name: "Address",
template: "adress-info/{action}/{id?}",
defaults: new { controller = "Address", action = "Index" }
);
My url helper generate wrong url addres if i don't use default parameter.
For example
//This is generate right url. http://localhost/address-info
#Url.RouteUrl("Address",new {action="Index"})
//i expect generate same url as up but it's generate http://localhost/address-info/anotherAction
#Url.RouteUrl("Address")
Why doesn't apply MapRoute's default action? What is the problem?
Thank you

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 :)

MVC 3 Routing and Action Links not following expected contextual Route

I'm attempting to do a custom route so I can prefix a url in my application with a chosen string and the do some processing based on that. The problem I'm running into is, that the action links that are generated are not contextualized based on the url that it exists on.
Routes:
routes.MapRoute(
"TestRoute",
"TEST/{controller}/{action}/{id}",
new { controller = "Space", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Space", action = "Index", id = UrlParameter.Optional });
Navigating to TEST/Space/Index works, as well as Space/Index, but the odd issue I need fixed is that the links generated via ActionLink do not obey the context in which they are loaded, at least for the {controller}/{action}/{id} default route. Pages that are loaded under TEST/Space/Index list links properly, but when /Space/Index is loaded, they are all referencing the TEST/ route that the calling url does not. Is this the default behavior? Is there a way to get these links to generate in the proper context?
Edit:
The first place I saw this was in the Html.BeginForm without the TEST/
Html.BeginForm("ToTheMoon", "Space", FormMethod.Post)
which renders the link as TEST/Space/ToTheMoon
but it also shows up in links:
#Html.ActionLink("Take Me To The Space Port", "SpacePort", "Space")
which renders TEST/Space/SpacePort
I found a bit of a way around this so that the context wouldn't be lost. Here's what I did to get this to work.
TestRoute changes to this:
routes.MapRoute(
"TestRoute",
"{path}/{controller}/{action}/{id}",
new { controller = "Space", action = "Index", id = UrlParameter.Optional },
new { path = #"TEST" },
new string[] { "The.Namespace" });
Setting the constraint on path and removing it from the route makes this routing work. Now I can hit the /TEST/Space/Index and all my links generated from ActionLink behave as intended. Also on a related issue, I ended up adding the namespace specification in the map route, as the development environment required that be in there to properly route things to the TEST path.
Some of the info I found was on this page.
If you do:
#Html.ActionLink("Text", "Index", "Space")
That is going to match the first route in your collection (TestRoute). This is the default behavior.
If you want to choose a specific route then use #Html.RouteLink instead.
If you want to target a specific route, you could use RouteLink extension, it allows you to specify which exact route should be used to generate the link.
#Html.RouteLink("with Test", "TestRoute")
#Html.RouteLink("with Test", "TestRoute", new {controller="Space", action="Foo"})
#Html.RouteLink("without Test", "Default", new {controller="Space", action="Foo"})

Categories