How to read multiple cookie with same name in webapi using C# - c#

We have two cookies created with same name.
When i am iterating through loop, i am always getting first cookie.
Is there way to access both cookie separately?
if (Request.Cookies.AllKeys.Where(x => x == "test").Count() > 1)
{
foreach (var cookie in Request.Cookies.AllKeys)
{
if (Request.Cookies[cookie].Name == "test")
{
var temp = System.Web.HttpContext.Current.Request.Cookies["test"];
temp.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(temp);
}
}
};

When a cookie already exists, and you update it (through the response's Cookies collection), either by adding or updating it, a second 'duplicate' cookie is added to the Request's Cookies collection. This duplicate one is actually the one you just updated.
Although I did not check this on MSDN documentation, I believe this is most probably by design. Why you ask? Because it allows you to get either YOUR current version of the cookie (the one you've just updated/added through the Response), or the one that was actually sent over by the user's browser (which is thus their current version of the cookie at this moment in time).
Now, using either Cookies.Get(name), Cookies[name] or -the way you are doing it- looping through the key collection (from the start) and then returning the first match, will always result in the first cookie beïng returned. This is the cookie as the user still knows it, thus not the one you've been updating during this request.
If you want to retrieve 'your' current version of the cookie, you must get the last one with that name, instead of the first. You can do so like this:
int index = Array.LastIndexOf(this.HttpRequest.Cookies.AllKeys, cookieKey);
if (index != -1)
{
result = this.HttpRequest.Cookies[index];
}
Of course this will also always return the correct cookie if you didn't update it within the current request.

we cannot have two cookies with the same name in a particular domain and also by default we get the cookies from the current domain. So I am not seeing a case where to you can get two cookies with the same name in the above-mentioned code.
Please mention your issue wit more detail.

Related

Update Session during ajax request then access Session in the view

Session["SelectedRecords"] is used to contain the Id's of selected records, e.g.
SelectedRecords: 1108392 1108393 1108394
When I fire an ajax post that removes an id from the Session["SelectedRecords"] which as far as server side is concerned successfully removes the ID from Session["SelectedRecords"]...
List<int> ids = SessionHelper.GetSelectedRecordIds();
ids.Remove(selectedItemModel.Id);
string csv = string.Join<int>(",", ids);
this.Session["SelectedRecords"] = csv;
using an onSuccess/onRequestEnd event I then use console.log to output the Session["SelectedRecords"] to check.
function onRequestEnd(e) {
console.log('onRequestEnd SelectedRecords: ' + #Session["SelectedRecords"]);
}
But the console.log shows that Session["SelectedRecords"] (as far as the client is concerned still contains the removed id?!)
So the question is when I remove a value from Session["SelectedRecords"] via an ajax post and afterwards access Session["SelectedRecords"] in the view, the view is reporting 'old' values i.e. not the latest values?!
Generally, when you have one object in Session and you POST a delete, you have to remove it also from the Session. This is done like below:
Session.Remove("key");
where key is the unique key you have used to store the item in the Session.
However, in your case this will not work. You have to do two things:
Remove the SelectedRecords from the Session.
Add the new SelectedRecords (without the one record you deleted with your POST) to the Session.
After doing this (which after your update it seems you already have this logic in your code), you have to return back to the client the new SelectedRecords and replace the old value with the new.
Something like this:
$("#selectedRecords").val(newSelectedRecords)
The above should be executed in the success callback of your AJAX call.

Is it possible to cache authorizations in ASP.NET MVC & Identity 2.0?

if this question is somehow off-topic, let me know.
I will take it elsewhere, but I wanted to get some ideas on how to accomplish something within an existing project.
My web app (using ASP.NET MVC 5 and ASP.NET Identity 2.0) performs authorization (via those fancy Authorize attributes) with a custom Role Provider.
Every authorization check (like Authorize(Roles = "Admin")) requires querying the database to perform the following:
Get the current "semester" (check what date range the current date & time falls within) from the Semesters table
Get the position with the name "Admin" from the Positions table
Check if there exists a record in the Leaders table containing the current user ID, the obtained semester ID, and the obtained position ID.
If a record exists, the user is authorized, otherwise they are not.
To be clear, assignment to a role is tied to a semester in order to limit the corresponding privileges to the duration of a semester.
I.e., once the semester ends, the user no longer has their powers, but the next person appointed for the next semester will immediately gain theirs.
Most of my users fall into roles that are checked on a great majority of the pages they visit, but not all.
All of those steps are performed, every time I need to authorize.
Here is an image of the database just to make it clear:
Is there a way to cache (so that I don't have to constantly query the database) these authorizations for a length of time equivalent to the time from when the check is first performed/cached to the end of the semester?
Or just cache them at all for any amount of time that's reasonable?
Ideally, if a semester or position is updated for whatever reason, the authorizations would somehow be made invalid and re-cached.
Lastly, is a custom RoleProvider a solid way to go about this?
Is there a way to cache (so that I don't have to constantly query the
database) these authorizations for a length of time equivalent to the
time from when the check is first performed/cached to the end of the
semester?
By default, ASP.Net Identity stores user's authorized roles inside Role Claim after user successful login. Those claims are stored inside cookie until user logout or close the browser.
It is not worth implementing additional caching for authorize attribute.
I'd be careful of caching the authorization, itself. You want to remain flexible with that, and without careful design, you can easily poke security holes in your application.
However, the queries you're making to get the information that is used to make the authorized determination could be potentially cached. For that, I'd recommend using MemoryCache. Simply:
ObjectCache cache = MemoryCache.Default;
...
var foos = cache.Get("key") as List<Foo>;
if (foos == null)
{
foos = repo.GetFoos();
cache.Add("key", foos, new CacheItemPolicy
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
});
}
// do something with `foos`
That's basically how it works, but in an environment like the web, you need to think about concurrency. I wrote a post on my blog that provides an extension to make handling this a lot easier.

How to remove specific session in asp.net?

I am facing a problem. I have created two sessions:
Session["userid"] = UserTbl.userid;
Session["userType"] = UserTbl.type;
I know how to remove sessions using Session.clear(). I want to remove the session "userType".
How do I remove a specific session?
Session.Remove("name of your session here");
There is nothing like session container , so you can set it as null
but rather you can set individual session element as null or ""
like Session["userid"] = null;
you can use Session.Remove() method; Session.Remove
Session.Remove("yourSessionName");
There are many ways to nullify session in ASP.NET. Session in essence is a cookie, set on client's browser and in ASP.NET, its name is usually ASP.NET_SessionId. So, theoretically if you delete that cookie (which in terms of browser means that you set its expiration date to some date in past, because cookies can't be deleted by developers), then you loose the session in server. Another way as you said is to use Session.Clear() method. But the best way is to set another irrelevant object (usually null value) in the session in correspondance to a key. For example, to nullify Session["FirstName"], simply set it to Session["FirstName"] = null.
HttpContext.Current.Session.Remove("sessionname");
it works for me
A single way to remove sessions is setting it to null;
Session["your_session"] = null;

Passing parameters to Controller ..but NOT on the URL

Is there a way to pass a parameter to a controller without putting it on the URL?
For example,
http://www.winepassionate.com/p/19/wine-chianti-docg-la-moto
has the value 19 on the URL. If you actually change that value to another, the page displays a different record even it the page name remains the same.
So I would like to NOT pass the ID on the URL but still be able to pass that to the Controller.
What's the recommended way to do so?
You can do a post and send it as a form parameter. I do not recommend this. Posts should be for requests that modify data. In this case you're most likely looking just to get that data. The fact that the id is in the URL is a good thing (see the Stack Overflow URLs for reference). If you really don't want the user to be able to modify it (I hope it's not because you think this makes it more secure, because it doesn't), you could do some simple encryption on it to make it more difficult to guess/produce a valid ID.
Using TempData, as some other suggest, is not a robust solution. It won't work for links on a page, just a GET after POST, and then only once since TempData is deleted after the next request.
Well, you have a couple of options:
Is this a form post? If so, then you can simply add a specific key value pair to your form when you submit it and then data will be passed along.
Is the URL unique to that resource? i.e. Does "Wine-chianti-docg-la-moto" exist as a unique representation of the number 19 in a database somewhere? If so, then you can simply do a lookup of that route component in your database to retrieve the value you need (or push that logic all the way down to the database).
Is that a value that is not expected to change a bunch? You can set that value in Session or in a cookie that would be persisted across pages and then pull it from the respective collection.
Are you redirecting to this page from another request on your server? If so, then you can use TempData to store this temporary value. However, I would recommend against this approach, as it is very transient and not good practice imo.
Lastly, you can obscure the value on the URL if you dont want it to be easily user editable. Encrypt it with some algorithm, and then decrypt it on the destination page. The user will be unlikely to be able to alter the ID by typing in a different value in the URL.
If the page is a GET, and you are following the PRG like you should be (Post-Redirect-Get) then you can use TempData["dataName"] = value; in your [HttpPost] controller and then consume it in your [HttpGet] method. It really depends on how the page is being called.
However, there is nothing wrong in letting the user change that number if it is not security related, and is common practice to show non-vital information in the url like that.
You should use TempData in this case. A good read on this can be found on this blog.
TempData allows you to store a value temporarily between requests and is, by default, erased after being accessed.
// TempData samplepublic ActionResult Featured(){ var featuredProduct = new Product { Name = "Assorted Cupcakes", Description = "Delectable vanilla and chocolate cupcakes", CreationDate = DateTime.Today, ExpirationDate = DateTime.Today.AddDays(7), ImageName = "cupcakes.jpg", Price = 5.99M, QtyOnHand = 12 };

Limit user to filling out form only once

I'm looking to create a simple web form, and I would like to "discourage" users from filling a form out multiple times. The metrics of the form are used for statistical analysis, and each time a user fills out and resubmits the form, the result set usually changes, and hence analysis.
While we don't want to BLOCK re-trys (knowing that a re-try was done is also valuable information), we do want to warn users: "Hey, it looks like you filled this out recently. Are you sure you want to fill it out again?"
The caveat here is that we want to minimize the amount of personably identifiable information collected.
Is storing a cookie with the clients IP the best/simpliest way to do this? Or is there a simple method for caching an IP server-side for xx amount of time so we can run a comparison to says "hey, I think this guy tried to access me earlier today. I should present a warning".
Cookie with constant value should be enough, not even IP. If user did not cleared cookies you'd know that the user already filled out the form.
On easy solution I've used before is to put an invisible timestamp in the HTML form the user fills out. If you get submitted the same timestamp twice, you know its a re-submittion.
If you're worried about tampering, you can always mix up/encrypt the timestamp.
This could also just be a random unique identifier, I chose a timestamp in order to know how long a user took filling out a form (roughly).
This is basically like a session cookie, but might be considered more "private" as theres nothing for a client's computer to remember so it can't be used as like some tracking cookies ad sites.
The downside is that this method requires that a client/proxy not cache the form as it "changes" every request.
There are two issues here the user clicking the submit button multiple times, and the user filling in the form at another point in time.
For the second I can see two quite simple solutions would recommend a session cookie, just cookie the users machine and don't let them see the form again, or ask for a piece of information like email address and then check in the DB if its been used before, if so disregard the new form details.
For the multiple form submit you can use this code, which will disable the button onclick.
//
// Disable button with no secondary JavaScript function call.
//
public static void DisableButtonOnClick(Button ButtonControl)
{
DisableButtonOnClick(ButtonControl, string.Empty);
}
// Disable button with a JavaScript function call.
//
public static void DisableButtonOnClick(Button ButtonControl, string ClientFunction)
{
var sb = new StringBuilder(128);
// If the page has ASP.NET validators on it, this code ensures the
// page validates before continuing.
sb.Append("if ( typeof( Page_ClientValidate ) == 'function' ) { ");
sb.Append("if ( ! Page_ClientValidate() ) { return false; } } ");
// Disable this button.
sb.Append("this.disabled = true;");
// If a secondary JavaScript function has been provided, and if it can be found,
// call it. Note the name of the JavaScript function to call should be passed without
// parens.
if (!String.IsNullOrEmpty(ClientFunction))
{
sb.AppendFormat("if ( typeof( {0} ) == 'function' ) {{ {0}() }};", ClientFunction);
}
// GetPostBackEventReference() obtains a reference to a client-side script function
// that causes the server to post back to the page (ie this causes the server-side part
// of the "click" to be performed).
sb.Append(ButtonControl.Page.GetPostBackEventReference(ButtonControl) + ";");
// Add the JavaScript created a code to be executed when the button is clicked.
ButtonControl.Attributes.Add("onclick", sb.ToString());
}

Categories