I have the following ActionLink
:
@Html.ActionLink("Upload", "Upload", "File")
yet when I hover over the link, the url displayed in the browser is http://localhost:44334/Upload
. Where is the controller in this url? Strangely, clicking the url takes me to my File/Upload
view, and yet stranger, the url displayed in the browser's address bar is https://localhost:44334/Upload
.
The ActionLink
is on page Home/Explorer
, so AFAIK a controller name is normally necessary.
Why is the ActionLink
helper leaving out the controller name, and why is the link still working? I have tried refreshing the page with cache clearing, with no difference. I don't know what else do besides leave it alone because it works, but I'm concerned this is some quirk and it will no longer work when I deploy my site.
My routing is still standard, out-of-box, in the Startup
class's Configure
method:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Strangely enough, I have now added a Download
link each row of an HTML table of files, looking like this:
@Html.ActionLink("Download", "Download", "File", new { filePath = file.Path })
and this link also renders without the controller name, e.g:
https://localhost/Download?filePath=....
Yes, there is a difference. Html. ActionLink generates an <a href=".."></a> tag whereas Url. Action returns only an url.
Html. ActionLink creates a hyperlink on a view page and the user clicks it to navigate to a new URL. It does not link to a view directly, rather it links to a controller's action.
Http{Verb}("{routeTemplae}")
is usually used when building a REST API. In order to be able to generate URLs for the default MVC controllers when using attribute routing you will need to use Route
attribute.
The original controller probably did not have a route prefix which meant that
//POST /Upload //<-- when there is no prefix on the controller
[HttpPost("Upload")]
on the controller would route to /Upload
with no controller prefix.
By including a prefix for the route on the controller it will include the controller name when generating URLs when using attribute routing.
[Route("[controller]"]
public class FileController : Controller {
//POST File/Upload
[HttpPost]
[Route("Upload")]
public async Task<ActionResult> Upload(UploadFilesViewModel model, IEnumerable<IFormFile> files) {
//...
}
//GET File/Download
[HttpGet]
[Route("Download")]
public async Task<IActionResult> Download(string filePath) {
//...
}
}
Reference Routing in ASP.NET Core
Reference Routing to Controller Actions
This is most strange, but in my FileController
, I had leftover attribute routing from when I was using the the controller for a Web API instead of in the MVC web application. The methods essentially looked like this:
[HttpPost("Upload")]
public async Task<ActionResult> Upload(UploadFilesViewModel model, IEnumerable<IFormFile> files)
[HttpGet("Download")]
public async Task<IActionResult> Download(string filePath)
Now that I have removed the route names from the attributes, and have just plain [HttpPost]
and [HttpGet]
, the actionlinks work correctly and render URLs that now do contain the controller name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With