-
Notifications
You must be signed in to change notification settings - Fork 249
Expand file tree
/
Copy pathAutoInvalidateCacheOutputAttribute.cs
More file actions
84 lines (73 loc) · 3.93 KB
/
AutoInvalidateCacheOutputAttribute.cs
File metadata and controls
84 lines (73 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace WebApi.OutputCache.V2
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class AutoInvalidateCacheOutputAttribute : BaseCacheAttribute
{
public bool TryMatchType { get; set; }
public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
{
if (actionExecutedContext.Response != null && !actionExecutedContext.Response.IsSuccessStatusCode) return;
if (actionExecutedContext.ActionContext.Request.Method != HttpMethod.Post &&
actionExecutedContext.ActionContext.Request.Method != HttpMethod.Put &&
actionExecutedContext.ActionContext.Request.Method != HttpMethod.Delete &&
actionExecutedContext.ActionContext.Request.Method.Method.ToLower() != "patch" &&
actionExecutedContext.ActionContext.Request.Method.Method.ToLower() != "merge") return;
var controller = actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor;
var actions = FindAllGetMethods(controller.ControllerType, TryMatchType ? actionExecutedContext.ActionContext.ActionDescriptor.GetParameters() : null);
var config = actionExecutedContext.ActionContext.Request.GetConfiguration();
EnsureCache(config, actionExecutedContext.ActionContext.Request);
foreach (var action in actions)
{
var key = config.CacheOutputConfiguration().MakeBaseCachekey(controller.ControllerType.FullName, action);
if (await WebApiCache.ContainsAsync(key))
{
await WebApiCache.RemoveStartsWithAsync(key);
}
}
}
private static IEnumerable<string> FindAllGetMethods(Type controllerType, IEnumerable<HttpParameterDescriptor> httpParameterDescriptors)
{
var actions = controllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
var filteredActions = actions.Where(x =>
{
if (x.Name.ToLower().StartsWith("get")) return true;
if (x.GetCustomAttributes(typeof(HttpGetAttribute), true).Any()) return true;
return false;
});
if (httpParameterDescriptors != null)
{
var allowedTypes = httpParameterDescriptors.Select(x => x.ParameterType).ToList();
var filteredByType = filteredActions.ToList().Where(x =>
{
if (allowedTypes.Any(s => s == x.ReturnType)) return true;
if (allowedTypes.Any(s => typeof(IEnumerable).IsAssignableFrom(x.ReturnType) && x.ReturnType.GetGenericArguments().Any() && x.ReturnType.GetGenericArguments()[0] == s)) return true;
if (allowedTypes.Any(s => typeof(IEnumerable).IsAssignableFrom(x.ReturnType) && x.ReturnType.GetElementType() == s)) return true;
return false;
});
filteredActions = filteredByType;
}
var projectedActions = filteredActions.Select(x =>
{
var overridenNames = x.GetCustomAttributes(typeof(ActionNameAttribute), false);
if (overridenNames.Any())
{
var first = (ActionNameAttribute)overridenNames.FirstOrDefault();
if (first != null) return first.Name;
}
return x.Name;
});
return projectedActions;
}
}
}