Make Cache object expire at midnight - asp.net

I have the following code:
var tempList = new BrandCollection();
if (HttpContext.Current.Cache["cachedDeviceList"] == null)
{
tempList = Provider.GetDeviceData(info);
HttpContext.Current.Cache.Insert(...);
}
else
{
tempList =
}
Cache.Insert() method is overloaded where I can set the dependencies, sliding and absolute expiration. I want to make the Cache expire at midnight. How do I do that? Thank in advance!

Absolute expiration is the way to do this - it's shorthand for 'this expires at an absolute point in time' as opposed to 'in twenty minutes from now'. So when you put an item into the cache, you need to calculate when midnight will be and then use that as the expiration point e.g.
var tempList = new BrandCollection();
if (HttpContext.Current.Cache["cachedDeviceList"] == null)
{
tempList = Provider.GetDeviceData(info);
// Find out when midnight will be by taking Today and adding a day to it
DateTime expirationTime = DateTime.Today.AddDays(1)
HttpContext.Current.Cache.Insert("cachedDeviceList", tempList, null, expirationTime, NoSlidingExpiration, CacheItemPriority.Normal, null);
}
else
{
...
}

Related

redirect chrome users in new window

I have tried this but its not what I want ....
also this code does not works
<%= Html.ActionLink("Paypal", "HowItWorksRedirect", null, new { #class = "Paypal" })%>
public ActionResult HowItWorksRedirect()
{
return Redirect("https://www.paypal-deutschland.de/sicherheit/schutzprogramme.html");
}
I want to redirect all chrome users to new window
I want to keep users on my website but also redirect them to new window... (600x800 or something like this)
How can I do that?
Opening a new window (or tab, depending on browser settings) is easy:
With a link, you can use
LINK
Or you can use JS:
window.open('http://google.com', 'Google', 'width=800, height=600');
With the help of navigator.userAgent you can get the User Agent and use a regex to find out if the user is using Chrome
if(/Chrome/.test(navigator.userAgent)) { /* CHROME USER */ }
<script>
//specify page to pop-under
var popunder="http://wow.ge/"
//specify popunder window features
//set 1 to enable a particular feature, 0 to disable
var winfeatures="width=800,height=510,scrollbars=1,resizable=1,toolbar=1,location=1,menubar=1,status=1,directories=0"
//Pop-under only once per browser session? (0=no, 1=yes)
//Specifying 0 will cause popunder to load every time page is loaded
var once_per_session=0
///No editing beyond here required/////
function get_cookie(Name) {
var search = Name + "="
var returnvalue = "";
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search)
if (offset != -1) { // if cookie exists
offset += search.length
// set index of beginning of value
end = document.cookie.indexOf(";", offset);
// set index of end of cookie value
if (end == -1)
end = document.cookie.length;
returnvalue=unescape(document.cookie.substring(offset, end))
}
}
return returnvalue;
}
function loadornot(){
if (get_cookie('popunder')==''){
loadpopunder()
document.cookie="popunder=yes"
}
}
function loadpopunder(){
win2=window.open(popunder,"",winfeatures)
win2.blur()
window.focus()
}
if (once_per_session==0)
loadpopunder()
else
loadornot()
</script>
but browsers blocking that !

Session Variables and List Object not Updating Correctly

I should be able to figure this out, but I've been fighting with it for quite a while now.
I have a popup page that has several available requests that a user can select from. Based upon the page that the user is accessing, there could be one request or multiple requests available for that user. The single and multiple request are both saved on different session variables.
I need to know the single request that the user selected at the beginning of the process. It works fine except when the user is allowed to add multiple requests, the single request session variable is also updated.
For example, single request variable has "Florida"; then, the user reaches the multiple request page and adds GA and LA to the multiple request session variable. The single request variable is also updated to include GA and LA even though the flag is false and never reached that line. I don't want it to be updated. I need that single request to be available at all the time, so the user can see it if and when requested.
Here is a sample code where the issue is happening:
List<Request> temp = new List<Request>();
List<Request> mySearchRequest = new List<Request>();
List<Request> listSingleRequest = new List<Request>();
if (SessionWrapper.currentRequest.AvailableRequests != null)
{
mySearchRequest = (List<Request>)SessionWrapper.currentRequest.AvailableRequests;
}
if (SessionWrapper.currentRequest.MultipleRequests != null)
{
temp = (List<Request>)SessionWrapper.currentRequest.MultipleRequests;
var test = temp.Find(delegate(Request req) { return req.RequestId == id && req.Desc == description; });
// Checking if we have on the container already
if (mySearchRequest.Any(r => r.RequestId == id && r.Desc == description) == false)
{
mySearchRequest.Add(test);
if (SessionWrapper.currentRequest.SingleRequest == true && mySearchRequest.Count() == 1)
{
listSingleRequest.Add(test);
SessionWrapper.currentRequest.singleRequest = listSingleRequest ;
listSingleRequest = null;
}
}
}
//Set multiple request session here
Your help is greatly appreciated.
Thanks,
JF
After playing around with it almost all night, I was able to fix it. I am not sure if that is the most efficient way of doing it, but it works for now.
if (SessionWrapper.currentRequest.MultipleRequests != null)
{
temp = (List<Request>)SessionWrapper.currentRequest.MultipleRequests;
var test = temp.Find(delegate(Request req) { return req.RequestId == id && req.Desc == description; });
// Checking if we have on the container already
if (mySearchRequest.Any(r => r.RequestId == id && r.Desc == description) == false)
{
mySearchRequest.Add(test);
if (SessionWrapper.currentRequest.SingleRequestPage == true && mySearchRequest.Count() == 1)
{
foreach (var item in test)
{
//Create a new request object and add it to the list
Request request = new Request();
request.RequestId == item.RequestId;
request.Description == item.Description;
listSingleRequest.Add(request);
}
SessionWrapper.currentRequest.singleRequest = listSingleRequest ;
listSingleRequest = null;
}
}
}
if (SessionWrapper.currentRequest.singleRequest != null)
{
tempRequest = SessionWrapper.currentRequest.singleRequest.ToList();
foreach (var test in tempRequest)
{
Request request = new Request();
request.RequestId == item.RequestId;
request.Description == item.Description;
listSingleRequest.Add(request);
}
SessionWrapper.currentRequest.ViewRequest = listSingleRequest;
listSingleRequest = null;
}

Application Cache and Slow Process

I want to create an application wide feed on my ASP.net 3.5 web site using the application cache. The data that I am using to populate the cache is slow to obtain, maybe up to 10 seconds (from a remote server's data feed). My question/confusion is, what is the best way to structure the cache management.
private const string CacheKey = "MyCachedString";
private static string lockString = "";
public string GetCachedString()
{
string data = (string)Cache[CacheKey];
string newData = "";
if (data == null)
{
// A - Should this method call go here?
newData = SlowResourceMethod();
lock (lockString)
{
data = (string)Cache[CacheKey];
if (data != null)
{
return data;
}
// B - Or here, within the lock?
newData = SlowResourceMethod();
Cache[CacheKey] = data = newData;
}
}
return data;
}
The actual method would be presented by and HttpHandler (.ashx).
If I collect the data at point 'A', I keep the lock time short, but might end up calling the external resource many times (from web pages all trying to reference the feed). If I put it at point 'B', the lock time will be long, which I am assuming is a bad thing.
What is the best approach, or is there a better pattern that I could use?
Any advice would be appreciated.
I add the comments on the code.
private const string CacheKey = "MyCachedString";
private static readonly object syncLock = new object();
public string GetCachedString()
{
string data = (string)Cache[CacheKey];
string newData = "";
// start to check if you have it on cache
if (data == null)
{
// A - Should this method call go here?
// absolut not here
// newData = SlowResourceMethod();
// we are now here and wait for someone else to make it or not
lock (syncLock)
{
// now lets see if some one else make it...
data = (string)Cache[CacheKey];
// we have it, send it
if (data != null)
{
return data;
}
// not have it, now is the time to look for it.
// B - Or here, within the lock?
newData = SlowResourceMethod();
// set it on cache
Cache[CacheKey] = data = newData;
}
}
return data;
}
Better for me is to use mutex and lock depended on the name CacheKey and not lock all resource and the non relative one. With mutex one basic simple example will be:
private const string CacheKey = "MyCachedString";
public string GetCachedString()
{
string data = (string)Cache[CacheKey];
string newData = "";
// start to check if you have it on cache
if (data == null)
{
// lock it base on resource key
// (note that not all chars are valid for name)
var mut = new Mutex(true, CacheKey);
try
{
// Wait until it is safe to enter.
// but also add 30 seconds max
mut.WaitOne(30000);
// now lets see if some one else make it...
data = (string)Cache[CacheKey];
// we have it, send it
if (data != null)
{
return data;
}
// not have it, now is the time to look for it.
// B - Or here, within the lock?
newData = SlowResourceMethod();
// set it on cache
Cache[CacheKey] = data = newData;
}
finally
{
// Release the Mutex.
mut.ReleaseMutex();
}
}
return data;
}
You can also read
Image caching issue by using files in ASP.NET

DevExpress XtraScheduler hanging on adding appointment to Storage

I have a XtraScheduler SchedulerControl configured as the following:
private DevExpress.XtraScheduler.SchedulerControl _SchedulerControl;
public DevExpress.XtraScheduler.SchedulerControl ConvSchedulerControl
{
get
{
if (_SchedulerControl == null)
{
_SchedulerControl = new DevExpress.XtraScheduler.SchedulerControl();
_SchedulerControl.Storage = new SchedulerStorage();
_SchedulerControl.Storage.Appointments.Mappings.Subject = "StandingOrderIDString";
_SchedulerControl.Storage.Appointments.Mappings.Start = "ScheduledDate";
_SchedulerControl.Storage.Appointments.Mappings.RecurrenceInfo = "RecurrenceInfo";
_SchedulerControl.Storage.Appointments.Mappings.Type = "Type";
_SchedulerControl.Storage.Appointments.CustomFieldMappings.Add(new DevExpress.XtraScheduler.AppointmentCustomFieldMapping("Inactive", "Inactive"));
_SchedulerControl.Storage.Appointments.CustomFieldMappings.Add(new DevExpress.XtraScheduler.AppointmentCustomFieldMapping("StandingOrderKEY", "StandingOrderKEY"));
BindingSource bs = new BindingSource();
bs.DataSource = new List<StandingOrder>();
_SchedulerControl.Storage.Appointments.DataSource = bs;
}
return _SchedulerControl;
}
}
and I am attempting to programmatically add an appointment with recurrence information, as in the examples given at http://help.devexpress.com/#WindowsForms/CustomDocument6201 . However, when the method execution reaches its final line (indicated) that adds the created appointment to the storage, it "hangs." No exception is ever thrown; I have left it running for upwards of 15 minutes with no change:
public void SetRecurrence(DateTime startDate, DateTime? endDate)
{
Appointment appointmentObj = ConvSchedulerControl.Storage.CreateAppointment(AppointmentType.Pattern);
if (endDate != null &&
endDate != DateTime.Parse("12/31/2999"))
{
appointmentObj.End = (DateTime)endDate;
}
else
{
appointmentObj.RecurrenceInfo.Range = RecurrenceRange.NoEndDate;
}
appointmentObj.Start = startDate;
appointmentObj.RecurrenceInfo.Type = RecurrenceType.Weekly;
appointmentObj.RecurrenceInfo.WeekDays = WeekDays.Monday;
appointmentObj.AllDay = true;
//Program execution reaches this line, but never proceeds past it.
ConvSchedulerControl.Storage.Appointments.Add(appointmentObj);
}
I would imagine that there's something wrong with the configuration that's preventing the storage from being able to successfully add the appointment, but I've been unable to turn up any other information on the subject. Does anyone know why this method isn't appropriate for adding an appointment to the storage, and how it can be corrected?
You've failed to provide a mapping for the 'End' field. This is a required mapping. Honestly, I only know this from having created a calendar in the designer. When you place a SchedulerControl onto a form/control, one of the things the designer gives you is a "Mappings Wizard". The 'Start' and 'End' fields are marked in the wizard as being required.

ASP.net Cache Absolute Expiration not working

I am storing a single integer value in HttpContext.Cache with an absolute expiration time of 5 minutes from now. However, after waiting 6 minutes (or longer), the integer value is still in the Cache (i.e. it's never removed even though the absolute expiration has passed). Here is the code I am using:
public void UpdateCountFor(string remoteIp)
{
// only returns true the first time its run
// after that the value is still in the Cache
// even after the absolute expiration has passed
// so after that this keeps returning false
if (HttpContext.Current.Cache[remoteIp] == null)
{
// nothing for this ip in the cache so add the ip as a key with a value of 1
var expireDate = DateTime.Now.AddMinutes(5);
// I also tried:
// var expireDate = DateTime.UtcNow.AddMinutes(5);
// and that did not work either.
HttpContext.Current.Cache.Insert(remoteIp, 1, null, expireDate, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
}
else
{
// increment the existing value
HttpContext.Current.Cache[remoteIp] = ((int)HttpContext.Current.Cache[remoteIp]) + 1;
}
}
The first time I run UpdateCountFor("127.0.0.1") it inserts 1 into the cache with key "127.0.0.1" and an absolute expiration of 5 minutes from now as expected. Every subsequent run then increments the value in the cache. However, after waiting 10 minutes it continues to increment the value in the Cache. The value never expires and never gets removed from the Cache. Why is that?
It's my understanding that an absolute expiration time means the item will get removed approximately at that time. Am I doing something wrong? Am I misunderstanding something?
I'm expecting the value to be removed from the Cache after 5 minutes time, however it stays in there until I rebuild the project.
This is all running on .NET 4.0 on my local machine.
It turns out that this line:
HttpContext.Current.Cache[remoteIp] = ((int)HttpContext.Current.Cache[remoteIp]) + 1;
removes the previous value and re-inserts the value with NO absolute or sliding expiration time. In order to get around this I had to create a helper class and use it like so:
public class IncrementingCacheCounter
{
public int Count;
public DateTime ExpireDate;
}
public void UpdateCountFor(string remoteIp)
{
IncrementingCacheCounter counter = null;
if (HttpContext.Current.Cache[remoteIp] == null)
{
var expireDate = DateTime.Now.AddMinutes(5);
counter = new IncrementingCacheCounter { Count = 1, ExpireDate = expireDate };
}
else
{
counter = (IncrementingCacheCounter)HttpContext.Current.Cache[remoteIp];
counter.Count++;
}
HttpContext.Current.Cache.Insert(remoteIp, counter, null, counter.ExpireDate, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
}
This will get around the issue and let the counter properly expire at the absolute time while still enabling updates to it.
Try using DateTime.UtcNow to calculate your timeout period instead of datetime.Now . You may be running into the issue described below:
absoluteExpiration Type:
System.DateTime The time at which the
inserted object expires and is removed
from the cache. To avoid possible
issues with local time such as changes
from standard time to daylight saving
time, use UtcNow rather than Now for
this parameter value. If you are using
absolute expiration, the
slidingExpiration parameter must be
NoSlidingExpiration.
There's a simpler answer than what smoak posted. Using that example as a starting point, the updated code below works and doesn't require a re-insert. The reason this works is because classes are reference types. Thus, when you update the counter inside the class instance it doesn't cause the cache to trigger an update.
public class IncrementingCacheCounter
{
public int Count;
}
public void UpdateCountFor(string remoteIp)
{
IncrementingCacheCounter counter = null;
if (HttpContext.Current.Cache[remoteIp] == null)
{
counter = new IncrementingCacheCounter { Count = 1};
HttpContext.Current.Cache.Insert(remoteIp, counter, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
}
else
{
counter = (IncrementingCacheCounter)HttpContext.Current.Cache[remoteIp];
counter.Count++;
}
}

Resources