Skip to content

Commit db44627

Browse files
committed
Merge pull request #138 from filipw/bugfix/103
Fix IHttpActionResult and related changes
2 parents d705000 + 9609017 commit db44627

6 files changed

Lines changed: 57 additions & 11 deletions

File tree

src/WebApi.OutputCache.Core/Cache/IApiOutputCache.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ namespace WebApi.OutputCache.Core.Cache
66
public interface IApiOutputCache
77
{
88
void RemoveStartsWith(string key);
9+
910
T Get<T>(string key) where T : class;
11+
12+
[Obsolete("Use Get<T> instead")]
1013
object Get(string key);
14+
1115
void Remove(string key);
16+
1217
bool Contains(string key);
18+
1319
void Add(string key, object o, DateTimeOffset expiration, string dependsOnKey = null);
20+
1421
IEnumerable<string> AllKeys { get; }
1522
}
1623
}

src/WebApi.OutputCache.Core/Cache/MemoryCacheDefault.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public T Get<T>(string key) where T : class
2323
return o;
2424
}
2525

26+
[Obsolete("Use Get<T> instead")]
2627
public object Get(string key)
2728
{
2829
return Cache.Get(key);

src/WebApi.OutputCache.V2/AutoInvalidateCacheOutputAttribute.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ public override void OnActionExecuted(HttpActionExecutedContext actionExecutedCo
2020
if (actionExecutedContext.Response != null && !actionExecutedContext.Response.IsSuccessStatusCode) return;
2121
if (actionExecutedContext.ActionContext.Request.Method != HttpMethod.Post &&
2222
actionExecutedContext.ActionContext.Request.Method != HttpMethod.Put &&
23-
actionExecutedContext.ActionContext.Request.Method != HttpMethod.Delete) return;
23+
actionExecutedContext.ActionContext.Request.Method != HttpMethod.Delete &&
24+
actionExecutedContext.ActionContext.Request.Method.Method.ToLower() != "patch" &&
25+
actionExecutedContext.ActionContext.Request.Method.Method.ToLower() != "merge") return;
2426

2527
var controller = actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor;
2628
var actions = FindAllGetMethods(controller.ControllerType, TryMatchType ? actionExecutedContext.ActionContext.ActionDescriptor.GetParameters() : null);

src/WebApi.OutputCache.V2/CacheOutputAttribute.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,15 @@ protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration co
9999
var negotiator = config.Services.GetService(typeof(IContentNegotiator)) as IContentNegotiator;
100100
var returnType = actionContext.ActionDescriptor.ReturnType;
101101

102-
if (negotiator != null && returnType != typeof(HttpResponseMessage))
102+
if (negotiator != null && returnType != typeof(HttpResponseMessage) && (returnType != typeof(IHttpActionResult) || typeof(IHttpActionResult).IsAssignableFrom(returnType)))
103103
{
104104
var negotiatedResult = negotiator.Negotiate(returnType, actionContext.Request, config.Formatters);
105+
106+
if (negotiatedResult == null)
107+
{
108+
return DefaultMediaType;
109+
}
110+
105111
responseMediaType = negotiatedResult.MediaType;
106112
if (string.IsNullOrWhiteSpace(responseMediaType.CharSet))
107113
{
@@ -113,8 +119,7 @@ protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration co
113119
if (actionContext.Request.Headers.Accept != null)
114120
{
115121
responseMediaType = actionContext.Request.Headers.Accept.FirstOrDefault();
116-
if (responseMediaType == null ||
117-
!config.Formatters.Any(x => x.SupportedMediaTypes.Contains(responseMediaType)))
122+
if (responseMediaType == null || !config.Formatters.Any(x => x.SupportedMediaTypes.Contains(responseMediaType)))
118123
{
119124
return DefaultMediaType;
120125
}
@@ -145,7 +150,7 @@ public override void OnActionExecuting(HttpActionContext actionContext)
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);

test/WebApi.OutputCache.V2.Tests/ServerSideTests.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public void no_caching_if_user_authenticated_and_flag_set_to_off()
237237
public void etag_match_304_if_none_match()
238238
{
239239
_cache.Setup(x => x.Contains(It.Is<string>(i => i.Contains("etag_match_304")))).Returns(true);
240-
_cache.Setup(x => x.Get(It.Is<string>(i => i.Contains("etag_match_304") && i.Contains(Constants.EtagKey))))
240+
_cache.Setup(x => x.Get<string>(It.Is<string>(i => i.Contains("etag_match_304") && i.Contains(Constants.EtagKey))))
241241
.Returns(@"""abc""");
242242

243243
var client = new HttpClient(_server);
@@ -254,8 +254,9 @@ public void etag_match_304_if_none_match()
254254
public void etag_not_match_304_if_none_match()
255255
{
256256
_cache.Setup(x => x.Contains(It.Is<string>(i => i.Contains("etag_match_304")))).Returns(true);
257-
_cache.Setup(x => x.Get(It.Is<string>(i => i.Contains("etag_match_304") && i.Contains(Constants.EtagKey))))
258-
.Returns((object)new EntityTagHeaderValue(@"""abcdef"""));
257+
_cache.Setup(x => x.Get<byte[]>(It.IsAny<string>())).Returns((byte[])null);
258+
_cache.Setup(x => x.Get<string>(It.Is<string>(i => i.Contains("etag_match_304") && i.Contains(Constants.EtagKey))))
259+
.Returns(@"""abcdef""");
259260

260261
var client = new HttpClient(_server);
261262
var req = new HttpRequestMessage(HttpMethod.Get, _url + "etag_match_304");
@@ -267,6 +268,30 @@ public void etag_not_match_304_if_none_match()
267268
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
268269
}
269270

271+
[Test]
272+
public void can_handle_ihttpactionresult_with_default_media_type()
273+
{
274+
var client = new HttpClient(_server);
275+
var result = client.GetAsync(_url + "Get_ihttpactionresult").Result;
276+
277+
_cache.Verify(s => s.Contains(It.Is<string>(x => x == "sample-get_ihttpactionresult:application/json; charset=utf-8")), Times.Exactly(2));
278+
_cache.Verify(s => s.Add(It.Is<string>(x => x == "sample-get_ihttpactionresult"), It.IsAny<object>(), It.Is<DateTimeOffset>(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once());
279+
_cache.Verify(s => s.Add(It.Is<string>(x => x == "sample-get_ihttpactionresult:application/json; charset=utf-8"), It.IsAny<object>(), It.Is<DateTimeOffset>(x => x <= DateTime.Now.AddSeconds(100)), It.Is<string>(x => x == "sample-get_ihttpactionresult")), Times.Once());
280+
}
281+
282+
[Test]
283+
public void can_handle_ihttpactionresult_with_non_default_media_type()
284+
{
285+
var client = new HttpClient(_server);
286+
var req = new HttpRequestMessage(HttpMethod.Get, _url + "Get_ihttpactionresult");
287+
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
288+
var result = client.SendAsync(req).Result;
289+
290+
_cache.Verify(s => s.Contains(It.Is<string>(x => x == "sample-get_ihttpactionresult:text/xml; charset=utf-8")), Times.Exactly(2));
291+
_cache.Verify(s => s.Add(It.Is<string>(x => x == "sample-get_ihttpactionresult"), It.IsAny<object>(), It.Is<DateTimeOffset>(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once());
292+
_cache.Verify(s => s.Add(It.Is<string>(x => x == "sample-get_ihttpactionresult:text/xml; charset=utf-8"), It.IsAny<object>(), It.Is<DateTimeOffset>(x => x <= DateTime.Now.AddSeconds(100)), It.Is<string>(x => x == "sample-get_ihttpactionresult")), Times.Once());
293+
}
294+
270295

271296
//[Test]
272297
//public void must_add_querystring_to_cache_params()

test/WebApi.OutputCache.V2.Tests/TestControllers/SampleController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,11 @@ public void Post_2_invalidates()
146146
{
147147
//do nothing
148148
}
149+
150+
[CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)]
151+
public IHttpActionResult Get_ihttpactionresult()
152+
{
153+
return Ok("value");
154+
}
149155
}
150156
}

0 commit comments

Comments
 (0)