I don't typically play with Cookies, but I wanted to look into this one verses the Session variables I typically use.
If I set a Cookie, then immediately try to read from it, I do not get the value back that I just set it to.
However, if I refresh the page or close the browser and open it back up, the Cookie appears to be set.
I'm debugging this in Chrome. Would that make any difference?
public const string COOKIE = "CompanyCookie1";
private const int TIMEOUT = 10;
private string Cookie1 {
get {
HttpCookie cookie = Request.Cookies[COOKIE];
if (cookie != null) {
TimeSpan span = (cookie.Expires - DateTime.Now);
if (span.Minutes < TIMEOUT) {
string value = cookie.Value;
if (!String.IsNullOrEmpty(value)) {
string[] split = value.Split('=');
return split[split.Length - 1];
}
return cookie.Value;
}
}
return null;
}
set {
HttpCookie cookie = new HttpCookie(COOKIE);
cookie[COOKIE] = value;
int minutes = String.IsNullOrEmpty(value) ? -1 : TIMEOUT;
cookie.Expires = DateTime.Now.AddMinutes(minutes);
Response.Cookies.Add(cookie);
}
}
Below is how I use it:
public Employee ActiveEmployee {
get {
string num = Request.QueryString["num"];
string empNum = String.IsNullOrEmpty(num) ? Cookie1 : num;
return GetActiveEmployee(empNum);
}
set {
Cookie1 = (value != null) ? value.Badge : null;
}
}
This is how I am calling it, where Request.QueryString["num"] returns NULL so that Cookie1 is being read from:
ActiveEmployee = new Employee() { Badge = "000000" };
Console.WriteLine(ActiveEmployee.Badge); // ActiveEmployee is NULL
...but reading from Cookie1 is returning null also.
Is there a command like Commit() that I need to call so that a cookie value is immediately available?
Cookies are not like Session- there are two cookie collections, not one.
Request.Cookies != Response.Cookies. The former is the set of cookies that are sent from the browser when they request the page, the latter is what you send back with the content. This is exposing the nature of the cookies RFC, unlike Session, which is a purely Microsoft construct.
When you set a cookie in a response it does not get magically transported into the request cookies collection. It's there in the response, you're free to check for it there, but it won't appear in the request object until it actually is sent from the browser in the next request.
To add to the other answers, you can get around the problem by caching the value in a private variable in case the cookie hasn't been updated yet:
private string _cookie1Value = null;
private string Cookie1 {
get {
if (_cookie1Value == null)
{
// insert current code
_cookie1Value = cookie.Value;
}
return _cookie1Value;
}
set {
// insert current code
_cookie1Value = value;
}
}
To simply put it; A cookie that is set in response, will only be available for the next htpp request (a next get or post action from the browser).
In detail: When a cookie value is set in HttpResponse, it will be persisted/stored only when after the response reaches client (meaning the browser will read the cookie value from Http Response header and save it). So, technically only for the henceforth requests it will be available. Example, when the user clicks on a link or a button that makes server call after this cycle from the browser.
Hope this gives you some idea, I suggest you read the What are cookies and ASP.NET wraps it before using it.
Related
I'm currently having an issue with cookies in my Web Application.
First of all, i created 2 generic methods into my controller to simplify my cookie manipulation. Here they are :
public bool SetCookie<T>(string key, T value)
{
try
{
string str = Utils.JSONParser.Serialize(value);
var cookie = new HttpCookie(key, Utils.JSONParser.Serialize(value))
{
HttpOnly = true
};
cookie.Expires = DateTime.UtcNow.AddDays(365);
Response.SetCookie(cookie);
return true;
}
catch (Exception ex)
{
throw ex;
}
}
public T GetCookie<T>(string key)
{
T obj;
if (Request.Cookies[key] != null)
{
HttpCookie cookie = Request.Cookies.Get(key);
obj = Utils.JSONParser.Deserialize<T>(cookie.Value);
return obj;
}
return (typeof(T) == typeof(int) ? (T)(object)-1 : default(T));
}
Note that, theses methods are working perfectly with some "normal" use. (The Utils.JSONParser is a simple encapsulation of JavaScriptSerializer.
I'm having an issue by using this code :
public ActionResult Index(int LineNumber = -1)
{
IndexViewModel model = new IndexViewModel();
if (LineNumber != -1)
this.SetCookie("lineNumber", LineNumber);
model.LineNumber = this.GetCookie<int>("lineNumber");
....
}
Here, LineNumber's value is for example 5, and the current cookie value is (for example) 20. So, here i wanna erase 20, and put 5 instead. But this isn't happening. I have to pass through this method 2 times (with 5 as parameter) to finally store 5 in the cookie value.
So my question is, is there a loading time to store a cookie ? Which would explain this ? Or am i simply missing something ?
Notice how your SetCookie method changes the Response while your GetCookie method gets the value from your Request. So only when you finish your entire request processing and then get a second request will the cookie set in the request be the cookie you set in the first response.
I'm trying to set and read cookies in c#. I wrote these two methods:
public static void setCookie(string sCookie, string value)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[sCookie];
if (cookie == null)
cookie = new HttpCookie(sCookie);
cookie.Value = value;
cookie.Expires = DateTime.Now.AddYears(1);
HttpContext.Current.Request.Cookies.Add(cookie);
}
public static string getCookie(string sCookie)
{
if (HttpContext.Current.Request.Cookies[sCookie] == null)
return null;
return HttpContext.Current.Request.Cookies[sCookie].Value;
}
But I don't know why when I read the method getCookie, after calling setCookie, the collection HttpContext.Current.Request.Cookies contains always 2 elements, "__RequestVerificationToken" and "ASP.NET_SessionId", it doesn't contain my cookies...
Methods are not in any controller, just in a utils class, but I don't see any problem for that...
Can you figure out why my set method doesn't work?
Thank you!
Set cookies to the Response object, also set the Path of a cookie
I can write and read cookies but I can't change value for existing cookie it always has first set value. I found few ways how it can be implemented but no one works. Here is my code:
private void AddPost(string key)
{
var context = System.Web.HttpContext.Current;
var request = context.Request;
var response = context.Response;
var cookie = request.Cookies[Constants.PostsViewing];
if (cookie == null || string.IsNullOrEmpty(cookie.Value))
{
response.Cookies.Add(new HttpCookie(Constants.PostsViewing, key)
{
Expires = DateTime.Now.AddDays(365)
});
}
else
{
if (cookie.Value.Split(';').Contains(key))
{
return;
}
var v = cookie.Value + ";" + key;
cookie.Value = v;
cookie.Expires = DateTime.Now.AddDays(365);
response.Cookies.Add(cookie);
// this way also doesn't work
//cookie.Value = v;
//response.AppendCookie(cookie);
// and this
//response.Cookies[Constants.PostsViewing].Value = v;
//response.Cookies[Constants.PostsViewing].Expires = DateTime.Now.AddDays(365);
}
}
According to msdn cookie file should be owerwritten.
Each cookie must have a unique name so that it can be identified later when reading it from the browser. Because cookies are stored by name, naming two cookies the same will cause one to be overwritten.
Do you have any idea how to fix it?
I just ran into this exact scenario with a similar block of code:
public ActionResult Index(int requestValue)
{
var name = "testCookie";
var oldVal = Request.Cookies[name] != null ? Request.Cookies[name].Value : null;
var val = (!String.IsNullOrWhiteSpace(oldVal) ? oldVal + ";" : null) + requestValue.ToString();
var cookie = new HttpCookie(name, val)
{
HttpOnly = false,
Secure = false,
Expires = DateTime.Now.AddHours(1)
};
HttpContext.Response.Cookies.Set(cookie);
return Content("Cookie set.");
}
The first time that code would run, the cookie would be set without incident. But any subsequent run would never update it at all (value or expiration).
Turns out, the semi-colon is an illegal character in a cookie value, and trying to delimit your values with it will cause the cookie value to be truncated. If we change the semi-colon to another character, like a pipe (|), everything works out just fine.
Consider the header sent for a cookie value (courtesy of Fiddler):
Response sent 61 bytes of Cookie data:
Set-Cookie: testCookie=2;1; expires=Tue, 09-Sep-2014 19:23:43 GMT; path=/
As we can see, the semi-colon is being used to separate the individual parts of the cookie definition. Thus, if you want to use a semi-colon in cookie value itself, it must be encoded so as not to be misinterpreted. This answer gives a more detailed look into the actual specification: https://stackoverflow.com/a/1969339/143327.
You can't use a semi-colon, in plain text, as your delimiter.
According to the ancient Netscape cookie_spec:
This string is a sequence of characters excluding semi-colon, comma and white space.
You can't directly modify a cookie. Instead you are creating a new cookie to overrite the old one.
http://msdn.microsoft.com/en-us/library/vstudio/ms178194(v=vs.100).aspx
Try
var v = cookie.Value + ";" + key;
Response.Cookies[Constants.PostsViewing].Value = v;
Response.Cookies[Constants.PostsViewing].Expires = DateTime.Now.AddDays(365);
This should change the client Response instead of the servers Request.
In order to use Response.AppendCookie, you first have to get a HttpCookie from your Cookies collection.
I have a javascript function that updates a cookie in the following manner:
aspx page:
function setCookie()
{
//...
document.cookie = "myCookie = HelloWorld";
//...
}
After an asp control triggers an event, the entire page gets sent back from the client. I want to be able to read the value of my cookie. How do I do that?
I've tried:
string temp = Request.ServerVariables["myCookie"].ToString(); but that is the wrong way to do it.
How do I read the client cookie on the server
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);
Source MSDN
Here is the helper method to retrieve cookie at server side.
public static String GetCookie(String cookieName)
{
try
{
if (HttpContext.Current.Request.Cookies[cookieName] == null)
return String.Empty;
return HttpContext.Current.Request.Cookies[cookieName].Value;
}
catch
{
return String.Empty;
}
}
Usage
var result = GetCookie("myCookie");
If you want to set cookie at client side, look at this Cookie plugin.
I don't really understand the difference between request cookie and response cookie. And it seem like everytime I postback, if I don't manually rewrite the cookie from request to response, then it disappears. How do I solve this?
public string getCookie(string name) {
if (Request.Cookies["MyApp"] != null && Request.Cookies["MyApp"][name] != null) {
return Request.Cookies["MyApp"][name];
} else if (Response.Cookies["MyApp"] != null && Response.Cookies["MyApp"][name] != null) {
return Response.Cookies["MyApp"][name];
} else {
return "";
}
}
public void writeCookie(string name, string value) {
Response.Cookies["MyApp"][name] = value;
HttpCookie newCookie = new HttpCookie(name, value);
newCookie.Expires = DateTime.Now.AddYears(1);
Response.SetCookie(newCookie);
}
Request.Cookies["MyApp"];
Code above will return you a cookie with name "MyApp" Doing this:
Request.Cookies["MyApp"][name]
You are taking value "name" from cookie called "MyApp".
But in your setCookie code you are setting a cookie with called name and do not create a cookie called "MyApp":
HttpCookie newCookie = new HttpCookie(name, value);
newCookie.Expires = DateTime.Now.AddYears(1);
Response.SetCookie(newCookie);
So, you should remove ["MyApp"] from any place you have it, or you may do something like this in setCookie:
public void writeCookie(string name, string value) {
if(Response.Cookies["MyApp"] == null) {
HttpCookie newCookie = new HttpCookie("MyApp");
newCookie.Expires = DateTime.Now.AddYears(1);
Response.SetCookie(newCookie);
}
if(Response.Cookies["MyApp"][name] == null)
Response.Cookies["MyApp"].Values.Add(name, value);
else
Response.Cookies["MyApp"][name] = val;
// or maybe simple Response.Cookies["MyApp"][name] = val; will work fine, not sure here
}
Request is the "thing" you get when the user tries to get to your website, while Response is a way of responding to this request.
In other words, see the official msdn documentation, namely this part:
ASP.NET includes two intrinsic cookie collections. The collection
accessed through the Cookies collection of HttpRequest contains
cookies transmitted by the client to the server in the Cookie header.
The collection accessed through the Cookies collection of HttpResponse
contains new cookies created on the server and transmitted to the
client in the Set-Cookie header.
http://msdn.microsoft.com/en-us/library/system.web.httprequest.cookies.aspx
So no, you don't have to create new cookies every time, unless they have already expired. Just be sure you reference the right collection of cookies.
You might want to check the domain and path that are being assigned to the cookie. It could be that your saved cookies are just being orphaned because the path is too specific or because the wrong domain is being set.
Domain is the server name that the browser sees such as "yourdomain.com". If the cookie is set with a different domain than this then the browser will never send it back. Likewise, the path of the cookie is the path to the resource being requested such as "/forum/admin/index" etc. The cookie is sent for that location and all child locations, but not for parent locations. A cookie set for "/forum/admin/index" will not be sent if you're accessing a page that sits in the "/forum" directory.