How to use a cookie with subdomains - c#

I have a situation where I want to use a cookie with these 2 subdomains app.example.com (ASP.NET) and appapi.example.com (Web API). I'm able to set the cookie successfully using the API like this:
public HttpResponseMessage Get()
{
...
var result = jsonHelper.setHttpResponseMessage(obj);
List<CookieHeaderValue> cookies = new List<CookieHeaderValue>();
NameValueCollection values = new NameValueCollection();
values["Value1"] = value1;
values["Value2"] = value2;
values["Value3"] = value3;
CookieHeaderValue cookie = new CookieHeaderValue("MyCookie", values);
/*#if DEBUG
cookie.Domain = Request.RequestUri.Host;
#else*/
cookie.Domain = ".example.com"; //I made this based on the answers to the questions posted below
//#endif
cookie.Path = "/";
cookie.Expires = DateTime.Now.AddHours(1);
cookie.HttpOnly = true;
cookies.Add(cookie);
result.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return result;
}
I'm using Postman and I get a response that looks like this under Cookie tab:
Name Value
MyCookie Value1=2&Value2=test&Value3=val
Then I'm sending the cookie to app.example.com/Page.aspx using Postman. The code at Page.aspx Page_Load looks like this:
if (!IsPostBack)
{
if (Request.Cookies["MyCookie"] != null)
{
var myCookie = Request.Cookies["MyCookie"].Values;
var value1 = myCookie["Value1"];
var value2 = myCookie["Value2"];
}
...
Here I'm not getting the values that I want which means that Request.Cookies["MyCookie"] is null
I'm aware of this question and this one which I have implemented above, but still it didn't fix my issue.
Based on this, I believe that it's possible to use a cookie with 2 or more subdomains, so I need to know how to implement it properly.

https://www.getpostman.com/docs/postman/sending_api_requests/cookies
above is the official document of how to add cookie in postman

Related

Unable to update cookies in asp.net mvc

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.

C# persistent cookie

I have seen the persistent cookies examples in ASP.NET MVC C# here on stackoverflow.
But I can't figure out why the code below isn't working.
First I write to the cookie:
HttpCookie cookie = new HttpCookie("AdminPrintModule");
cookie.Expires = DateTime.Now.AddMonths(36);
cookie.Values.Add("PrinterSetting1", Request.QueryString["Printer1"]);
cookie.Values.Add("PrinterSetting2", Request.QueryString["Printer2"]);
cookie.Values.Add("PrinterSetting3", Request.QueryString["Printer3"]);
Response.Cookies.Add(cookie);
I see the cookies stored in Internet Explorer. The content looks OK.
Then the reading code:
HttpCookie cookie = Request.Cookies["AdminPrintModule"];
test = cookie.Values["PrinterSetting2"].ToString();
The cookie variable keeps null . Storing the PrinterSetting2 value in the test variable fails.
I don't know what I'm doing wrong because this is more or less a copy-paste from the examples here on stackoverflow. Why can't I read the PrinterSetting2 value from the cookie ?
try with below code :-
if (Request.Cookies["AdminPrintModule"] != null)
{
HttpCookie cookie = Request.Cookies["AdminPrintModule"];
test = cookie["PrinterSetting2"].ToString();
}
Have a look at this document http://www.c-sharpcorner.com/uploadfile/annathurai/cookies-in-Asp-Net/ :-
Below are few types to write and read cookies :-
Non-Persist Cookie - A cookie has expired time Which is called as
Non-Persist Cookie
How to create a cookie? Its really easy to create a cookie in the
Asp.Net with help of Response object or HttpCookie
Example 1:
HttpCookie userInfo = new HttpCookie("userInfo");
userInfo["UserName"] = "Annathurai";
userInfo["UserColor"] = "Black";
userInfo.Expires.Add(new TimeSpan(0, 1, 0));
Response.Cookies.Add(userInfo);
Example 2:
Response.Cookies["userName"].Value = "Annathurai";
Response.Cookies["userColor"].Value = "Black";
How to retrieve from cookie?
Its easy way to retrieve cookie value form cookes by help of Request
object. Example 1:
string User_Name = string.Empty;
string User_Color = string.Empty;
User_Name = Request.Cookies["userName"].Value;
User_Color = Request.Cookies["userColor"].Value;
Example 2:
string User_name = string.Empty;
string User_color = string.Empty;
HttpCookie reqCookies = Request.Cookies["userInfo"];
if (reqCookies != null)
{
User_name = reqCookies["UserName"].ToString();
User_color = reqCookies["UserColor"].ToString();
}
You must ensure that you have values in Request.QueryString.Just to check if your code works hard code values of cookies and then read from cookie.

Using Cookie in Asp.Net Mvc 4

I have web application in Asp.Net MVC4 and I want to use cookie for user's login and logout. So my actions as follows:
Login Action
[HttpPost]
public ActionResult Login(string username, string pass)
{
if (ModelState.IsValid)
{
var newUser = _userRepository.GetUserByNameAndPassword(username, pass);
if (newUser != null)
{
var json = JsonConvert.SerializeObject(newUser);
var userCookie = new HttpCookie("user", json);
userCookie.Expires.AddDays(365);
HttpContext.Response.Cookies.Add(userCookie);
return RedirectToActionPermanent("Index");
}
}
return View("UserLog");
}
LogOut Action
public ActionResult UserOut()
{
if (Request.Cookies["user"] != null)
{
var user = new HttpCookie("user")
{
Expires = DateTime.Now.AddDays(-1),
Value = null
};
Response.Cookies.Add(user);
}
return RedirectToActionPermanent("UserLog");
}
And I use this cookie in _Loyout as follow:
#using EShop.Core
#using Newtonsoft.Json
#{
var userInCookie = Request.Cookies["user"];
}
...
#if (userInCookie != null && userInCookie.Value)
{
<li>Salam</li>
<li>Cıxış</li>
}
else
{
<li>Giriş</li>
}
But When I click *UserOut* action this action happen first time, but then it doesn't work. I put breakpoint for looking process but it get UserLog action doesn't UserOut.
My question is that where I use wrong way of cookie? What is a best way using cookie in Asp.Net Mvc4 for this scenario ?
Try using Response.SetCookie(), because Response.Cookies.Add() can cause multiple cookies to be added, whereas SetCookie will update an existing cookie.
We are using Response.SetCookie() for update the old one cookies and Response.Cookies.Add() are use to add the new cookies. Here below code CompanyId is update in old cookie[OldCookieName].
HttpCookie cookie = Request.Cookies["OldCookieName"];//Get the existing cookie by cookie name.
cookie.Values["CompanyID"] = Convert.ToString(CompanyId);
Response.SetCookie(cookie); //SetCookie() is used for update the cookie.
Response.Cookies.Add(cookie); //The Cookie.Add() used for Add the cookie.
userCookie.Expires.AddDays(365);
This line of code doesn't do anything. It is the equivalent of:
DateTime temp = userCookie.Expires.AddDays(365);
//do nothing with temp
You probably want
userCookie.Expires = DateTime.Now.AddDays(365);

Send Cookie in Post Response WebAPI

I am trying to send the user a cookie after I authenticate him. everything works perfect, the response is being constructed in my code, but even after the client got the response, There is no cookie saved in the browser (checking it via chrome F12 -> Resources).
Note: I can see the response being sent in fiddler with my cookie:
I wonder what is going wrong and why the browser doesn't save the cookie.
Here is the WebAPI function that handles the Post request:
public HttpResponseMessage Post([FromBody]User user)
{
IDal dal = new ProGamersDal();
var currentUser = dal.GetUser(user.Username, user.Password);
if (currentUser == null)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Bad request.");
}
else
{
var res = new HttpResponseMessage();
var cookie = new CookieHeaderValue("user",JsonConvert.SerializeObject(new ReponseUser(){username = currentUser.Username, role = currentUser.Role}));
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
res.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return res;
}
}
I've found out what the problem is since in Firefox the cookie was saved.
In chrome you cannot set a cookie with the domain of 'localhost' since it is considered as invalid domain (valid domain must contain two dots in it) - and therefore the cookie is invalid.
In order to solve it, in case of localhost, you should either:
set the domain to null.
set the domain to '' (empty)
set the domain to '127.0.0.1'
This is the fix in my code:
cookie.Domain = Request.RequestUri.Host == "localhost" ? null : Request.RequestUri.Host;

Cookies Do Not Set Quickly

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.

Categories