Asked by:
.NET Framework 4.7 breaking Web Forms Page Cache

Question
-
User-227976983 posted
In an ASP.NET webforms context (FYI - .NET Framework 4.5.1 project), the following code works when .NET Framework 4.7 is not installed. But when Framework 4.7 is installed (which came out today), I get a NullReference exception.
public class Default : System.Web.UI.Page { protected override void OnInit(EventArgs e) { string key = "key", data = "data"; Cache.Insert(key, data, null, DateTime.Now.AddMinutes(5), TimeSpan.Zero); Cache[key].ToString(); // Throws NRE when 4.7 installed } }
After debugging I've determined the item is being added to the cache and then immediately deleted. I found two workarounds:
1. Web.config
<system.web> ... <caching> <cache disableExpiration="true"/> </caching> ... </system.web>
2. Change insert statement to this
Cache.Insert(key, data, null, DateTime.Now.AddMinutes(5), TimeSpan.Zero, CacheItemPriority.Normal, (key,value,removal)=> { });
I'm very confused as to what I'm doing wrong in my first cache statement that works fine before installing v4.7. Is this a bug?
Thanks,
Fungus Man
Friday, June 16, 2017 12:33 AM
All replies
-
User-158764254 posted
you're using conflicting arguments. When using an absolute expiration you should not use a timespan.zero.
instead try this:
Cache.Insert(key, data, null, DateTime.Now.AddMinutes(5), System.Web.Caching.Cache.NoSlidingExpiration);
https://msdn.microsoft.com/en-us/library/4y13wyk9(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.web.caching.cache.noslidingexpiration(v=vs.110).aspx
Friday, June 16, 2017 1:33 AM -
User-227976983 posted
Hi
Thanks for your response. Tried that - exact same result. Item not being held in cache. Now Im convinced there is a bug with that insert method in .net 4.7.
Friday, June 16, 2017 9:20 AM -
User-227976983 posted
Actually this is a serious issue - how can I report this bug to microsoft and how long would it take to get it fixed? I dont want to use that web.config setting and Im not sure rewriting my code is use another method is appropriate.
Friday, June 16, 2017 9:27 AM -
User475983607 posted
Actually this is a serious issue - how can I report this bug to microsoft and how long would it take to get it fixed? I dont want to use that web.config setting and Im not sure rewriting my code is use another method is appropriate.
Your code does not wok in 4.6 either. However, mbanavige's suggestion does work which I verified.
Friday, June 16, 2017 10:00 AM -
User-227976983 posted
Thanks mgebhard - I am not sure if you caught my note in my original question: project Target framework isn't 4.7, its actually 4.5.1. All I did was install 4.7 on two servers and my workstation and neither mbanavige's nor my original code works. Its strange that the other functions accept my parameters too...
Can you, or anyone, please test the scenario I mentioned? Maybe there is a set up issue on my side.
Friday, June 16, 2017 4:10 PM -
User753101303 posted
Hi,
And what if you try :
Cache.Insert(key, data, null, DateTime.UtcNow.AddMinutes(5), System.Web.Caching.Cache.NoSlidingExpiration);
Friday, June 16, 2017 4:46 PM -
User475983607 posted
ahmad.fungus
Thanks mgebhard - I am not sure if you caught my note in my original question: project Target framework isn't 4.7, its actually 4.5.1. All I did was install 4.7 on two servers and my workstation and neither mbanavige's nor my original code works. Its strange that the other functions accept my parameters too...
Can you, or anyone, please test the scenario I mentioned? Maybe there is a set up issue on my side.
I have 4.7 installed and cannot reproduce this issue. I can only reproduce the bug if I target a framework 4.6+. I suspect there might be other issues in the code base.
Friday, June 16, 2017 5:19 PM -
User-1084200161 posted
It's a bug in Cache.Insert.. you're not doing anything wrong..
You'd have to use one of the workarounds for now until this is addressed (which should be next release)..
If you can use this overload: Cache.Insert (String, Object, CacheDependency, DateTime, TimeSpan, CacheItemPriority, CacheItemRemovedCallback) -- that one does not have the same bug as the Insert overload you're using.. so that should work too... Docs for this overload https://msdn.microsoft.com/en-us/library/05kd8d77(v=vs.110).aspx
PS. You do not need to report this bug to MSFT.. it's already been reported/noted.
Friday, June 16, 2017 9:37 PM -
User753101303 posted
Just installed 4.7 and on my side it seems to work just fine on my dev machine. Also if using the removal callback I can see it happens roughly when expected.
Saturday, June 17, 2017 10:05 AM -
User-1084200161 posted
Reflect the code in that Cache.Insert overload and you'll spot the problem in about 2 seconds ;) Especially if you then compare it with other Insert overloads that do not have this issue..
Saturday, June 17, 2017 2:15 PM -
User475983607 posted
Reflect the code in that Cache.Insert overload and you'll spot the problem in about 2 seconds ;) Especially if you then compare it with other Insert overloads that do not have this issue..
That's a vague response. Can you elaborate on what you found? Or where the bug is documented?
I looked at the source code it looks like the right version...
https://github.com/Microsoft/referencesource/blob/master/System.Web/Cache/cache.cs
As far as I can tell the mbanavige's answer is correct and documented in the source well as the MS docs.
// // Summary: // Used as the slidingExpiration parameter in an System.Web.Caching.Cache.Insert(System.String,System.Object) // or System.Web.Caching.Cache.Add(System.String,System.Object,System.Web.Caching.CacheDependency,System.DateTime,System.TimeSpan,System.Web.Caching.CacheItemPriority,System.Web.Caching.CacheItemRemovedCallback) // method call to disable sliding expirations. This field is read-only. public static readonly TimeSpan NoSlidingExpiration;
I suppose the method could check if the user passed TimeSpan.Zero then add the NoSlidingExpiration member to the CacheInsertOptions() object rather than the user's argument. That might be a bit more user friendly.
Again. my finding are framework 4.5 is tolerant of TimeSpan.Zero while 4.6+ is not. I have 4.7 installed on my machine which does not affect 4.5 as the OP suggests. If I change the target framework, that does cause a problem using TimeSpan.Zero.
Please explain what I'm missing.
Saturday, June 17, 2017 3:33 PM -
User-1084200161 posted
Line 425 in that reference source you posted is the problem...
Expiration timestamp is converted to UTC, but then they don't use UTC (they mistakenly use original argument into the function)... Line 425 should have had utcAbsoluteExpiration declared on LIne 422... (instead of absoluteExpiration)... and it's an oversight, unfortunately.. this is not documented anywhere (yet).
TimeSpan.Zero vs NoSlidingExpiration is not the issue, because NoSlidingExpiration *is* TimeSpan.Zero :) so it does not matter which one you put in there.. they're same.
Line 182:
public static readonly TimeSpan NoSlidingExpiration = TimeSpan.Zero;
Saturday, June 17, 2017 5:51 PM -
User475983607 posted
Ah, got it... thanks
Saturday, June 17, 2017 6:07 PM -
User1300272511 posted
You are right. Looks like a bug in System.Web/Cache/cache.cs and with new update it is causing issues.
Sunday, June 18, 2017 9:58 PM -
User753101303 posted
I suspected something related and this is why I suggested earlier to pass explicitely UtcNow.AddMinutes(5) in the call and see what happens.
Monday, June 19, 2017 6:52 AM -
User-227976983 posted
Thanks all. I guess its not likely this will be fixed any time soon.. :(
Monday, June 19, 2017 3:57 PM -
User753101303 posted
And you tried/considered using explicitely DateTime.UtcNow.AddMinutes(5) as suggested earlier twice ? It seems to me it would be an easy fix and it doesn't need to be changed back once the underlying bug is fixed.
Monday, June 19, 2017 4:25 PM