MVC.net session gets mixed between users - asp.net-mvc

I am storing user objects in session, pulling them out in the controllers, and sometimes write some data into them. but when to users post at the same time, the sessions get mixed fro some reason.
Does anyone have any idea how that is possible ?
typical post:
[HttpPost]
public ActionResult Index(QuestionModel model, FormCollection collection)
{
var person = ((Person)Session["Person"]);
if (!ModelState.IsValid)
{
ModelState.Clear();
ModelState.AddModelError("", Global.Global.error);
return View(new QuestionModel(person.page, (CultureInfo)Session["culture"]));
}
person.page = model.Page;
while (person.Answers.Count > model.Page - 1)
{
person.Answers.RemoveAt(person.Answers.Count - 1);
}
var answer = new Answer() { answer = model.ChosenAnswer, Question = "Q" + person.page };
person.Answers.Add(answer);
if (!CheckForNextPage(person.page)) { person.hasFinishedQuestions = true; return RedirectToRoute("Result"); }
person.page++;
return View(new QuestionModel(person.page, (CultureInfo)Session["culture"]));
}
I echo the session id on every page, and when a couple of users are using the website they get each others session + sessionid ...
#update: 3 experienced developers have been looking for the problem for 2 days, still no solution. already removed about 95% off the code, still same issue. server posts back responses from another session

This is not possible.
So this is my guess:
You are testing this wrongly, you are using different tabs from the same browser.
Some people don't know that this doesn't create a different session.
Try testing this on 2 different browsers (i.e. firefox and chrome) as they will not share the session (as the session id is normally stored in a cookie).
Please report back if this was the case.

We "solved" it. We didn't actually solve it, but we copied all the sources to a new project, recompiled, and everything worked. Untill this day, we still don't know why, and how that error happened ...

Related

How to pass parameter to another page by TempData in ASP.NET MVC framwork?

I want to Redirect from a page to another page without showing parameter on the url.
some articles say that "TempData is stored in the session and will be automatically removed at the end of the first request." recommand me to use TempData to transfer parameter, but it's not working so fine for me.
As you can see, this is a totally new testing project without any other noise, after TempData["test"] = "testString" executed, when I look into TempData, it has keys count and values count equal to 1,
but after RedirectToAction("About") has been executed, TempData["test"] has only both 0 count of keys and values.
public IActionResult Index()
{
TempData["test"] = "testString";
return RedirectToAction("About");
//return View("About", test); // this will show parameter on the url
}
public IActionResult About()
{
string test = (TempData["test"] == null) ? "isNull" : TempData["test"].ToString();
return View();
}
I've tried .Netframwork 4.5 and .Netframwork 4.8.
Actually, It works in Edge, and neither Chrome, Firefox or Opera does on my computer. But it works on my friend's computer in Chrome, we are confusing with these results.
You don't need to check for null here (on very first read from tempData framework mark this for deletion). So in short in your about action use follow
object testValue = TempData["test"];
if you want to check whether temp data is null or not you can use TempData["test"].ToString()!=null and I think you cannot check Tempdata["test"] is null or not.
string test = TempData["test"] as string;
if(String.IsNullOrEmpty(test))
test = "isNull";

Improper Logout

I know this question might sound silly, but this problem is really making a big trouble.
I have a web application made on ASP.NET MVC 4. To enter that application one has to register, after that when the user logs out. It shows the proper message of logging out. But, if the user clicks the back button of the browser, It enters back to the user's profile.(It never happens every time, it happens very rarely).
Any type of suggestion is highly anticipated.
If i am not clear enough.Feel free to ask any question regarding this matter.
Please help me.
The credentials gets stored in cookie. I want to store that in cookie, but i want to remove that while logging out.
LogOut Code:
public ActionResult Logout()
{
Session.Clear();
if (HttpContext.Request.Cookies["xxxx"] != null)
{
var c = HttpContext.Request.Cookies["xxxx"];
c.Expires = DateTime.Now.AddDays(-10);
HttpContext.Response.Cookies.Add(c);
}
if (HttpContext.Request.Cookies["xxxx"] != null)
{
var c = HttpContext.Request.Cookies["xxxx"];
c.Expires = DateTime.Now.AddDays(-10);
HttpContext.Response.Cookies.Add(c);
}
HttpContext.Session["var1"] = null;
HttpContext.Session["var2"] = null;
HttpContext.Session["var3"] = null;
}

Multi Post for Action with return File in ASP.NET MVC

Assume this code in One of my Actions
[HttpPost]
public ActionResult Generate (Params){
....
InsertOneRawToDB();
return RedirectToAction("Index", new { info = info });
}
So every thing is OK yet but when I change return to:
InsertOneRawToDB();
byte[] myfile = GenerateAZipFile();
return File( myfile , "application/zip" , "MyFileName");
In this case I see a weird behavior: before return, One raw inserted to DB, and after return another raw inserted, it seems the InsertOneRawToDB called again.
Does any one know about this? what happening here?
PS: I use Visual Studio 2012 RTM + ASP.NET MVC4
PS: OK I Use IDM (Internet Download Manager) to download zip file and that cause MultiPost on this Action So How can I handle this?
Based on your conclusion that the problem is related to using a download manager... That's what download mangers do. They create multiple connections to the file.
One thing you could do is store a session variable that says "Already started downloading", and then only insert the record the first time.
however if the user legitimately downloaded the file multiple times then you would only get one record.
Another option would be to examine the Http headers and look for the "Range" header, which is what is used to download a file in multiple pieces (or resume a file). You would then have to take the Range parameters and only return the portion of the file requested.
Here's an example of how to do a Ranged download: http://tpeczek.com/2011/10/range-requests-in-aspnet-mvc.html
I'm actually quite surprised that this hasn't come up before... I guess most people don't do database actions in a download action or notice it.
You can redirect to new action and in this new action return file.
[HttpPost]
public ActionResult Generate (Params){
....
InsertOneRawToDB();
return RedirectToAction("GetFile"};
}
[HttpGet]
public ActionResult GetFile
{
byte[] myfile = GenerateAZipFile();
return File(myfile, "application/zip", "filename.ext");
}

HOW? Controller return nothing/current view

SHORT:
How do I make a controller return the current view or just simply do nothing?
LONG:
I have a partial view where i've created an imageslider.
It contains a link which sends a request to a controller to get the next image (using ajax).
The controller fetches the next image, stores it in ViewData and sends back a partial view (the one above).
Now, what I do today is that when the controller reaches the last image it re-return the very same image (by refetching it), but still creates a new view, that is, the client/browser re-parses the "same" data.
This seems somewhat non-optimal.
What I'd like to do is that when controller reaches the last image it should simply do nothing.
If I return null then the view is updated with empty contents.
I want the view/client/browser to retain whatever it has and the controller to simply do nothing.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult GetNextImage(...)
{
if(Request.IsAjaxRequest())
{
if(CURRENT_IMAGE != LAST_IMAGE)
{
Image image = GetNextImage(...);
var partialViewResult = new PartialViewResult();
partialViewResult.ViewName = "ImageSlide";
partialViewResult.ViewData.Model = image;
return partialViewResult;
}
else
{
// DO NOTHING, HOW?
}
}
return RedirectToAction("Error", "Home");
}
You can return an EmptyResult if you want it to do nothing...
return new EmptyResult();
If you're using the AjaxHelper you can avoid the update by supplying an unsuccessful status code (e.g. 404 or whatever is most appropriate), that'll stop it replacing your div as the javascript in MicrosoftMvcAjax.js explicitly checks for a successful response before updating any elements:-
this.ControllerContext.HttpContext.Response.StatusCode = 404;
return new EmptyResult();
Ultimately the best way to avoid it is to design the partial view so it avoids the problem in the first place (like you mention yourself).
I ran into this problem today. I wanted to find a solution for how to deal with double-clicks on the client side trying to reenter the controller action on the server side while it was still processing. If a user entered that action, I wanted it to just ignore the request and do nothing on the browser side.
Solution looks like this:
public async Task<ActionResult> MyAction()
{
if(!CanEnterAction(nameof(MyAction))) return new HttpStatusCodeResult(204);
try
{
// Do long running stuff
return ValidActionResult();
}
finally
{
ExitedAction(nameof(MyAction));
}
}
Returning a status code of 204 basically does nothing to the page displayed in the browser. The actual result eventually makes it back to the browser when the action is complete.
This question is old, but I wasn't able to find an answer anywhere on StackOverflow. I figured it had to be possible since a FileResult doesn't really affect the current page, either, other than saving a file.
I would use
return new HttpStatusCodeResult(204);
this way you would stay on the same page and there is no post back.
Here is the defination
The HTTP 204 No Content success status response code indicates that the request has succeeded, but that the client doesn't need to go away from its current page
Assuming that you are using MicrosoftMvcAjax, you could send back a JavascriptResult that alerts the user that they have reached the end of the slider. If the response is javascript rather than content, the MicrosoftMvcAjax handler executes it instead of replacing the DOM contents.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult GetNextImage(...)
{
if(Request.IsAjaxRequest())
{
if(CURRENT_IMAGE != LAST_IMAGE)
{
Image image = GetNextImage(...);
var partialViewResult = new PartialViewResult();
partialViewResult.ViewName = "ImageSlide";
partialViewResult.ViewData.Model = image;
return partialViewResult;
}
else
{
return JavaScript( "alert('No more images');" );
}
}
return RedirectToAction("Error", "Home");
}
Of course, you'd probably want to be more creative and use the jQuery dialog plugin or something rather than an alert.
Ok, I've got it.
Not a solution to my question but still solves the problem.
I'll simply not show the "Next" link when the view shows the last image.
Can't believe I didn't think of it earlier...
Thanks for your efforts guys

How to clear/expire browser cache on log off?

In my ASP.net MVC application, I've got several views that I'd like to set to save in the browser's cache. I've got the methods built to do it, but here's my issue.
The menu in my site is different between logged in and logged off visitors. If the logged in page is cached, then even when the user logs off the menu remains in the logged in mode. It's actually not, but on that visitor's browser it is.
How can I go about clearing/expiring that cache so the visitor's browser updates when I need it to, yet still be able to make use of browser cache?
Thanks in advance!
For HTML pages it's difficult. I turned off client caching for that same reason, and tried to make the server caching as efficient as possible. I now use OutputCache with VaryByCustom set to the login status.
We ran some load tests on that system and the only bottleneck is the bandwidth that this generates.
And on a side note: I used donut-caching for the login status. But I was not able to get it to work with dynamic compression (to reduce the bandwidth bottleneck mentioned above)
See also this question
You can do it with an AutoRefresh attribute on your action method. Here are some examples:
[AutoRefresh(ControllerName = "Home", ActionName = "About", DurationInSeconds = 10)]
public ActionResult Index1()
{
}
AutoRefresh(ActionName = "About", DurationInSeconds = 15)]
public ActionResult Index2()
{
}
[AutoRefresh(RouteName = "ByFavoriteRoute", DurationInSeconds = 30)]
public ActionResult Index3()
{
}
[AutoRefresh(DurationInSeconds = 45)]
public ActionResult Index4()
{
}

Resources