Shopping Cart Cookie not working in c# MVC - c#

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

Related

Modifying cookie subkeys in C#

I can't for the life of me understand what I'm doing wrong here. I've searched high and low but everything I try doesn't seem to fix.
I'm trying to create a cookie that stores the first and last name of a user. If the user goes back and changes either the first or second name it should modify these subkeys in the userName cookie. This part doesn't seem to work though?
protected void btnContinue_Click(object sender, EventArgs e)
{
if (IsValid)
{
HttpCookie cookie = new HttpCookie("userName");
if (cookie != null)
{
Response.Cookies.Remove("userName");
cookie.Values["firstName"] = txtFirstName.Text;
cookie.Values["lastName"] = txtLastName.Text;
}
else
{
cookie.Values["firstName"] = txtFirstName.Text;
cookie.Values["lastName"] = txtLastName.Text;
}
cookie.Expires = DateTime.Now.AddMinutes(5);
Response.Cookies.Add(cookie);
}
Response.Redirect("~/Order.aspx");
}
The way to delete cookies on the client browser is to override them, setting the expires value to a date in the past.
When you use this code:
Response.Cookies.Remove("userName");
you only delete the cookie on server, which Means it's not sent to the client. This Means the old cookie on the client is kept.
To delete the old cookie:
HttpCookie cookie = new HttpCookie("olduserName");
cookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cookie);
Here 'oldusername' contain the previous value of 'username'.
Edit:
Another way is to name your cookie with a name that doesn't change, ever, then you can simply override it with the new value, when username changes.
Edit2:
I actually made the same mistake as you did, you should use:
Response.Cookies.Set(cookie);
When using Add there can be more than one Cookie with the same name. This is most likely your problem (sorry, I did not see that before).
Edit2:
Just saw this line now:
Response.Redirect("~/Order.aspx");
You are redirecting! Then the cookies are not set on the client.
Instead you should set the cookies in "~/Order.aspx".

Do I have to rewrite cookie everytime I postback to retain it?

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.

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 :)

Why is my cookie not set?

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.

Setting ViewStateUserKey gives me a "Validation of viewstate MAC failed" error

I have the following in my BasePage class which all my ASPX pages derive from:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}
I also have a machineKey set in Web.config. I don't think this error is because of a web farm because this happens on my dev machine too.
My host has now upgraded to .NET 3.5 SP1. After this update, everytime I compile with the ViewStateUserKey setting above, I constantly get the "Validation of viewstate MAC failed" error on every postback.
What am I doing wrong here? Is this setting even necessary anymore with the latest framework update?
OK - Im a year late to the conversation - but how is this the correct answer? This applies only in the case of authenticated users and using the ViewStateUserKey as the username is a lot easier to guess than a session id GUID.
BTW if you want to 'fix' the code up top, use the Session ID, however you must set a session variable in order for the session id to stop from changing every time. Ex.
Session["Anything"] = DateTime.Now
ViewStateUserKey = Session.SessionID;
This of course is assuming you are going to use sessions, otherwise you need some other key to use such as the username or any other guid kept in a cookie.
I've searched around quite a bit to find the definitive cause of the issue.
This post from Microsoft really helped explain all the different causes.
http://support.microsoft.com/kb/2915218
Cause 4 is what we have landed on which is an invalid ViewStateUserKeyValue
Setting ViewStateUserKey to Session.SessionID or User.Identity.Name did not work for us.
We intermittently got the validation error due to the following.
When the application pool is reset by IIS, the session is renewed in effect causing the error.
We drop the Session on login to avoid session fixation, also resulting in the error on login.
What finally worked for us was a cookie based solution, which is now provided in VS2012.
public partial class SiteMaster : MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
//First, check for the existence of the Anti-XSS cookie
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
//If the CSRF cookie is found, parse the token from the cookie.
//Then, set the global page variable and view state user
//key. The global variable will be used to validate that it matches in the view state form field in the Page.PreLoad
//method.
if (requestCookie != null
&& Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
//Set the global token variable so the cookie value can be
//validated against the value in the view state form field in
//the Page.PreLoad method.
_antiXsrfTokenValue = requestCookie.Value;
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
//If the CSRF cookie is not found, then this is a new session.
else
{
//Generate a new Anti-XSRF token
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
//Set the view state user key, which will be validated by the
//framework during each request
Page.ViewStateUserKey = _antiXsrfTokenValue;
//Create the non-persistent CSRF cookie
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
//Set the HttpOnly property to prevent the cookie from
//being accessed by client side script
HttpOnly = true,
//Add the Anti-XSRF token to the cookie value
Value = _antiXsrfTokenValue
};
//If we are using SSL, the cookie should be set to secure to
//prevent it from being sent over HTTP connections
if (FormsAuthentication.RequireSSL &&
Request.IsSecureConnection)
responseCookie.Secure = true;
//Add the CSRF cookie to the response
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
//During the initial page load, add the Anti-XSRF token and user
//name to the ViewState
if (!IsPostBack)
{
//Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
//If a user name is assigned, set the user name
ViewState[AntiXsrfUserNameKey] =
Context.User.Identity.Name ?? String.Empty;
}
//During all subsequent post backs to the page, the token value from
//the cookie should be validated against the token in the view state
//form field. Additionally user name should be compared to the
//authenticated users name
else
{
//Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] !=
(Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of
Anti-XSRF token failed.");
}
}
}
}
Source
I fixed it for now by changing the code to:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (User.Identity.IsAuthenticated)
ViewStateUserKey = User.Identity.Name;
}
Can you turn off ViewState MAC encoding with the EnableViewStateMac #Page attribute?
VERY Strange, I too had similar issue for 3 days and now i resolved it.
1. I had enabled forms authentication and had ssl false
<forms defaultUrl="~/" loginUrl="~/Account/Login.aspx" requireSSL="false" timeout="2880" />
but in my httpcookies tag I had requireSSL=true. Since in the Site.Master.cs it uses cookies to set the ViewStateUserKey, it was having issues
hence I was getting the error.
I modified this to false and restarted web app, now its all good.

Categories