c# mvc: RedirectToAction() and browser navigation buttons - c#

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.

Related

ASP.Net MVC Preventing direct access to action out of RedirectToAction method

My site aims to upload files to sharepoint folders. Users are coming from another system by using a button referencing my site and contains userId and other parameters. When a call comes to my site shown below
http://myapplication/Upload/ToFolder?entityName=new_policy&entityGuid=4451E282-80B0-E611-80E8-C4346BACFC18&systemUserId=1ADEC6E1-008C-430D-A163-D7BA7AD75689
I authenticate user with userId and redirect user to http://myapplication/Policy using RedirectToAction method and setting some parameters to static properties. Because of static properties I use my params but I dont want to do this way. I want to detect that when users types directly http://myapplication/Policy link and throw an error like "You should come from this site only via link on other system."
How can I detect this behaviour of users ?
You could set a tempdata value in the first action...
TempData["isRedirect"] = true;
which gets read by the second action
if(TempData["isRedirect"] == null)
{
//Deny access
}
//Set temp data again so that user can refresh
TempData["isRedirect"] = true;

How can I pass two parameters from ActionLink to ActionResult

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.

MVC Redirect to another page

I have a controller which processes an uploaded file.
In that controller, I return the user to a SharePoint list depending on the successful parsing of that file. I am able to enter a direct URL, but I am opening this page in a form so I need to change the window.top.location instead of just window.location. I tried doing this a few ways such as returning a JavaScript result, but I received some browser warning messages I'd like to avoid.
I ended up making a partial razor view which grabs a parameter from the query string in order to determine which list it should go to. The function works fine, but the page is seemingly inactive when I return it using:
return Redirect("~/Parsing/ParsingRedirector?List=MasterDealer");
My page exists in the folder, but I get an error stating "The resource cannot be found. "
Any reason why that's happening? I admittedly don't have a full understanding of MVC or even close to it at this point.
Try this:
return RedirectToAction("ParsingRedirector", "Parsing", new { List = "MasterDealer"});
This may be of help:
http://www.dotnet-tricks.com/Tutorial/mvc/4XDc110313-return-View()-vs-return-RedirectToAction()-vs-return-Redirect()-vs-return-RedirectToRoute().html
Keep in mind that, per that article, in the case of Redirect "you have to specify the full URL to redirect."

How to persist keeping the info in the Session["Stuff"]?

When the user makes selection and clicks a button, I call to:
public ActionResult Storage(String data)
{
Session["Stuff"] = data;
return null;
}
Then, I redirect them to another page where the data is accessed by
#Session["Stuff"]
This far, I'm happy. What I do next is that upon a click on a button on the new page, I perform a call to:
public ActionResult Pdfy()
{
Client client = new Client();
byte[] pdf = client.GetPdf("http://localhost:1234/Controller/SecondPage");
client.Close();
return File(pdf, "application/pdf", "File.pdf");
}
Please note that the PDFization itself works perfectly well. The problem is that when I access the second page a second time (it's beeing seen by the user and looks great both in original and on reload), it turns out that Session["Stuff"] suddenly is null!
Have I started a new session by the recall?
How do I persistently retain data stored in Session["Stuff"] before?
If you're simply storing string data (as would be indicated by your method signature) in an MVC application, don't.
It's far easier to pass the data as a query parameter to each method that needs it. It's far easier to manage and doesn't rely on Session sticky-ness.
To generate the appropriate links, you can pass data to your views and use Html.ActionLink to generate your links with the appropriate parameter data.
Here's several reasons why the session variable could return null:
null is passed into Storage
Some other code sets Session["Stuff"] to null
The session times out
Something calls Session.Clear() (or Session.Abandon())
The underlying AppPool is restarted on the server
Your web server is farmed and session state is not distributed properly
The first two can be discovered by debugging.

Keeping list of attached files of a page with TempData without any conflict with another instanse of the page

Hello Friends...
I have a mvc project and a form with a attachment box (such as yahoo mail compose)
for example "create_request.cshtml"
I want:
each user fill the fields and upload his/her files (i post each file by Ajax when the user select any one) and after submit the form, if the page has error (checked server side), user see the uploaded files in the response page (response form with highlighted errors)...
I implemented the above scenario very nice:
(Ajax+ Tempdata+ save the files server side befor submit + Thumbs of uploaded files befor submit the form)
in my controller:
public void KeepTempData(string name, string value)
{
TempData[name] = value;
}
in my view i send each file name to the server after i upload it by another ajax codes:
ajaxPostData(KeepTempData, "Attachments", $('#Attachments').val());
But i have a problem:
Because i used TempData for keeping list of uploaded filenames, if the user attach a file in the current page then opens a new Tab in her/his browser and goes to the "create_request" page address. He/She see an empty form with a attached file...
My Solution:
Maybe I can solve this problem with a unique key for each page (each form) and keeping it in a session variable and a hidden field for each page request>> using: "Anti Forgery Token with a Salt" or "DateTime.Now"
I found This post on the web. its problem is like as my problem. and its solution is like as my solution.
What is appropriate solutions in MVC for this problem???
What is your recommendation for using TempData's (or Session's) without any conflict when user have different requests of a pages in some tabs of a browser (like firfox)???
TempData has very short lifespan. You should use Session instead of TempData.
Infact session object is the backing storage behind TempData. But the data stored in TempData is available to the current request and Subsequent request.
I Solved this problem by:
Get a key from querystring
If the key is empty
I generate a new and unique key in the action of controller
Redirect the page to a new url with the key (as a querystring key-value)
Else
Adding the key to the ViewBag (for set a hidden field in view)
Save the key in a session variable.
.
public virtual ActionResult Create(string attkey)
{
if (string.IsNullOrEmpty(attkey))
{
attkey = generatNewNameForSession('key'); // for examle: kye_jhtyujbvkjadsgfvn
Response.Redirect("myControle/Create, attkey="+attkey), true);
}
ViewBag.AttachmentsKey = attkey;
if (Session[attkey] == null)
KeepData(attkey, "");
.
.
.
Now each instance of my page has a Identification and now i can decide shown or not shown the previously attached files.

Categories