ASP.NET Core MVC ActionLink - asp.net

I am new to ASP.NET Core and building a Project in .NET Core MVC.
In my Admin Area I have a controller UserRolesController and Action CreateRole (Works Alright)
In the View, I added a Hyperlink to the CreateRole Action
<a class="btn btn-primary" asp-controller="UserRoles" asp-action="CreateRole">Create Role</a>
But after running the link shows as https://localhost:44332/UserRoles/CreateRole instead of https://localhost:44332/Admin/UserRoles/CreateRole
Again link the Area to my Homepage returns https://localhost:44332/UserRoles?area=Admininstead of https://localhost:44332/Admin/UserRoles
This is how my routes are configured
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapAreaControllerRoute(
"admin",
"Admin",
"Admin/{controller=Home}/{action=Index}/{id?}");
endpoints.MapAreaControllerRoute(
"client",
"Client",
"Client/{controller=Home}/{action=Index}/{id?}");
endpoints.MapAreaControllerRoute(
"investor",
"investor",
"Investor/{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
What am I doing wrong. Thanks

I think you need add asp-area tag helper:
<a class="btn btn-primary" asp-area="Products" asp-controller="Admin" asp-action="CreateRole">Create Role</a>
OR
#Html.ActionLink("Admin/UserRoles/CreateRole", "CreateRole", "UserRoles",new { area = "Admin" })
Click Here For more information

I found a solution. You should modify the order to make the Areas route first :
endpoints.MapAreaControllerRoute(
"area",
"Admin",
"{area:exists}/{controller=Home}/{action=Index}/{id?}"
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
It worked for me

Related

Route url is including ?=

I'm using the following Razor in my page:
<a asp-action="Logs" asp-route-channel="#channel.Name">
<button class="btn btn-success btn-circle"><i class="fa fa-eye"></i></button>
</a>
channel is a string, not an integer, which is why I don't use id.
And this is how I'm routing it:
endpoints.MapControllerRoute("logs", "Dashboard/Logs/{channel}");
And in my Controller, I'm simply doing this for testing purposes:
public IActionResult Logs(string channel)
{
return Content(channel);
}
However, when the link is generated, I get something like this:
<a href="/Dashboard/Logs?channel=mychannel">
Instead of the expected:
<a href="/Dashboard/Logs/mychannel">
EDIT
Here's what I've tried:
[HttpGet("{channel}")]
public IActionResult Logs(string channel)
{
return Content(channel);
}
Which results in https://localhost:44351/mychannel
I've also tried:
[HttpGet("Dashboard/Logs/{channel}")]
public IActionResult Logs(string channel)
{
return Content(channel);
}
Which works as intended, but why should I have to include the whole path like that?
You are mapping to the default convention based route, which would most likely have {id} as a route parameter. Because it maps to the default and you included {channel} it would add that parameter as a query string instead of part of the URL.
You would need to include a custom route for that action in order to get the desired URL generation.
endpoints.MapControllerRoute(
name: "Logs",
pattern: "Dashboard/Logs/{channel}",
defaults: new { controller = "Dashboard", action = "Logs" });
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
and the necessary route values would need to be included so that it maps to the intended route
<a asp-controller="Dashboard" asp-action="Logs" asp-route-channel="#channel.Name">
<button class="btn btn-success btn-circle"><i class="fa fa-eye"></i></button>
</a>

ASP.NET MVC Razor: how to add a Css style class or ID on the link below

#Html.ActionLink("Some link text", "MyAction", "MyController", protocol: null, hostName: null, fragment: "MyAnchor", routeValues: null, htmlAttributes: null)
Current output:
Some Link Text
I want it to be :
<a class="smoothScroll" href="/#MyAnchor">Some Link Text</a>
If they is a better way to do this in ASP.NET MVC +4 Razor, please assist. Thanks
Pass the following as the htmlAttributes parameter:
new { #class = "smoothScroll" }

Linking to a MVC controller from ASP page

I have inherited a asp project with all new projects being done in MVC. I have a link on an asp page which I would like to route to a MVC action but can't seem to manage this. This is what I have so far which doesn't work.
ASP page:
<div id="mainMenuAnalystics" class="panel pageLink" runat="server">
<div class="header">
<asp:HyperLink NavigateUrl="IDoNotExist.aspx"
Text="Analytics"
runat="server"/><br class="floatClear" />
</div>
</div>
In the routeConfig.cs file I added this:
routes.MapRoute(
name: "Analytics",
url: "DestinyWireless.src/aspx/IDoNotExist.aspx",
defaults:
new
{
controller = "Areas/MVC/Controllers/ReportingController",
action = "Index"
});
So instead of going to IdoNotexist.aspx, I want to redirect to the Index method in Reporting controller which is located at Areas/MVC/Controllers/ReportingController. Anyone know how to achieve this?
Of course it would be great if I could just add a #Url.action on the asp page itself but it seems asp does not support razor.
Folder structure:

redirect to page#about using symfony&twig

I'm using Symfony , I wanna redirect the user to a specific frame in a page
So How can i translate this <a href="index.html#about"/> to twig ? I tried <a href="{{path('pl_index')}}#about"/> but it doesnt work
in twig you can use {{path('_welcome') }} and it will send you to your home index, check your route.yml and you can see what are the paths generated by symfony.
for example this is my config.yml:
//savabundle config.yml
sava_inventario_construccion:
path: /productos/construccion
defaults: { _controller: savaInventarioBundle:Inventario:construccion }
sava_inventario_index:
path: /productos/
defaults: { _controller: savaInventarioBundle:Inventario:index }
if i want to generate www.mypage.com/productos/construccion#about link, this is what my html should look like
<a href="{{path('sava_inventario_construccion') }}#about"/>
you can read more in here
http://symfony.com/doc/current/book/templating.html

Slugs not working in Forms with GET method

This is my routing:
myapp_upgradeAccount:
path: /upgradeAccount
defaults: { _controller: myapp:UpgradeAccount:index }
myapp_checkUsernameForUpgrade:
path: /upgradeAccount/check/{username}
defaults: { _controller: myapp:UpgradeAccount:checkUsername }
methods: [GET]
and this is my form
<form method="get" action="upgradeAccount/check">
<label for="username">Insert your username:</label>
<input name="username" type="text">
<input id="chech-username-for-upgrade" class="green" type="submit" value="Check">
...
But everytime I submit the form I get this error:
No route found for "GET /upgradeAccount/check"
The problem is that when I submit the form, I get the following URL:
http://localhost/app_dev.php/upgradeAccount/check?username=123
when i think I should be getting
http://localhost/app_dev.php/upgradeAccount/check/123
If I trz the latter manually, it works allright. What am I missing?
This is the way HTML forms work.
From w3.org:
get: With the HTTP "get" method, the form data set is appended to the
URI specified by the action attribute (with a question-mark ("?") as
separator) and this new URI is sent to the processing agent.
To do what you want to do keeping the GET method, you have to define your route as:
myapp_checkUsernameForUpgrade:
path: /upgradeAccount/check
defaults: { _controller: myapp:UpgradeAccount:checkUsername }
methods: [GET]
And in your controller, you access the query string parameter with:
if(!is_null($this->getRequest()->get('username'))
{
//Do your stuff
}
EDIT:
If you want your user to be redirected to a url formatted as upgradeAccount/check/{username}, you can either do it with JavaScript (as suggested in #usoban answer) or inside the controller using Redirect:
//path: /upgradeAccount/check
public function check()
{
if(!is_null($this->get('request')->request->get('username')))
return $this->redirect($this->generateUrl('myapp_checkUsernameForUpgrade', array('username' => $this->get('request')->request->get('username'))));
//By default, return the view with your form asking the username
return $this->render('AcmeHelloBundle:Hello:index.html.twig');
}
//path: /upgradeAccount/check/{username}
public function checkUsername($username)
{
//Do some fun stuff with $username coming from the url
}
Then in your view, the form signatures becomes:
<form method="post" action="upgradeAccount/check">
<label for="username">Insert your username:</label>
<input name="username" type="text">
<!-- additionnal fields -->
<input id="chech-username-for-upgrade" class="green" type="submit" value="Check">
</form>
And your route:
myapp_check:
path: /upgradeAccount/check
defaults: { _controller: myapp:UpgradeAccount:check }
methods: [POST]
myapp_checkUsernameForUpgrade:
path: /upgradeAccount/check/{username}
defaults: { _controller: myapp:UpgradeAccount:checkUsername }
methods: [GET]
You need to generate routes that take parameters.
so you would need to do
<form method="get" action="{{path('your_route_name', {username:'usernmae'})">
However this obviously won't quite work for you since you do not know the username until they enter it. You could look into the FOSJsRoutingBundle but this will require javascript. Not the best solution, but it will work. Otherwise you will need to remove the username parameter
As #cheesemacfly mentioned, that is how forms work :)
To get it woking myself, I used some javascript. Let's assume you're using jQuery:
<form method="get" action="upgradeAccount/check/___username___" id="my_form">
...
<input name="username" type="text" id="username">
$(document).ready(function(){
$('#my_form').submit(function(evt){
var username = $('#username').val(),
action = $(this).attr('action').replace(/___username___/g, username);
if (/* empty or whatever 'validation' */) {
evt.preventDefault(); // stop the form from submitting
return false;
}
$(this).attr('action', action);
return true;
});
});

Resources