Difference between HttpResponse: SetCookie, AppendCookie, Cookies.Add - c#

there are some different ways to create multi value cookies in ASP.NET:
var cookie = new HttpCookie("MyCookie");
cookie["Information 1"] = "value 1";
cookie["Information 2"] = "value 2";
// first way
Response.Cookies.Add(cookie);
// second way
Response.AppendCookie(cookie);
// third way
Response.SetCookie(cookie);
When should I use which way? I've read that SetCookie method updates the cookie, if it already exits. Doesn't the other ways update the existing cookie as well?
And is the following code best practice for writing single value cookies?
Response.Cookies["MyCookie"].Value = "value";

If I remember correctly both
Response.Cookies.Add(..)
and
Response.AppendCookie(..)
will allow multiple cookies of the same name to be appended to the response.
On the other hand
Response.SetCookie(..)
and
Response.Cookies[key].Value = value;
will always overwrite previous cookies of the same name.

When should I use which way?
It's depends on what Cookie operation you want to do.
Note that Add and AppendCookie are doing the same functionality except the fact that with AppendCookie you're not referencing the Cookies property of the Response class and it's doing it for you.
Response.Cookies.Add - Adds the specified cookie to the cookie
collection.
Response.AppendCookie - Adds an HTTP cookie to the
intrinsic cookie collection
Response.SetCookie - Updates an existing cookie in the cookie
collection.
Exceptions will not be thrown when duplicates cookies are added or when attempting to update not-exist cookie.
The main exception of these methods is: HttpException (A cookie is appended after the HTTP headers have been sent.)
The Add method allows duplicate cookies in the cookie collection. Use the Set method to ensure the uniqueness of cookies in the cookie collection.
Thanks for MSDN!

To piggyback on tne's comment in Wiktor's reply, AppendCookie and SetCookie shouldn't be used - they're for internal use by the .NET framework. They shouldn't be public but they are, my guess would be as a hack for the IIS pipeline somewhere else.
So you should do your cookie setting this way (or write an extension method for setting multiple cookies):
string cookieName = "SomeCookie";
string cookieValue = "2017";
if (Response.Cookies[cookieName] == null)
{
Response.Cookies.Add(new HttpCookie(cookieName, cookieValue));
}
else
{
Response.Cookies[cookieName].Value = cookieValue;
}

Related

Access cookie before View loaded in MVC5?

Let's say I have a cookie with value "OLD", then I update the cookie with following code :
var lang = new HttpCookie("lang");
lang.Value = "NEW";
lang.Expires = DateTime.UtcNow.AddDays(2);
HttpContext.Current.Response.SetCookie(lang); //set updated cookie value
var x = HttpContext.Current.Request.Cookies("lang");
x will still have "OLD" as value because it's not being sent to the client. Is it possible to get the updated value without it being sent to client first?
The Problem
you are setting the cookie in HttpContext.Current.Response and trying to find it in HttpContext.Current.Request even before the next request has come to server.
It is not going to work.
My Advice
For this case, use of cookie is incorrect. You have other options better fit for purpose, like -
ViewData
ViewBag
TempData
Session
ViewModel
The Answer
But if you still want to use cookie this way, search the cookie in HttpContext.Current.Response. I am sure you will get it.
Like this:
var cookieValue = HttpContext.Current.Response.Cookies["OLD"].Value
If you don't want to send value to client side and only want to use for reference you can use TempData for your purpose. Which might help.
I think, you should look for it in Response, not in Request, because request - it's that came from client.

Reading a cookie that has just been written causes the cookie to be blanked

Okay so this one has me stumped. I have written a function that reads the value of a cookie. The logic is
check Response.Cookies in case it has just been written
otherwise read from Request.Cookies to get the previous value
If the cookie has just been written then all is good, and I get the value. However if the cookie has not been written on this visit - it appears to blank the value of the already store cookie.
What?
Here is the code
Note the write happens in a controller
public static void PersistCookie(string cookieName, string cookieValue, bool persistent)
{
var cookie = new HttpCookie(cookieName, cookieValue)
{
Path = "/",
HttpOnly = true,
};
if (persistent)
cookie.Expires = DateTime.Now.AddMonths(6);
HttpContext.Current.Response.SetCookie(cookie);
}
Note the read happens ina partial view
public static string ReadCookieValue(string cookieName, bool checkResponseFirst)
{
if (checkResponseFirst && HttpContext.Current.Response.Cookies[cookieName] != null &&
HttpContext.Current.Response.Cookies[cookieName].Value.HasValue())
return HttpContext.Current.Response.Cookies[cookieName].Value;
return HttpContext.Current.Request.Cookies[cookieName] != null ? HttpContext.Current.Request.Cookies[cookieName].Value : "";
}
It almost seems that just by checking if a cookie has a value, it messes things up.
Thoughts?
Okay so after much more searching on the web, a good work colleague cam up with the following
it looks like I have come across a curiosity in .NET.
Check out this article
http://www.codeproject.com/Articles/3106/On-The-Care-and-Handling-of-Cookies
If you try to access a cookie that doesn't exist in the Response.Cookies collection, it will be created with an empty string in the Value and an Expires date of 01-Jan-0001 00:00. Strangely, it also creates a matching cookie in the Request.Cookies collection if one doesn't already exist.
So if you look at a cookie in the Response then you are indirectly overwriting the cookie on the client machine with an empty cookie, due to expire when the browser closes
So my problem is solved (or should that be unsolvable). As it turns out I have a workaround using the ViewBag but I am glad I was not going crazy!
Thanks for you help
I am not sure you can set cookies in partial views. When setting the cookie with Response.SetCookie, the information is returned to the browser in the Set-Cookie HTTPHeader field. I don't think partial views can set this value, try inspecting your applications response with Fiddler2, after calling Response.SetCookie.
I usually set my cookies with plain Javascript.

How do I manually delete a cookie in asp.net MVC 4

I need to delete authentication cookie manually (Instead of using FormsAuthentication.SignOut whcih for some reasons does not work). I tried
System.Web.HttpContext.Request.Cookies.Remove(cookieName); // for example .ASPXAUTH
System.Web.HttpContext.Response.Cookies.Remove(cookieName); // for example .ASPXAUTH
FormsAuthentication.SignOut(); // I don't know why this one does not work
Neither of those command work. In fact Response cookies are empty and request cookie contains the cookie I want to delete when the following commands are executed it no longer contains the cookie I deleted but in browser the cookie still exists and I am able to do things that authorized users can even after signing out.
Try:
if (Request.Cookies["MyCookie"] != null)
{
var c = new HttpCookie("MyCookie")
{
Expires = DateTime.Now.AddDays(-1)
};
Response.Cookies.Add(c);
}
More information on MSDN.
c.Expires = DateTime.Now.AddDays(-1);
This does not clear cookies instantly.
Use this: c.Expires = DateTime.Now.AddSeconds(1);
This will clear cookies instantly.

Updating the value of a cookie not working

I need to get the value of a cookie and update it. I must be doing something wrong because my cookie does not get updated. This is my code:
if (HttpContext.Current.Request.Cookies.AllKeys.Contains(EconnectConstants.FILE_SHARE_DOCUMENTS))
{
var existingCookie = HttpContext.Current.Request.Cookies[EconnectConstants.FILE_SHARE_DOCUMENTS];
existingCookie.Value = encriptedInput;
existingCookie.Expires = DateTime.Now.AddMonths(1);
HttpContext.Current.Response.Cookies.Set(existingCookie);
}
else
{
var cookie = new HttpCookie(EconnectConstants.FILE_SHARE_DOCUMENTS, encriptedInput);
cookie.Expires = DateTime.Now.AddMonths(1);
cookie.Value = encriptedInput;
HttpContext.Current.Response.Cookies.Add(cookie);
}
Can anyone please tell me what I am doing wrong?
This question is very old, but I faced this issue a time ago. As #argaz explain, since you are updating a value in the Response, you cannot get it from another object (the Request). Values are transferred from Request to Response in the next postback.
So, if your cookie stores data only valid for the current session AND
you cannot wait to a postback happens, then instead implement a fake (as reading cookie values from same just updated Response according to special condition or force a postback to same page), consider the use Session object, which is not dependent of postbacks.
This seems suspicious:
HttpContext.Current.Request.Cookies.Set(existingCookie);
You are changing a property of the request object, it should not affect the response (which affects what is stored at the user).
You can probably remove the if and do:
HttpContext.Current.Request.Cookies[EconnectConstants.FILE_SHARE_DOCUMENTS].Value = encriptedInput;
HttpContext.Current.Request.Cookies[EconnectConstants.FILE_SHARE_DOCUMENTS].Expires = DateTime.Now.AddMonths(1);

How do I use the cookie container with RestSharp and ASP.NET sessions?

I'd like to be able to call an authentication action on a controller and if it succeeds, store the authenticated user details in the session.
However, I'm not sure how to keep the requests inside the session as I'm using RestSharp as a detached client. I need to somehow get a key back from the server on successful authorisation and then for each future call, check the key with that stored in the session.
How do I ensure the RestClient in RestSharp sends all future requests with the cookie set correctly so inside service calls, the session variable can be retrieved correctly?
I've been looking at the cookie container with HttpFactory but there doesn't seem to be any documentation on this anywhere.
If someone is having a similar problem, please note that the above is not quite required for a simple "store my cookies after each request" problem.
Jaffas approach above works, but you can simply attach a CookieStore to your RestClient and have the cookies be stored automatically.
I know this is not a solution for everyone, since you might want to store dedicated cookies only. On the other hand it makes your life easier for testing a REST client!
(I used Jaffas variables for ease):
CookieContainer _cookieJar = new CookieContainer();
var client = new RestClient("http://<test-server>/letteron"); //test URL
client.CookieContainer = _cookieJar;
I worked this out in the end.
Basically create a cookie container, then add the session cookie from the response into the cookie container. All future requests will then contain this cookie.
var sessionCookie = response.Cookies.SingleOrDefault(x => x.Name == "ASP.NET_SessionId");
if (sessionCookie != null)
{
_cookieJar.Add(new Cookie(sessionCookie.Name, sessionCookie.Value, sessionCookie.Path, sessionCookie.Domain));
}

Categories