moonpyk / mvcdonutcaching

ASP.NET MVC Extensible Donut Caching brings donut caching to ASP.NET MVC 3 and later. The code allows you to cache all of your page apart from one or more Html.Actions which can be executed every request. Perfect for user specific content.
https://github.com/moonpyk/mvcdonutcaching
MIT License
142 stars 50 forks source link

Null reference exception #26

Closed tubededentifrice closed 10 years ago

tubededentifrice commented 10 years ago

It recently appeared, not really sure why. The error is random (impossible to reproduce), so probably it's a race condition or browser related. I'm unable to reproduce the error myself. I got 14 occurences accross only 3 IP, all having "Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)" as user agent and very strange post data (see below). It's not a big issue (nasty spider), but the exception shouldn't be thrown away.

NullReferenceException: Object reference not set to an instance of an object.

1 File "DevTrends.MvcDonutCaching.KeyGenerator" line 220 in GenerateKey(System.Web.Mvc.ControllerContext context, DevTrends.MvcDonutCaching.CacheSettings cacheSettings)
2 File "DevTrends.MvcDonutCaching.DonutOutputCacheAttribute" line 0 in ExecuteCallback(System.Web.Mvc.ControllerContext context, System.Boolean hasErrors)
3 File "System.Web.Mvc.ControllerActionInvoker" line 29 in InvokeExceptionFilters(System.Web.Mvc.ControllerContext controllerContext, System.Collections.Generic.IList`1[System.Web.Mvc.IExceptionFilter] filters, System.Exception exception)
4 File "System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass21" line 693 in <BeginInvokeAction>b__19(System.AsyncCallback asyncCallback, System.Object asyncState)
5 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 38 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
6 File "System.Web.Mvc.Async.AsyncResultWrapper" line 11 in Begin(System.AsyncCallback callback, System.Object state, System.Web.Mvc.Async.BeginInvokeDelegate beginDelegate, System.Web.Mvc.Async.EndInvokeDelegate`1[TResult] endDelegate, System.Object tag, System.Int32 timeout)
7 File "System.Web.Mvc.Async.AsyncControllerActionInvoker" line 199 in BeginInvokeAction(System.Web.Mvc.ControllerContext controllerContext, System.String actionName, System.AsyncCallback callback, System.Object state)
8 File "System.Web.Mvc.Controller" line 33 in <BeginExecuteCore>b__1c(System.AsyncCallback asyncCallback, System.Object asyncState, System.Web.Mvc.Controller+ExecuteCoreState innerState)
9 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncVoid`1" line 0 in CallBeginDelegate(System.AsyncCallback callback, System.Object callbackState)
10 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 38 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
11 File "System.Web.Mvc.Async.AsyncResultWrapper" line 14 in Begin(System.AsyncCallback callback, System.Object callbackState, System.Web.Mvc.Async.BeginInvokeDelegate`1[TState] beginDelegate, System.Web.Mvc.Async.EndInvokeVoidDelegate`1[TState] endDelegate, TState invokeState, System.Object tag, System.Int32 timeout, System.Threading.SynchronizationContext callbackSyncContext)
12 File "System.Web.Mvc.Controller" line 241 in BeginExecuteCore(System.AsyncCallback callback, System.Object state)
13 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 44 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
14 File "System.Web.Mvc.Async.AsyncResultWrapper" line 24 in Begin(System.AsyncCallback callback, System.Object callbackState, System.Web.Mvc.Async.BeginInvokeDelegate`1[TState] beginDelegate, System.Web.Mvc.Async.EndInvokeVoidDelegate`1[TState] endDelegate, TState invokeState, System.Object tag, System.Int32 timeout, System.Threading.SynchronizationContext callbackSyncContext)
15 File "System.Web.Mvc.Controller" line 165 in BeginExecute(System.Web.Routing.RequestContext requestContext, System.AsyncCallback callback, System.Object state)
16 File "System.Web.Mvc.MvcHandler" line 34 in <BeginProcessRequest>b__4(System.AsyncCallback asyncCallback, System.Object asyncState, System.Web.Mvc.MvcHandler+ProcessRequestState innerState)
17 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncVoid`1" line 14 in CallBeginDelegate(System.AsyncCallback callback, System.Object callbackState)
18 File "System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1" line 44 in Begin(System.AsyncCallback callback, System.Object state, System.Int32 timeout)
19 File "System.Web.Mvc.Async.AsyncResultWrapper" line 24 in Begin(System.AsyncCallback callback, System.Object callbackState, System.Web.Mvc.Async.BeginInvokeDelegate`1[TState] beginDelegate, System.Web.Mvc.Async.EndInvokeVoidDelegate`1[TState] endDelegate, TState invokeState, System.Object tag, System.Int32 timeout, System.Threading.SynchronizationContext callbackSyncContext)
20 File "System.Web.Mvc.MvcHandler" line 189 in BeginProcessRequest(System.Web.HttpContextBase httpContext, System.AsyncCallback callback, System.Object state)
21 File "System.Web.HttpApplication+CallHandlerExecutionStep" line 451 in System.Web.HttpApplication.IExecutionStep.Execute
22 File "System.Web.HttpApplication" line 60 in ExecuteStep(System.Web.HttpApplication+IExecutionStep step, System.Boolean& completedSynchronously)
curl --request GET 'https://website.com/page' \
--header 'Content-Length:514' \
--header 'Accept-Language:zh;q=0.9,en;q=0.8' \
--header 'Accept-Encoding:gzip, deflate' \
--header 'Host:website.com' \
--header 'Accept:text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1' \
--header 'User-Agent:Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)' \
--header 'Connection:close' \
--header 'Content-Type:application/x-www-form-urlencoded' \
--header 'Refer:http://website.com/' \
--data '?(??P
H?;j????ÖjuC??=?zh-z?????e???l?????y?d??$??????|???q????~}Z?3[g??9vn@S???n ????/a???8??e?
?
yJF
?t=??9??*?\?(D????QJ????'
anorborg commented 10 years ago

I think I may have had the same issue. I did a pull request #27 .

tubededentifrice commented 10 years ago

I don't think it's the same issue, because you solved a "duplicate key exception" (as you state, btw), but I'm having a "Null reference exception". To be honest I've investigated this because it was only happening with dumb spiders.

anorborg commented 10 years ago

Sorry about that, I didn't read in detail. I actually have gotten the null reference exception too, and it was with a spider. Since it crawls, I assume the issue is probably in the first two lines:

var actionName     = context.RouteData.Values["action"].ToString();
var controllerName = context.RouteData.Values["controller"].ToString();

Spiders tend to break up a url so there may be some cases were an action isn't defined with he request (i.e http://myurlroot.com/somecontroller/someaction exists in a sitemap, a crawler may try http://myurlroot.com/somecontoller and if a default action isn't defined the value may be null in routedata). It would probably be best if the code checked for null on these route values. Short of that though, you could possibly look over your routes and my sure default actions are defined on all of them.

tubededentifrice commented 10 years ago

I think this is a duplicate of https://github.com/moonpyk/mvcdonutcaching/issues/19 (I don't know what #19 is closed since the issue remains). The reported line seems wrong in my stack trace since there is no line 220 in https://github.com/moonpyk/mvcdonutcaching/blob/173519a3d89ef28a09cb2ae45df9a34c4438b716/DevTrends.MvcDonutCaching/KeyGenerator.cs ; and line 43 as reported on issue #19 can't thrown a null reference exception (maybe the line 36? would be fixed with a simple x.Key != null && ...?)

moonpyk commented 10 years ago

I just uploaded a new release candidate of the package on nuget.org