How can I pass two parameters from ActionLink to ActionResult - c#

I'm implementing a website using asp.net MVC. I'm trying assign role to user by clicking into the role. I've tried several ways, unfortunately, I failed.
Controller method
[HttpPost,ActionName("AssignUserToRole")]
[ValidateAntiForgeryToken]
[CustomAuthorize(Roles ="SudoAdmin")]
public ActionResult AssignUserToRole(long userId, long roleId)
{
new BusinessUser().AddRoleToUser(userId, roleId);
return RedirectToAction("Index");
}
view
#Html.ActionLink(#r.RoleName, "AssignUserToRole", "Users", new { userId = Model.UserId, roleId = r.RoleId })
first I tried Jquery Ajax, but it failed, even though I think it was not a very great idea. However, I still would like to do it with "Ajax"I mean without refreshing the page.
I hope my question is good enough
thanks for all of you

First, the action is set to respond only to POST. That means unless you request it via POST, you'll get a 404, since there's no action that can respond to any other request method.
As a link, it will always make the request via GET. If you employ JavaScript, you can bind to the click event and send the request via POST using AJAX, but again, you have to send it as POST. If you use something like $.get or $.ajax with the method as GET, it won't work.
Ideally, if you intend to hit the action via POST, then you should employ a form element in your view. Using CSS, you can style the submit button to look like a link, if that's what you want, but the underlying structure should be a form.

Related

Updating the displayed URL in the browser using .NET Core

So, I have a certain webpage (view) that I have created. I have a requirement where I need to update the displayed URL in the browser's to show a different path to this page and update the querystring.
Update: I don't want to actually redirect the page, this is merely a cosmetic update. To make the URL appear differently that what it was. It's a requirement our customer support team wanted. :p
Ex.
https://www.myserver.com/error/
I need to update the path in the URL depending on the type of error, like so:
https://www.myserver.com/#/order-completed?var=someguid
My error page handles various situations you see.
I know this is easily done in JS, but I want to be able to do this from my error page Controller.
Could someone lend a hand? I'd super appreciate it!
I think "update the path" means you simply have to redirect the browser to that url. If you are using ASP.NET MVC, you can use the Redirect controller method like this:
return Redirect("https://www.myserver.com/#/order-completed?var=someguid");
So, I went the way of JS afterall. I call it from window.onload in the View.
var fromController = '#ViewData["NewURL"]';
histoy.pushState(null, '', fromController);
In the Controller, in the Index() action
ViewData["NewURL"] = #"/myURL/myview?user=2342434";
return View();

RedirectToAction appends route to URL instead of directing to action in other controller

I have a simple RedirectToAction at the end of a controller method in the controller "AccountController". I want to redirect now to a method called loads in the Home controller. Code:
return RedirectToAction("loads", "Home", new { unique_id = new_questionnaire.Unique_ID, purpose = "resume" });
Instead of going to http://localhost:40829/Home/loads/..., it goes to http://localhost:40829/Home/Index?ReturnUrl=%2fHome%2floads%3funique_id%3d49557%26purpose%3dresume&unique_id=49557&purpose=resume. What am I doing wrong here? How can I redirect to another controller method while passing route values as well?
The problem was that I use Forms Authentication and the user was not authenticated when trying to access the URL. This caused the website to redirect the user to the login page.
When ReturnURL shows up in the url, this might be the problem. Hope this can help people in the future.
In my case, adding a Cookie and a Forms Authentication Ticket solved the problem. I already had a function ready for this, I just needed to call it.

c# mvc: RedirectToAction() and browser navigation buttons

In my application, i am storing an object into session which is passed to a web service to return data to display in a table. If the session exists, then it will not ask the user to input fresh data. However, if a user selects a link called "New List", then the session data will be cleared and the user prompted to enter new data.
In my code, i have an anchor defined like so:
New List
Which will trigger this Controller Action:
public ActionResult NewList()
{
Session["new_list"] = "y";
return RedirectToAction("List");
}
And then continue to execute this action:
public ActionResult List()
{
if ((string)Session["new_list"] == "y")
{
//clear session variables, load fresh data from API
}else{
//display blank table. Ask user to input data to retrieve a list
}
....
}
Now, the issue i have is when a user navigates away from the list page, and then navigates back with the browser's back button, it is still calling newlist. In the history of the browser, instead of storing List it is storing newlist which is causing the session variable to clear. What can i do to stop this from happening or is there a different mechanism to use in c# mvc that can help me achieve the desired effect.
Your main problem here is that the NewList action uses GET when it should really be a POST.
A GET request is never supposed to alter the state of a resource, but simply return the current state of the resource; while a POST request allows for the altering of a resource.
Because you allow the NewList action to be called with a GET request, the user's browser assumes (quite rightly on its part) that nothing bad/undesired will happen if it simply repeats the request in the future, e.g. when a user uses the back button.
If instead a POST request is issued, a user browser will never re-issue the request without the user confirming they actually intended to re-issue it.
The solution to your problem then is modify this to the standard PRG pattern: POST/Redirect/GET; that is, send a POST request to perform the state change, redirect the user browser to another page, and GET the result page. In this scheme, pressing the back-button would effectively "skip" over the state change action and go the previous page the user was on.
To accomplish this in MVC:
[HttpPost]
public ActionResult NewList()
{
//clear session variables, load fresh data from API
return RedirectToAction("List");
}
public ActionResult List()
{
// whatever needs to happen to display the state
}
This does mean that you can't provide the "New List" action directly as a hyperlink in the page, as these will always issue GET requests. You will need to use a minimal form like so: <form method="post" action="#Url.Action("NewList", "Alert")"><button type="submit">New List</button></form>. You can style the button to look like a normal hyperlink as desired.
The reason it storing NewList is because you are redirecting to "Alert/NewList", and its the string in your URL for making hit to "NewList" Action, So whenever you are try back button the browser gets this "Alert/NewList" URL, hence its making hit to action "NewList".
But now, I am not getting why the session gets clear. because you are initializing the session in "NewList" itself. Still i suggest you to use local-storage to assign values with session.

Hide parameters from #Url.Action

I have this code
<a href="#Url.Action(" Edicao ", "EdicaoListaVerificacao ", new { idFormulario = m.Id })" title="Editar" class="glyphicon glyphicon-pencil" aria-hidden="true" />
Where 'Edit' is my action and 'FunctionEdit' is my Controller. My action needs a parameter and I passed it building a 'instance'. How the property needs. The problem is that the URL can be altered and the user can access things that they can't.
You can never hide your URLs - nor should you. You should verify, instead, inside the Edicao action method that the user has permission to view the Formulario with the specified Id.
In all web applications, you have to assume that the URLs users try to retrieve can be absolutely anything - and that some users will attempt to edit URLs to get at hidden content. ASP.NET has built-in authentication and authorization mechanisms that you should use.
If you're just looking for a simple way to make a URL that's impossible to guess, without forcing users to log on, you have to use something more complicated than a numeric ID, like a GUID.
And if at any point you are tempted by roll-your-own solutions such as URL referrer checking or verifying cookies, remember that easier-to-use solutions are most likely built into ASP.NET already.
That's it! Thank you, guys. I found a way to implement a check in my action. With Request.UrlReferrer.
public ActionResult Edicao(int idFormulario)
{
Uri url = Request.UrlReferrer;
if (url != null)
{
DO ALL THINGS YOU HAVE TO
}
else
{
RETURN TO INDEX
}
}
The Request.UrlReferrer returns me the URL if it comes from my request. If not returns null. Than I just build an if block ;). Thank you guys!

How do I redirect to my parent action in MVC site?

I have been looking at several pages on here already such as:
How do I redirect to the previous action in ASP.NET MVC?
How can I redirect my action to the root of the web site?
Along with several hours of searching google.
No where seems to have an answer to my problem and I am sure it should be possible within MVC somehow hence the reason I am now here to ask the question.
So the problem I am facing is that I want to allow the user to change the language of the page by choosing a new language from a drop down menu which is in its own partial view hence the problem, I need to redirect to the parent action and not the child. This all works fine as long as i send the user back to the root of the site. Using the following code:
[HttpPost]
public ActionResult RegionSelect(RegionSelectionModel model)
{
var currentUser = Session.GetCurrentUser();
var currentDbUser = Session.GetUserEntity(_dataAccessLayer);
if (!ModelState.IsValid)
{
model.AvailableRegions = CacheHelpers.GetAvailableRegions<RegionView>(_dataAccessLayer, _cache).ToList();
return PartialView("_RegionSelect", model);
}
var selectedRegion = UsersControllerHelpers.SetSelectedRegion(model, _dataAccessLayer, _cache, _website.Client);
var uri = model.OriginalUrl;
var routeInfo = new RouteHelpers(uri, HttpContext.Request.ApplicationPath);
// Route Data
var routeData = routeInfo.RouteData;
routeData.Values.Remove("language");
var defaultClientLanguageCode = _website.Client.LanguagesSupported.FirstOrDefault().Code;
if (currentDbUser.Language.CountryCode != selectedRegion.PrimaryLanguage.CountryCode)
{
//TODO: Decide where to redirect or whether to refresh the whole page...
if ((defaultClientLanguageCode == selectedRegion.PrimaryLanguage.CountryCode) || (model.SelectedRegionId == 0))
{
UsersControllerHelpers.UpdateUsersRegions(currentUser, selectedRegion, _website.Client, _cache, _dataAccessLayer,
Session);
return RedirectToRoute(routeData.Values);
}
routeData.Values.Add("language",selectedRegion.PrimaryLanguage.CountryCode);
return RedirectToRoute(routeData.Values);
}
return RedirectToRoute(routeData.Values);
}
Two of my return statements return to the root page and one returns to the root but with a language so it would be "http://mysite/en-En/" but what if the user is on a page other than the root site? I want to somehow redirect them back to this same action but with the correct language string at the start.
How can i do this?
I have thought of several "hacky" ways of doing this, such as splitting the URL and swapping the language codes over. But ideally I am looking to do this as clean as possible.
Can anyone give me any idea's? Or is it just not possible?
It seems like it should be really simple but apparently not.
Thanks in advance for any help that you can provide.
EDITED
Added new code that is using code from suggested answer below.
I am now having two new problems.
I am getting this error message, if there are any things in the URL such as ?page=1:
A potentially dangerous Request.Path value was detected from the client (?)
If i try and remove the language completely using .Remove(). It removes it fine but when i try and redirect to the page in the default language it adds language?=language to the end of the URI.
Any ideas how i can resolve these two issues?
This option is definitely my answer. Leave me a comment if you need me to drop some code, and I can do that, but the examples on the linked website should get you started.
Use this method to change Request.UrlReferrer into Route data, then merge your language into that, then do a RedirectToRoute with the modified Route data.
Just use RouteData.Values.Add, RouteData.Values.Remove, and RouteData.values["whatever"], then pass that modified RouteData.Values object to RedirectToRoute()

Categories