Why is my cookie not set? - c#

I am playing around again with ASP.NET, and tried to set a cookie in one action which will be read in another action.
The strange thing is: the cookie gets set, but looses its value when accessing another page. Here is my simple controller code:
public class HomeController : Controller
{
public ActionResult About()
{
var cookie = Response.Cookies.Get("sid");
ViewData["debug"] = "Id: " + cookie.Value;
return View();
}
public ActionResult DoLogin()
{
var cookie = new HttpCookie("sid", Guid.NewGuid().ToString());
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
return RedirectToAction("About");
}
}
The flow is like this: first I access /Home/DoLogin, then I get redirected to /Home/About which should actually output the value of the sid cookie. But the cookie does not have any value.
Cookies are not disabled in my browser
I know that ASP.NET has its own session handling mechanism, just playing around and stumbled upon this cookie problem
Thanks for any hints!

In your About action, use Request.Cookies instead.
As a short explanation: When you set something in Response.Cookies, that cookie is sent to the client which stores it. On each subsequent Request to the same namespace, until the expiry date is reached, the client sends that cookie to the server, which stores it in Request.Cookies.

Related

"An item with the same key has already been added." while adding "/&output=embed"

Implementing a MVC application in C# with Evernote API. I am using the AsyncOAuth.Evernote.Simple nuget package. Receiving and error of Refused to display in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN', when trying to navigate to URL that fires off the OAuth process.
There is an iframe that is surrounding my code (which can not be altered). After implementing the code an error is generated: "An item with the same key has already been added". This error occurs when requestToken is hit for the first time.
Below is my EvernoteProviderController.cs
public class EvernoteProviderController : Controller
{
// Initialize Oauth call, pulling values from web.config
EvernoteAuthorizer EvernoteAuthorizer = new EvernoteAuthorizer(ConfigurationManager.AppSettings["Evernote.Url"] + "&output=embed", ConfigurationManager.AppSettings["Evernote.Key"], ConfigurationManager.AppSettings["Evernote.Secret"]);
// This method makes the original call to Evernote to get a token so that the user can validate that they want to access this site.
public ActionResult Authorize(bool reauth = false)
{
// Allow for reauth
if (reauth)
SessionHelper.Clear();
// First of all, check to see if the user is already registered, in which case tell them that
if (SessionHelper.EvernoteCredentials != null)
return Redirect(Url.Action("AlreadyAuthorized"));
// Evernote will redirect the user to this URL once they have authorized your application
var callBackUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Url.Action("ObtainTokenCredentials");
// Generate a request token - this needs to be persisted till the callback
var requestToken = EvernoteAuthorizer.GetRequestToken(callBackUrl);
// Persist the token
SessionHelper.RequestToken = requestToken;
// Redirect the user to Evernote so they can authorize the app
var callForwardUrl = EvernoteAuthorizer.BuildAuthorizeUrl(requestToken);
return Redirect(callForwardUrl);
}
// This action is the callback that Evernote will redirect to after the call to Authorize above
public ActionResult ObtainTokenCredentials(string oauth_verifier)
{
// Use the verifier to get all the user details we need and store them in EvernoteCredentials
var credentials = EvernoteAuthorizer.ParseAccessToken(oauth_verifier, SessionHelper.RequestToken);
if (credentials != null)
{
SessionHelper.EvernoteCredentials = credentials;
return Redirect(Url.Action("Authorized"));
}
else
{
return Redirect(Url.Action("Unauthorized"));
}
}
// Show the user if they are authorized
public ActionResult Authorized()
{
return View(SessionHelper.EvernoteCredentials);
}
public ActionResult Unauthorized()
{
return View();
}
//Redirects user if already authorized, then dump out the EvernoteCredentials object
public ActionResult AlreadyAuthorized()
{
return View(SessionHelper.EvernoteCredentials);
}
public ActionResult Settings()
{
return View();
}
}
Has anyone had this issue with iframes before or knows in what direction I should go? I am trying to embed my URL endpoint so I can get around the iframe error.
Solved the error.
A bit of back story:
The purpose of this application was to provide the OAuth page where a user can sign up which will generate a AuthToken and NotebookURL, (both are needed with Evernote API to pull read/write Notes - which is Evernote's object).
The previous behavior (before I changed it), was when a user clicked on the link - they will be redirected (in the same window) to the Evernote OAuth page.
This caused issues for me, because I had another wrapper around my code (iframe). So in non-technical terms, I had a iframe within an iframe within an iframe.
Workaround
Created a JavaScript code which would add an click event listener, which would then create a popup using window.open.
$("#btnStart").click(function () {
myWindow = window.open(baseUrl + "/EvernoteProvider/Authorize", '_blank', 'width=500,height=500, scrollbars=no,resizable=no');
myWindow.focus();
});

Shopping Cart Cookie not working in c# MVC

What this cookie aims is (if the cookie exists) to remember CartId so that user anonymous or registered can see his cart. If cookie doesn't exists it creates one with GuId and stores the cartId for some period of time.
I tried in some way to achieve that in this code:
enter image description here
And here cookie isn't working. It saves only cookie in line 190 with CartId always 0 and the other if and else statements are not checked. The line 190 I wrote it because it was throwing null exception statement without this line.Also I think that a mistake that I made is that I didn't use Current context above of line 197.
I tried to use HttpContext.Current and it throws this error :
enter image description here
Help me out please if it can be fixed. Any other example or url of cookies c# shopping cart is accepted. Thank you in advance.
First attempt:
public string GetCartId(HttpContextBase context )
{
if (context.Request.Cookies["CartId"] == null) return "0";
string cartId = context.Request.Cookies["CartId"].Value;
{
// if the cart ID doesn't exist in the cookie, generate
// a new ID
if (context.Request.Cookies["CartId"] == null)
{
// generate a new GUID
cartId = Guid.NewGuid().ToString();
// create the cookie object and set its value
HttpCookie cookie = new HttpCookie("CartId", cartId);
// set the cookie's expiration date
cookie.Expires = DateTime.Now.AddMinutes(2);
// set the cookie on the client's browser
context.Response.Cookies.Add(cookie);
// return the CartID
return cartId.ToString();
}
else // check if the cart ID exists as a cookie
{
// return the id
return cartId;
}
}
}
Here it saves cartId always null and not checking other statements
Second Attempt I added Current Context :
if (context.Request.Cookies["CartId"] == null)
{
HttpContext context = HttpContext.Current;
And context underlined with red says a local parameter named context cannot be declared in this scope because the name is used in an enclosing local scope.
Creating a cookies within a MVC Controller:
HttpCookie cookie = new HttpCookie("Cookie");
cookie.Value = "Hello Cookie! CreatedOn: " + DateTime.Now.ToShortTimeString();
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
Check & Read a cookie within a MVC Controller:
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains("Cookie"))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies["Cookie"];
...
The Cookies.AllKeys.Contains() can replace your null check.
How to you call your method? What is the value of context?
The MSDN Documentation about Cookies can be found here...
Working with cookie in Legacy Asp.net was good, As you are developing application using MVC design pattern, Here we have other important concept to manage state.
Few are listed below:-
tempdata
viewdata
viewbag
And you can get explanation here
The value for the HttpOnly property of HttpCookie is "false" by default
This means you ask the browser to store your cookie on the disk
Change this to "true" before adding the cookie to the response. A note here, the client cookie will be lost if he closes all the instances of the browser.
If this does not help, you should add a privacy policy to your web site
try this, and if http only does not help, we can go for the p3p privacy policy solution

Accessing Cookies in View value null MVC 4

So I really stumped with cookies right now and I'm not exactly sure whats going on. I saw a lot of cookie questions regarding losing values of cookies and I've tried almost copying exact same code but it still doesn't seem to resolve any of the issues.
Here is the code I use to set the cookie.
HttpCookie cookie = Response.Cookies["Name"];
if (cookie != null)
{
cookie.Value = user.LastName + " " + user.FirstName;
cookie.Expires = DateTime.UtcNow.AddYears(1);
Response.Cookies.Set(cookie);
}
else
{
cookie.Name = "Name";
cookie.Value = user.LastName + " " + user.FirstName;
cookie.Expires = DateTime.UtcNow.AddYears(1);
Response.Cookies.Add(cookie);
}
return RedirectToAction("Index", "Home");
Currently I'm debugging at Home/Index to check the values of the cookie before it gets to the view to see what is in the cookie.
One strange note is that when I check the content of the cookie the values are there but the Expire date is reset to 1/1/0001 right after I redirect from creating the cookie. I don't understand why does it reset it... or am I not setting/adding the cookies properly?
public ActionResult Index()
{
HttpCookie cookie = Request.Cookies["Name"];
ViewBag.Name = cookie.Value;
return View();
}
public ActionResult About()
{
HttpCookie cookie = Request.Cookies["Name"];
return View();
}
The issue is that the Cookie value is there before I return to the view but once I get to the view and try to access it directly from the view with.
#Response.Cookies["Name"].Value
The moment I get to the view the cookie values are null, expiration time gets change to when the browser is close when I check the cookie in the setting of chrome.
I read on some other articles it had something to do with the way I am redirecting, but I tried using response.redirect but it didn't seem to fix the issue. Can anyone point me in the right direction for handling this?

Lost session/cookie when login as another user

I am building dnn module which allow logged in user to log in as another user.
But I have some wired issue here.
This is how I log out current user and login as another user:
UserInfo userInfo = UserController.GetUserById(portalId, userId);
if (userInfo != null)
{
DataCache.ClearUserCache(this.PortalSettings.PortalId, Context.User.Identity.Name);
if (Session["super_userId"] == null)
{
Session["super_userId"] = this.UserId;
Session["super_username"] = this.UserInfo.Username;
}
HttpCookie impersonatorCookie = new HttpCookie("cookieName");
impersonatorCookie.Expires = DateTime.Now.AddHours(1);
Response.Cookies.Add(impersonatorCookie);
Response.Cookies["cookieName"]["super_userId"] = this.UserId.ToString();
Response.Cookies["cookieName"]["super_username"] = this.UserInfo.Username;
PortalSecurity objPortalSecurity = new PortalSecurity();
objPortalSecurity.SignOut();
UserController.UserLogin(portalId, userInfo, this.PortalSettings.PortalName, Request.UserHostAddress, false);
Response.Redirect(Request.RawUrl, true);
}
And in PageLoad() I try to read value from this cookie but it doesn't read anything:
try
{
string super_userId = Request.Cookies["cookieName"]["super_userId"];
string super_username = Request.Cookies["cookieName"]["super_username"];
if (!String.IsNullOrEmpty(super_userId))
{
this.Visible = true;
this.lblSuperUsername.Text = Session["super_username"].ToString();
this.txtPassword.Enabled = true;
this.btnBackToMyAccount.Enabled = true;
}
...
I also have tried to do the same with session but nothing works, and I can't figure why?
As I find here, there can be problems with setting cookies in a request that gets redirected, and here is stated that cookies won't get set with a redirect when their domain is not /.
So you can try to not redirect using HTTP headers, but show a "Logged In" page instead that contains a "Home" link and a meta refresh or Javascript redirect.
By the way, setting a UserID in a cookie is not really the way to go. What if I change that cookie value to 1?
I suggest when you set a new cookie to always set the Domain, and probably and the Expires.
Response.Cookies[cookieName].Domain = RootURL;
Response.Cookies[cookieName].Expires = DateTime.UtcNow.AddDays(cDaysToKeep);
The domain is very importan to be the url with out the subdomain, eg only the mydomain.com with out the www. because if a cookie is set from www.mydomain.com and you try to read it from mydomain.com or vice versa, then the cookie will not be read and you may lost it / overwrite it.
So I suggest to make a function that when you set a cookie, you set at least 3 parametres, the Domain, the Expires, and the Value.
Similar questions and answers :
Multiple applications using same login database logging each other out
asp.net forms authentication logged out when logged into another instance
Put these two statements
Response.Cookies["cookieName"]["super_userId"] = this.UserId.ToString();
Response.Cookies["cookieName"]["super_username"] = this.UserInfo.Username;
after
UserController.UserLogin(portalId, userInfo, this.PortalSettings.PortalName, Request.UserHostAddress, false);
May be the UserLogin method is resetting the Session variables.
Hope it Helps :)

RedirectToAction causing empty cookie to be set ahead of cookie with values, which results in "lost" cookie

I am using a cookie and if the cookie is set, it forwards the user to signin, else it shows them an error page (unauthorized). The cookie is being set correctly, and if I navigate to any page by typing it in the address bar, it works just fine. However, when I use RedirectToAction or FormsAuthentication.RedirectToLogin the cookie is not available, which is causing an infinite loop in redirection.
Home - If user has cookie, go to signin, if not show home page.
Signin - If user has cookie, show page, else redirect to home
My redirection is handled through an attribute.
public sealed class RequireBillerAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
IUserSession session = ServiceLocator.Locate<IUserSession>();
if (session.BillerId == 0)
filterContext.Result = new RedirectResult("~/");
}
}
My Home action looks like this
public ActionResult Index()
{
//if the user is signed in, send them to their account page. They don't need to see the front page
if (Request.IsAuthenticated)
{
return RedirectToAction("Index", "Account");
}
//users with their cookie set should sign in
if (session.BillerId != 0)
return RedirectToAction("Index", "SignIn");
return View();
}
And my signin action looks like this
[RequireBiller]
public ActionResult Index()
{
SignInModel model = BuildSignInModel();
return View(model);
}
Now, when I hit mysite.com/ the redirect causes an infinite loop. In debugging, the attribute cannot find the value from the cookie. The cookie is actually blank in the request. When I type mysite.com/signin everything works peachy. Any ideas?
EDIT
As suggested, I ran fiddler. Here's what the requests look like
# Result Protocol Host URL Body Caching Content-Type Process Comments Custom
1 302 HTTP localhost:27412 / 124 private text/html; charset=utf-8 chrome:6008
2 302 HTTP localhost:27412 /SignIn 118 private text/html; charset=utf-8 chrome:6008
3 302 HTTP localhost:27412 / 124 private text/html; charset=utf-8 chrome:6008
4 302 HTTP localhost:27412 /SignIn 118 private text/html; charset=utf-8 chrome:6008
And here is the cookie information
First
__RequestVerificationToken_Lw__=NNu8v2oTMX2YKQOW+JRN1LQRYPhlmPszQa8Rs1KrQp1pPxWmQO8GG7eRrzbhFZF38p05ckuLHAK3QaTIlxeFJ6POTX1woXRx/ahApLpF529inJO9mj3jSnoHqG6fthzJpoLYQL61NOCCUO2wwzLmQg==;
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=P%2ffJD5CdLO0pCGU6GntaPw*=P6QAytlDVUrkQn84c9vDVg*
Second
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=;
__RequestVerificationToken_Lw__=NNu8v2oTMX2YKQOW+JRN1LQRYPhlmPszQa8Rs1KrQp1pPxWmQO8GG7eRrzbhFZF38p05ckuLHAK3QaTIlxeFJ6POTX1woXRx/ahApLpF529inJO9mj3jSnoHqG6fthzJpoLYQL61NOCCUO2wwzLmQg==;
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=P%2ffJD5CdLO0pCGU6GntaPw*=P6QAytlDVUrkQn84c9vDVg*
Third
__RequestVerificationToken_Lw__=NNu8v2oTMX2YKQOW+JRN1LQRYPhlmPszQa8Rs1KrQp1pPxWmQO8GG7eRrzbhFZF38p05ckuLHAK3QaTIlxeFJ6POTX1woXRx/ahApLpF529inJO9mj3jSnoHqG6fthzJpoLYQL61NOCCUO2wwzLmQg==;
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=P%2ffJD5CdLO0pCGU6GntaPw*=P6QAytlDVUrkQn84c9vDVg*
Fourth
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=;
__RequestVerificationToken_Lw__=NNu8v2oTMX2YKQOW+JRN1LQRYPhlmPszQa8Rs1KrQp1pPxWmQO8GG7eRrzbhFZF38p05ckuLHAK3QaTIlxeFJ6POTX1woXRx/ahApLpF529inJO9mj3jSnoHqG6fthzJpoLYQL61NOCCUO2wwzLmQg==;
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=P%2ffJD5CdLO0pCGU6GntaPw*=P6QAytlDVUrkQn84c9vDVg*
And here's what it looks like when I type in /signin into the address bar
__RequestVerificationToken_Lw__=NNu8v2oTMX2YKQOW+JRN1LQRYPhlmPszQa8Rs1KrQp1pPxWmQO8GG7eRrzbhFZF38p05ckuLHAK3QaTIlxeFJ6POTX1woXRx/ahApLpF529inJO9mj3jSnoHqG6fthzJpoLYQL61NOCCUO2wwzLmQg==;
4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*=P%2ffJD5CdLO0pCGU6GntaPw*=P6QAytlDVUrkQn84c9vDVg*
Yes, my cookies are encrypted. The cookiename is "4%40f0nkyBbqcTD4g9yl1J8KDNcWdqRpixrEoHLuMP2Lc*" It seems to me the redirect is appending a new empty cookie in there. WHY? I'm not sure.
ADDITIONAL
After debugging, I have found that indeed there are 3 cookies in the Request. The first is the empty cookie, which is returned by default when using the name. The third cookie in the collection has the values set. Why it is appending this cookie into the request is a mystery. I can probably work around this by picking the cookie that has a value over the other one, but I'd rather fix the root issue, whatever it is, that is happening only on the signin page.
I think what's happening is that RedirectToAction is doing a Response.Redirect() which is terminating the processing of the request and not allowing the cookie to be set. Sounds like a similar problem to what is documented here for session:
http://weblogs.asp.net/bleroy/archive/2004/08/03/207486.aspx
I had a cookie that was not being set properly after calling RedirectToAction(). I ended up utilizing TempData[] as described in this answer: https://stackoverflow.com/a/3624353/1265197
Here is my code. The account string was retrieved via a Query String on the url named 'account':
public ActionResult OriginatingAction(string account)
{
//Some other code
TempData["data"] = account;
return RedirectToAction("RedirectAction");
}
I could then use TempData["data"] to set the cookie in the action that I redirected to:
public ActionResult RedirectAction()
{
if(TempData["data"] != null)
{
HttpCookie dataCookie = new HttpCookie("dataCookie");
dataCookie.Values.Add("account", TempData["data"] as string);
dataCookie.Expires = DateTime.Now.AddHours(12);
Response.Cookies.Add(dataCookie);
}
return View();
}

Categories