@@ -20,6 +20,7 @@ namespace WebApi.OutputCache.V2
2020 [ AttributeUsage ( AttributeTargets . Method , AllowMultiple = false , Inherited = true ) ]
2121 public class CacheOutputAttribute : ActionFilterAttribute
2222 {
23+ private const string CurrentRequestMediaType = "CacheOutput:CurrentRequestMediaType" ;
2324 protected static MediaTypeHeaderValue DefaultMediaType = new MediaTypeHeaderValue ( "application/json" ) { CharSet = Encoding . UTF8 . HeaderName } ;
2425
2526 /// <summary>
@@ -62,8 +63,6 @@ public class CacheOutputAttribute : ActionFilterAttribute
6263 /// </summary>
6364 public Type CacheKeyGenerator { get ; set ; }
6465
65- private MediaTypeHeaderValue _responseMediaType ;
66-
6766 // cache repository
6867 private IApiOutputCache _webApiCache ;
6968
@@ -100,9 +99,15 @@ protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration co
10099 var negotiator = config . Services . GetService ( typeof ( IContentNegotiator ) ) as IContentNegotiator ;
101100 var returnType = actionContext . ActionDescriptor . ReturnType ;
102101
103- if ( negotiator != null && returnType != typeof ( HttpResponseMessage ) )
102+ if ( negotiator != null && returnType != typeof ( HttpResponseMessage ) && ( returnType != typeof ( IHttpActionResult ) || typeof ( IHttpActionResult ) . IsAssignableFrom ( returnType ) ) )
104103 {
105104 var negotiatedResult = negotiator . Negotiate ( returnType , actionContext . Request , config . Formatters ) ;
105+
106+ if ( negotiatedResult == null )
107+ {
108+ return DefaultMediaType ;
109+ }
110+
106111 responseMediaType = negotiatedResult . MediaType ;
107112 if ( string . IsNullOrWhiteSpace ( responseMediaType . CharSet ) )
108113 {
@@ -114,8 +119,7 @@ protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration co
114119 if ( actionContext . Request . Headers . Accept != null )
115120 {
116121 responseMediaType = actionContext . Request . Headers . Accept . FirstOrDefault ( ) ;
117- if ( responseMediaType == null ||
118- ! config . Formatters . Any ( x => x . SupportedMediaTypes . Contains ( responseMediaType ) ) )
122+ if ( responseMediaType == null || ! config . Formatters . Any ( x => x . SupportedMediaTypes . Contains ( responseMediaType ) ) )
119123 {
120124 return DefaultMediaType ;
121125 }
@@ -138,14 +142,15 @@ public override void OnActionExecuting(HttpActionContext actionContext)
138142
139143 var cacheKeyGenerator = config . CacheOutputConfiguration ( ) . GetCacheKeyGenerator ( actionContext . Request , CacheKeyGenerator ) ;
140144
141- _responseMediaType = GetExpectedMediaType ( config , actionContext ) ;
142- var cachekey = cacheKeyGenerator . MakeCacheKey ( actionContext , _responseMediaType , ExcludeQueryStringFromCacheKey ) ;
145+ var responseMediaType = GetExpectedMediaType ( config , actionContext ) ;
146+ actionContext . Request . Properties [ CurrentRequestMediaType ] = responseMediaType ;
147+ var cachekey = cacheKeyGenerator . MakeCacheKey ( actionContext , responseMediaType , ExcludeQueryStringFromCacheKey ) ;
143148
144149 if ( ! _webApiCache . Contains ( cachekey ) ) return ;
145150
146151 if ( actionContext . Request . Headers . IfNoneMatch != null )
147152 {
148- var etag = _webApiCache . Get ( cachekey + Constants . EtagKey ) as string ;
153+ var etag = _webApiCache . Get < string > ( cachekey + Constants . EtagKey ) ;
149154 if ( etag != null )
150155 {
151156 if ( actionContext . Request . Headers . IfNoneMatch . Any ( x => x . Tag == etag ) )
@@ -159,16 +164,16 @@ public override void OnActionExecuting(HttpActionContext actionContext)
159164 }
160165 }
161166
162- var val = _webApiCache . Get ( cachekey ) as byte [ ] ;
167+ var val = _webApiCache . Get < byte [ ] > ( cachekey ) ;
163168 if ( val == null ) return ;
164169
165- var contenttype = _webApiCache . Get ( cachekey + Constants . ContentTypeKey ) as MediaTypeHeaderValue ?? new MediaTypeHeaderValue ( cachekey . Split ( new [ ] { ':' } , 2 ) [ 1 ] ) ;
170+ var contenttype = _webApiCache . Get < MediaTypeHeaderValue > ( cachekey + Constants . ContentTypeKey ) ?? new MediaTypeHeaderValue ( cachekey . Split ( new [ ] { ':' } , 2 ) [ 1 ] ) ;
166171
167172 actionContext . Response = actionContext . Request . CreateResponse ( ) ;
168173 actionContext . Response . Content = new ByteArrayContent ( val ) ;
169174
170175 actionContext . Response . Content . Headers . ContentType = contenttype ;
171- var responseEtag = _webApiCache . Get ( cachekey + Constants . EtagKey ) as string ;
176+ var responseEtag = _webApiCache . Get < string > ( cachekey + Constants . EtagKey ) ;
172177 if ( responseEtag != null ) SetEtag ( actionContext . Response , responseEtag ) ;
173178
174179 var cacheTime = CacheTimeQuery . Execute ( DateTime . Now ) ;
@@ -184,10 +189,12 @@ public override async Task OnActionExecutedAsync(HttpActionExecutedContext actio
184189 var cacheTime = CacheTimeQuery . Execute ( DateTime . Now ) ;
185190 if ( cacheTime . AbsoluteExpiration > DateTime . Now )
186191 {
187- var config = actionExecutedContext . Request . GetConfiguration ( ) . CacheOutputConfiguration ( ) ;
192+ var httpConfig = actionExecutedContext . Request . GetConfiguration ( ) ;
193+ var config = httpConfig . CacheOutputConfiguration ( ) ;
188194 var cacheKeyGenerator = config . GetCacheKeyGenerator ( actionExecutedContext . Request , CacheKeyGenerator ) ;
189195
190- var cachekey = cacheKeyGenerator . MakeCacheKey ( actionExecutedContext . ActionContext , _responseMediaType , ExcludeQueryStringFromCacheKey ) ;
196+ var responseMediaType = actionExecutedContext . Request . Properties [ CurrentRequestMediaType ] as MediaTypeHeaderValue ?? GetExpectedMediaType ( httpConfig , actionExecutedContext . ActionContext ) ;
197+ var cachekey = cacheKeyGenerator . MakeCacheKey ( actionExecutedContext . ActionContext , responseMediaType , ExcludeQueryStringFromCacheKey ) ;
191198
192199 if ( ! string . IsNullOrWhiteSpace ( cachekey ) && ! ( _webApiCache . Contains ( cachekey ) ) )
193200 {
@@ -197,7 +204,7 @@ public override async Task OnActionExecutedAsync(HttpActionExecutedContext actio
197204
198205 if ( responseContent != null )
199206 {
200- var baseKey = config . MakeBaseCachekey ( actionExecutedContext . ActionContext . ControllerContext . ControllerDescriptor . ControllerName , actionExecutedContext . ActionContext . ActionDescriptor . ActionName ) ;
207+ var baseKey = config . MakeBaseCachekey ( actionExecutedContext . ActionContext . ControllerContext . ControllerDescriptor . ControllerType . FullName , actionExecutedContext . ActionContext . ActionDescriptor . ActionName ) ;
201208 var contentType = responseContent . Headers . ContentType ;
202209 string etag = actionExecutedContext . Response . Headers . ETag . Tag ;
203210 //ConfigureAwait false to avoid deadlocks
0 commit comments