diff --git a/WebAPI.OutputCache.sln b/WebAPI.OutputCache.sln
index 35d14d9..5ede701 100644
--- a/WebAPI.OutputCache.sln
+++ b/WebAPI.OutputCache.sln
@@ -1,10 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi.OutputCache", "src\WebApi.OutputCache\WebApi.OutputCache.csproj", "{4F32DC89-081B-4264-92F8-F3371A088EB4}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi.OutputCache.Tests", "test\WebApi.OutputCache.Tests\WebApi.OutputCache.Tests.csproj", "{C5DFB349-FA13-41A1-9F11-332E88664DF7}"
-EndProject
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{944DCBA5-777A-4BE8-A1A3-1EA0924D8B70}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
@@ -12,8 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{944DCB
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi.OutputCache.Demo", "sample\WebApi.OutputCache.Demo\WebApi.OutputCache.Demo.csproj", "{E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CEA1F6A7-ACA0-4B5B-BEE0-23AEB7E30A7D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{70946FFB-B575-4B2F-A174-3BDD93100097}"
@@ -36,18 +32,6 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {4F32DC89-081B-4264-92F8-F3371A088EB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4F32DC89-081B-4264-92F8-F3371A088EB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4F32DC89-081B-4264-92F8-F3371A088EB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4F32DC89-081B-4264-92F8-F3371A088EB4}.Release|Any CPU.Build.0 = Release|Any CPU
- {C5DFB349-FA13-41A1-9F11-332E88664DF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C5DFB349-FA13-41A1-9F11-332E88664DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C5DFB349-FA13-41A1-9F11-332E88664DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C5DFB349-FA13-41A1-9F11-332E88664DF7}.Release|Any CPU.Build.0 = Release|Any CPU
- {E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05}.Release|Any CPU.Build.0 = Release|Any CPU
{1267460B-C100-48AD-B2E2-9DDE2E40F052}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1267460B-C100-48AD-B2E2-9DDE2E40F052}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1267460B-C100-48AD-B2E2-9DDE2E40F052}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -73,13 +57,10 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {4F32DC89-081B-4264-92F8-F3371A088EB4} = {CEA1F6A7-ACA0-4B5B-BEE0-23AEB7E30A7D}
+ {1267460B-C100-48AD-B2E2-9DDE2E40F052} = {70946FFB-B575-4B2F-A174-3BDD93100097}
{7A6F57F6-38E1-4287-812E-AD7D1025BA5E} = {CEA1F6A7-ACA0-4B5B-BEE0-23AEB7E30A7D}
+ {FC585541-1F28-4D49-BCD9-1A08A90B2C66} = {1644F771-3A1F-40A4-80AA-CDB22B334F1F}
{3E45FA0B-C465-4DE9-9BC3-40A606B73E84} = {CEA1F6A7-ACA0-4B5B-BEE0-23AEB7E30A7D}
- {C5DFB349-FA13-41A1-9F11-332E88664DF7} = {70946FFB-B575-4B2F-A174-3BDD93100097}
- {1267460B-C100-48AD-B2E2-9DDE2E40F052} = {70946FFB-B575-4B2F-A174-3BDD93100097}
{44F519D6-E825-442C-A112-B5C4404EAA44} = {70946FFB-B575-4B2F-A174-3BDD93100097}
- {E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05} = {1644F771-3A1F-40A4-80AA-CDB22B334F1F}
- {FC585541-1F28-4D49-BCD9-1A08A90B2C66} = {1644F771-3A1F-40A4-80AA-CDB22B334F1F}
EndGlobalSection
EndGlobal
diff --git a/WebApi.OutputCache.sln.ide/graph/WebApi.OutputCache.sln.ide b/WebApi.OutputCache.sln.ide/graph/WebApi.OutputCache.sln.ide
deleted file mode 100644
index 4b1badd..0000000
--- a/WebApi.OutputCache.sln.ide/graph/WebApi.OutputCache.sln.ide
+++ /dev/null
@@ -1,3 +0,0 @@
-
- 0001-01-01T00:00:00Z
-
\ No newline at end of file
diff --git a/sample/WebAPI.OutputCache.Demo/Program.cs b/sample/WebAPI.OutputCache.Demo/Program.cs
deleted file mode 100644
index bda8eb7..0000000
--- a/sample/WebAPI.OutputCache.Demo/Program.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Web.Http;
-using System.Web.Http.SelfHost;
-using WebApi.OutputCache.Core.Cache;
-
-namespace WebAPI.OutputCache.Demo
-{
- class Program
- {
- static void Main(string[] args)
- {
- var config = new HttpSelfHostConfiguration("http://localhost:999");
- config.Routes.MapHttpRoute(
- name: "DefaultApi",
- routeTemplate: "api/{controller}/{id}",
- defaults: new { id = RouteParameter.Optional }
- );
- var server = new HttpSelfHostServer(config);
-
- config.CacheOutputConfiguration().RegisterCacheOutputProvider(() => new MemoryCacheDefault());
-
- server.OpenAsync().Wait();
-
- Console.ReadKey();
-
- server.CloseAsync().Wait();
- }
- }
-}
diff --git a/sample/WebAPI.OutputCache.Demo/Properties/AssemblyInfo.cs b/sample/WebAPI.OutputCache.Demo/Properties/AssemblyInfo.cs
deleted file mode 100644
index ef82fc9..0000000
--- a/sample/WebAPI.OutputCache.Demo/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("WebAPI.OutputCache.Demo")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("WebAPI.OutputCache.Demo")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("b8e3c80f-067d-4fc7-a3ec-cf33384ae98d")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/sample/WebAPI.OutputCache.Demo/Team.cs b/sample/WebAPI.OutputCache.Demo/Team.cs
deleted file mode 100644
index 58914f0..0000000
--- a/sample/WebAPI.OutputCache.Demo/Team.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace WebAPI.OutputCache.Demo
-{
- public class Team
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public string League { get; set; }
- }
-}
\ No newline at end of file
diff --git a/sample/WebAPI.OutputCache.Demo/Teams2Controller.cs b/sample/WebAPI.OutputCache.Demo/Teams2Controller.cs
deleted file mode 100644
index f5f1bdc..0000000
--- a/sample/WebAPI.OutputCache.Demo/Teams2Controller.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Tasks;
-using System.Web.Http;
-using WebAPI.OutputCache.TimeAttributes;
-
-namespace WebAPI.OutputCache.Demo
-{
- [AutoInvalidateCacheOutput]
- public class Teams2Controller : ApiController
- {
- private static readonly List Teams = new List
- {
- new Team {Id = 1, League = "NHL", Name = "Leafs"},
- new Team {Id = 2, League = "NHL", Name = "Habs"},
- };
-
- [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
- public IEnumerable Get()
- {
- return Teams;
- }
-
- [CacheOutputUntil(2013, 7, 20)]
- public Team GetById(int id)
- {
- var team = Teams.FirstOrDefault(i => i.Id == id);
- if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
-
- return team;
- }
-
- public void Post(Team value)
- {
- if (!ModelState.IsValid) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
- Teams.Add(value);
- }
-
- public void Put(int id, Team value)
- {
- if (!ModelState.IsValid) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
-
- var team = Teams.FirstOrDefault(i => i.Id == id);
- if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
-
- team.League = value.League;
- team.Name = value.Name;
- }
-
- public void Delete(int id)
- {
- var team = Teams.FirstOrDefault(i => i.Id == id);
- if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
-
- Teams.Remove(team);
- }
- }
-}
diff --git a/sample/WebAPI.OutputCache.Demo/TeamsController.cs b/sample/WebAPI.OutputCache.Demo/TeamsController.cs
deleted file mode 100644
index 1eea4a8..0000000
--- a/sample/WebAPI.OutputCache.Demo/TeamsController.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Tasks;
-using System.Web.Http;
-using WebAPI.OutputCache.TimeAttributes;
-
-namespace WebAPI.OutputCache.Demo
-{
- public class TeamsController : ApiController
- {
- private static readonly List Teams = new List
- {
- new Team {Id = 1, League = "NHL", Name = "Leafs"},
- new Team {Id = 2, League = "NHL", Name = "Habs"},
- };
-
- [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)]
- public IEnumerable Get()
- {
- return Teams;
- }
-
- [CacheOutputUntil(2014, 7, 20)]
- public Team GetById(int id)
- {
- var team = Teams.FirstOrDefault(i => i.Id == id);
- if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
-
- return team;
- }
-
- [InvalidateCacheOutput("Get")]
- public void Post(Team value)
- {
- if (!ModelState.IsValid) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
- Teams.Add(value);
- }
-
- public void Put(int id, Team value)
- {
- if (!ModelState.IsValid) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
-
- var team = Teams.FirstOrDefault(i => i.Id == id);
- if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
-
- team.League = value.League;
- team.Name = value.Name;
-
- var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request);
- cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey((TeamsController t) => t.GetById(0)));
- }
-
- public void Delete(int id)
- {
- var team = Teams.FirstOrDefault(i => i.Id == id);
- if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
-
- Teams.Remove(team);
- }
- }
-}
diff --git a/sample/WebAPI.OutputCache.Demo/WebAPI.OutputCache.Demo.csproj b/sample/WebAPI.OutputCache.Demo/WebAPI.OutputCache.Demo.csproj
deleted file mode 100644
index ca42ec4..0000000
--- a/sample/WebAPI.OutputCache.Demo/WebAPI.OutputCache.Demo.csproj
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {E8DC6A3C-A6BD-44BE-8777-ABD5F05EBD05}
- Exe
- Properties
- WebAPI.OutputCache.Demo
- WebAPI.OutputCache.Demo
- v4.0
- 512
- ..\
- true
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
- ..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll
-
-
-
-
-
- ..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll
-
-
-
- ..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll
-
-
- ..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.20918.0\lib\net40\System.Web.Http.SelfHost.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {3E45FA0B-C465-4DE9-9BC3-40A606B73E84}
- WebApi.OutputCache.Core
-
-
- {4f32dc89-081b-4264-92f8-f3371a088eb4}
- WebApi.OutputCache
-
-
-
-
-
-
\ No newline at end of file
diff --git a/sample/WebAPI.OutputCache.Demo/packages.config b/sample/WebAPI.OutputCache.Demo/packages.config
deleted file mode 100644
index 24e1774..0000000
--- a/sample/WebAPI.OutputCache.Demo/packages.config
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/sample/WebApi.OutputCache.Demo/app.config b/sample/WebApi.OutputCache.Demo/app.config
deleted file mode 100644
index c5e1dae..0000000
--- a/sample/WebApi.OutputCache.Demo/app.config
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/sample/WebApi.OutputCache.V2.Demo/WebApi.OutputCache.V2.Demo.csproj b/sample/WebApi.OutputCache.V2.Demo/WebApi.OutputCache.V2.Demo.csproj
index 5c8516a..d721e9d 100644
--- a/sample/WebApi.OutputCache.V2.Demo/WebApi.OutputCache.V2.Demo.csproj
+++ b/sample/WebApi.OutputCache.V2.Demo/WebApi.OutputCache.V2.Demo.csproj
@@ -46,11 +46,13 @@
..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Net.Http.dll
-
- ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll
+
+ ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
+ True
-
- ..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll
+
+ ..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
+ True
False
diff --git a/sample/WebApi.OutputCache.V2.Demo/app.config b/sample/WebApi.OutputCache.V2.Demo/app.config
index c5e1dae..7435912 100644
--- a/sample/WebApi.OutputCache.V2.Demo/app.config
+++ b/sample/WebApi.OutputCache.V2.Demo/app.config
@@ -1,3 +1,16 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/WebApi.OutputCache.V2.Demo/packages.config b/sample/WebApi.OutputCache.V2.Demo/packages.config
index 09eba1f..ba57378 100644
--- a/sample/WebApi.OutputCache.V2.Demo/packages.config
+++ b/sample/WebApi.OutputCache.V2.Demo/packages.config
@@ -1,7 +1,7 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/src/WebAPI.OutputCache/.gitignore b/src/WebAPI.OutputCache/.gitignore
deleted file mode 100644
index e796d48..0000000
--- a/src/WebAPI.OutputCache/.gitignore
+++ /dev/null
@@ -1,164 +0,0 @@
-#################
-## Eclipse
-#################
-
-*.pydevproject
-.project
-.metadata
-bin/
-tmp/
-*.tmp
-*.bak
-*.swp
-*~.nib
-local.properties
-.classpath
-.settings/
-.loadpath
-
-# External tool builders
-.externalToolBuilders/
-
-# Locally stored "Eclipse launch configurations"
-*.launch
-
-# CDT-specific
-.cproject
-
-# PDT-specific
-.buildpath
-
-
-#################
-## Visual Studio
-#################
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.sln.docstates
-
-# Build results
-[Dd]ebug/
-[Rr]elease/
-*_i.c
-*_p.c
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.vspscc
-.builds
-*.dotCover
-
-## TODO: If you have NuGet Package Restore enabled, uncomment this
-packages/*
-!packages/repositories.config
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-
-# Visual Studio profiler
-*.psess
-*.vsp
-
-# ReSharper is a .NET coding add-in
-_ReSharper*
-
-# Installshield output folder
-[Ee]xpress
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish
-
-# Others
-[Bb]in
-[Oo]bj
-sql
-TestResults
-*.Cache
-ClientBin
-stylecop.*
-~$*
-*.dbmdl
-Generated_Code #added for RIA/Silverlight projects
-
-# Backup & report files from converting an old project file to a newer
-# Visual Studio version. Backup files are not needed, because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-
-
-
-############
-## Windows
-############
-
-# Windows image file caches
-Thumbs.db
-
-# Folder config file
-Desktop.ini
-
-
-#############
-## Python
-#############
-
-*.py[co]
-
-# Packages
-*.egg
-*.egg-info
-dist
-build
-eggs
-parts
-bin
-var
-sdist
-develop-eggs
-.installed.cfg
-
-# Installer logs
-pip-log.txt
-
-# Unit test / coverage reports
-.coverage
-.tox
-
-#Translations
-*.mo
-
-#Mr Developer
-.mr.developer.cfg
-
-# Mac crap
-.DS_Store
diff --git a/src/WebAPI.OutputCache/AutoInvalidateCacheOutputAttribute.cs b/src/WebAPI.OutputCache/AutoInvalidateCacheOutputAttribute.cs
deleted file mode 100644
index 54bee55..0000000
--- a/src/WebAPI.OutputCache/AutoInvalidateCacheOutputAttribute.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Http;
-using System.Reflection;
-using System.Web.Http;
-using System.Web.Http.Controllers;
-using System.Web.Http.Filters;
-using WebApi.OutputCache.Core;
-
-namespace WebAPI.OutputCache
-{
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
- public sealed class AutoInvalidateCacheOutputAttribute : BaseCacheAttribute
- {
- public bool TryMatchType { get; set; }
-
- public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
- {
- 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") 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.ControllerName, action);
- if (WebApiCache.Contains(key))
- {
- WebApiCache.RemoveStartsWith(key);
- }
- }
- }
-
- private static IEnumerable FindAllGetMethods(Type controllerType, IEnumerable 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;
- }
- }
-}
\ No newline at end of file
diff --git a/src/WebAPI.OutputCache/BaseCacheAttribute.cs b/src/WebAPI.OutputCache/BaseCacheAttribute.cs
deleted file mode 100644
index 47b86d7..0000000
--- a/src/WebAPI.OutputCache/BaseCacheAttribute.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System.Net.Http;
-using System.Web.Http;
-using System.Web.Http.Filters;
-using WebApi.OutputCache.Core.Cache;
-
-namespace WebAPI.OutputCache
-{
- public abstract class BaseCacheAttribute : ActionFilterAttribute
- {
- // cache repository
- protected IApiOutputCache WebApiCache;
-
- protected virtual void EnsureCache(HttpConfiguration config, HttpRequestMessage req)
- {
- WebApiCache = config.CacheOutputConfiguration().GetCacheOutputProvider(req);
- }
- }
-}
\ No newline at end of file
diff --git a/src/WebAPI.OutputCache/CacheOutputAttribute.cs b/src/WebAPI.OutputCache/CacheOutputAttribute.cs
deleted file mode 100644
index d4ba10a..0000000
--- a/src/WebAPI.OutputCache/CacheOutputAttribute.cs
+++ /dev/null
@@ -1,244 +0,0 @@
-using System;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Formatting;
-using System.Net.Http.Headers;
-using System.Text;
-using System.Threading;
-using System.Web.Http;
-using System.Web.Http.Controllers;
-using System.Web.Http.Filters;
-using WebApi.OutputCache.Core;
-using WebApi.OutputCache.Core.Time;
-
-namespace WebAPI.OutputCache
-{
- [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
- public class CacheOutputAttribute : BaseCacheAttribute
- {
- protected static MediaTypeHeaderValue DefaultMediaType = new MediaTypeHeaderValue("application/json");
-
- ///
- /// Cache enabled only for requests when Thread.CurrentPrincipal is not set
- ///
- public bool AnonymousOnly { get; set; }
-
- ///
- /// Corresponds to MustRevalidate HTTP header - indicates whether the origin server requires revalidation of a cache entry on any subsequent use when the cache entry becomes stale
- ///
- public bool MustRevalidate { get; set; }
-
- ///
- /// Do not vary cache by querystring values
- ///
- public bool ExcludeQueryStringFromCacheKey { get; set; }
-
- ///
- /// How long response should be cached on the server side (in seconds)
- ///
- public int ServerTimeSpan { get; set; }
-
- ///
- /// Corresponds to CacheControl MaxAge HTTP header (in seconds)
- ///
- public int ClientTimeSpan { get; set; }
-
- ///
- /// Corresponds to CacheControl NoCache HTTP header
- ///
- public bool NoCache { get; set; }
-
- ///
- /// Corresponds to CacheControl Private HTTP header. Response can be cached by browser but not by intermediary cache
- ///
- public bool Private { get; set; }
-
- ///
- /// Class used to generate caching keys
- ///
- public Type CacheKeyGenerator { get; set; }
-
- private MediaTypeHeaderValue _responseMediaType;
-
- internal IModelQuery CacheTimeQuery;
-
- readonly Func _isCachingAllowed = (ac, anonymous) =>
- {
- if (anonymous)
- if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
- return false;
-
- return ac.Request.Method == HttpMethod.Get;
- };
-
- protected virtual void EnsureCacheTimeQuery()
- {
- if (CacheTimeQuery == null) ResetCacheTimeQuery();
- }
-
- protected void ResetCacheTimeQuery()
- {
- CacheTimeQuery = new ShortTime( ServerTimeSpan, ClientTimeSpan );
- }
-
- protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration config, HttpActionContext actionContext)
- {
- MediaTypeHeaderValue responseMediaType = null;
-
- var negotiator = config.Services.GetService(typeof(IContentNegotiator)) as IContentNegotiator;
- var returnType = actionContext.ActionDescriptor.ReturnType;
-
- if (negotiator != null && returnType != typeof(HttpResponseMessage))
- {
- var negotiatedResult = negotiator.Negotiate(returnType, actionContext.Request, config.Formatters);
- responseMediaType = negotiatedResult.MediaType;
- responseMediaType.CharSet = Encoding.UTF8.HeaderName;
- }
- else
- {
- if (actionContext.Request.Headers.Accept != null)
- {
- responseMediaType = actionContext.Request.Headers.Accept.FirstOrDefault();
- if (responseMediaType == null ||
- !config.Formatters.Any(x => x.SupportedMediaTypes.Contains(responseMediaType)))
- {
- DefaultMediaType.CharSet = Encoding.UTF8.HeaderName;
- return DefaultMediaType;
- }
- }
- }
-
- return responseMediaType;
- }
-
- public override void OnActionExecuting(HttpActionContext actionContext)
- {
- if (actionContext == null) throw new ArgumentNullException("actionContext");
-
- if (!_isCachingAllowed(actionContext, AnonymousOnly)) return;
-
- var config = actionContext.Request.GetConfiguration();
-
- EnsureCacheTimeQuery();
- EnsureCache(config, actionContext.Request);
-
- var cacheKeyGenerator = config.CacheOutputConfiguration().GetCacheKeyGenerator(actionContext.Request, CacheKeyGenerator);
-
- _responseMediaType = GetExpectedMediaType(config, actionContext);
- var cachekey = cacheKeyGenerator.MakeCacheKey(actionContext, _responseMediaType, ExcludeQueryStringFromCacheKey);
-
- if (!WebApiCache.Contains(cachekey)) return;
-
- if (actionContext.Request.Headers.IfNoneMatch != null)
- {
- var etag = WebApiCache.Get(cachekey + Constants.EtagKey) as string;
- if (etag != null)
- {
- if (actionContext.Request.Headers.IfNoneMatch.Any(x => x.Tag == etag))
- {
- var time = CacheTimeQuery.Execute(DateTime.Now);
- var quickResponse = actionContext.Request.CreateResponse(HttpStatusCode.NotModified);
- ApplyCacheHeaders(quickResponse, time);
- actionContext.Response = quickResponse;
- return;
- }
- }
- }
-
- var val = WebApiCache.Get(cachekey) as byte[];
- if (val == null) return;
-
- var contenttype = WebApiCache.Get(cachekey + Constants.ContentTypeKey) as string ?? cachekey.Split(':')[1];
-
- actionContext.Response = actionContext.Request.CreateResponse();
- actionContext.Response.Content = new ByteArrayContent(val);
-
- actionContext.Response.Content.Headers.ContentType = new MediaTypeHeaderValue(contenttype);
- var responseEtag = WebApiCache.Get(cachekey + Constants.EtagKey) as string;
- if (responseEtag != null) SetEtag(actionContext.Response, responseEtag);
-
- var cacheTime = CacheTimeQuery.Execute(DateTime.Now);
- ApplyCacheHeaders(actionContext.Response, cacheTime);
- }
-
- public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
- {
- if (actionExecutedContext.ActionContext.Response == null || !actionExecutedContext.ActionContext.Response.IsSuccessStatusCode) return;
-
- if (!_isCachingAllowed(actionExecutedContext.ActionContext, AnonymousOnly)) return;
-
- var cacheTime = CacheTimeQuery.Execute(DateTime.Now);
- if (cacheTime.AbsoluteExpiration > DateTime.Now)
- {
- var config = actionExecutedContext.Request.GetConfiguration().CacheOutputConfiguration();
- var cacheKeyGenerator = config.GetCacheKeyGenerator(actionExecutedContext.Request, CacheKeyGenerator);
-
- var cachekey = cacheKeyGenerator.MakeCacheKey(actionExecutedContext.ActionContext, _responseMediaType, ExcludeQueryStringFromCacheKey);
-
- if (!string.IsNullOrWhiteSpace(cachekey) && !(WebApiCache.Contains(cachekey)))
- {
- var response = actionExecutedContext.Response;
- var actionContext = actionExecutedContext.ActionContext;
- SetEtag(response, CreateEtag(actionExecutedContext, cachekey, cacheTime));
-
-
- if (response.Content != null)
- {
- response.Content.ReadAsByteArrayAsync().ContinueWith(t =>
- {
- var baseKey = config.MakeBaseCachekey(actionContext.ControllerContext.ControllerDescriptor.ControllerName, actionContext.ActionDescriptor.ActionName);
-
- WebApiCache.Add(baseKey, string.Empty, cacheTime.AbsoluteExpiration);
- WebApiCache.Add(cachekey, t.Result, cacheTime.AbsoluteExpiration, baseKey);
-
- WebApiCache.Add(cachekey + Constants.ContentTypeKey,
- response.Content.Headers.ContentType.MediaType,
- cacheTime.AbsoluteExpiration, baseKey);
-
- WebApiCache.Add(cachekey + Constants.EtagKey,
- response.Headers.ETag.Tag,
- cacheTime.AbsoluteExpiration, baseKey);
- });
- }
- }
- }
-
- ApplyCacheHeaders(actionExecutedContext.ActionContext.Response, cacheTime);
- }
-
- protected virtual string CreateEtag(HttpActionExecutedContext actionExecutedContext, string cachekey, CacheTime cacheTime)
- {
- return Guid.NewGuid().ToString();
- }
-
- private void ApplyCacheHeaders(HttpResponseMessage response, CacheTime cacheTime)
- {
- if (cacheTime.ClientTimeSpan > TimeSpan.Zero || MustRevalidate || Private)
- {
- var cachecontrol = new CacheControlHeaderValue
- {
- MaxAge = cacheTime.ClientTimeSpan,
- MustRevalidate = MustRevalidate,
- Private = Private
- };
-
- response.Headers.CacheControl = cachecontrol;
- }
- else if (NoCache)
- {
- response.Headers.CacheControl = new CacheControlHeaderValue {NoCache = true};
- response.Headers.Add("Pragma", "no-cache");
- }
- }
-
- private static void SetEtag(HttpResponseMessage message, string etag)
- {
- if (etag != null)
- {
- var eTag = new EntityTagHeaderValue(@"""" + etag.Replace("\"", string.Empty) + @"""");
- message.Headers.ETag = eTag;
- }
- }
- }
-}
diff --git a/src/WebAPI.OutputCache/CacheOutputConfiguration.cs b/src/WebAPI.OutputCache/CacheOutputConfiguration.cs
deleted file mode 100644
index f2b7bf0..0000000
--- a/src/WebAPI.OutputCache/CacheOutputConfiguration.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-using System;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Net.Http;
-using System.Reflection;
-using System.Web.Http;
-using WebApi.OutputCache.Core.Cache;
-
-namespace WebAPI.OutputCache
-{
- public class CacheOutputConfiguration
- {
- private readonly HttpConfiguration _configuration;
-
- public CacheOutputConfiguration(HttpConfiguration configuration)
- {
- _configuration = configuration;
- }
-
- public void RegisterCacheOutputProvider(Func provider)
- {
- _configuration.Properties.GetOrAdd(typeof(IApiOutputCache), x => provider);
- }
-
- public void RegisterCacheKeyGeneratorProvider(Func provider)
- where T: ICacheKeyGenerator
- {
- _configuration.Properties.GetOrAdd(typeof (T), x => provider);
- }
-
- public void RegisterDefaultCacheKeyGeneratorProvider(Func provider)
- {
- RegisterCacheKeyGeneratorProvider(provider);
- }
-
- public string MakeBaseCachekey(string controller, string action)
- {
- return string.Format("{0}-{1}", controller.ToLower(), action.ToLower());
- }
-
- public string MakeBaseCachekey(Expression> expression)
- {
- var method = expression.Body as MethodCallExpression;
- if (method == null) throw new ArgumentException("Expression is wrong");
-
- var methodName = method.Method.Name;
- var nameAttribs = method.Method.GetCustomAttributes(typeof(ActionNameAttribute), false);
- if (nameAttribs.Any())
- {
- var actionNameAttrib = (ActionNameAttribute) nameAttribs.FirstOrDefault();
- if (actionNameAttrib != null)
- {
- methodName = actionNameAttrib.Name;
- }
- }
-
- return string.Format("{0}-{1}", typeof(T).Name.Replace("Controller",string.Empty).ToLower(), methodName.ToLower());
- }
-
- private static ICacheKeyGenerator TryActivateCacheKeyGenerator(Type generatorType)
- {
- var hasEmptyOrDefaultConstructor =
- generatorType.GetConstructor(Type.EmptyTypes) != null ||
- generatorType.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
- .Any (x => x.GetParameters().All (p => p.IsOptional));
- return hasEmptyOrDefaultConstructor
- ? Activator.CreateInstance(generatorType) as ICacheKeyGenerator
- : null;
- }
-
- public ICacheKeyGenerator GetCacheKeyGenerator(HttpRequestMessage request, Type generatorType)
- {
- generatorType = generatorType ?? typeof (ICacheKeyGenerator);
- object cache;
- _configuration.Properties.TryGetValue(generatorType, out cache);
-
- var cacheFunc = cache as Func;
-
- var generator = cacheFunc != null
- ? cacheFunc()
- : request.GetDependencyScope().GetService(generatorType) as ICacheKeyGenerator;
-
- return generator
- ?? TryActivateCacheKeyGenerator(generatorType)
- ?? new DefaultCacheKeyGenerator();
- }
-
- public IApiOutputCache GetCacheOutputProvider(HttpRequestMessage request)
- {
- object cache;
- _configuration.Properties.TryGetValue(typeof(IApiOutputCache), out cache);
-
- var cacheFunc = cache as Func;
-
- var cacheOutputProvider = cacheFunc != null ? cacheFunc() : request.GetDependencyScope().GetService(typeof(IApiOutputCache)) as IApiOutputCache ?? new MemoryCacheDefault();
- return cacheOutputProvider;
- }
- }
-}
\ No newline at end of file
diff --git a/src/WebAPI.OutputCache/DefaultCacheKeyGenerator.cs b/src/WebAPI.OutputCache/DefaultCacheKeyGenerator.cs
deleted file mode 100644
index 35d3c22..0000000
--- a/src/WebAPI.OutputCache/DefaultCacheKeyGenerator.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Web.Http.Controllers;
-using WebApi.OutputCache.Core;
-
-namespace WebAPI.OutputCache
-{
- public class DefaultCacheKeyGenerator : ICacheKeyGenerator
- {
- public virtual string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false)
- {
- var controller = context.ControllerContext.ControllerDescriptor.ControllerName;
- var action = context.ActionDescriptor.ActionName;
- var key = context.Request.GetConfiguration().CacheOutputConfiguration().MakeBaseCachekey(controller, action);
- var actionParameters = context.ActionArguments.Where(x => x.Value != null).Select(x => x.Key + "=" + GetValue(x.Value));
-
- string parameters;
-
- if (!excludeQueryString)
- {
- var queryStringParameters =
- context.Request.GetQueryNameValuePairs()
- .Where(x => x.Key.ToLower() != "callback")
- .Select(x => x.Key + "=" + x.Value);
- var parametersCollections = actionParameters.Union(queryStringParameters);
- parameters = "-" + string.Join("&", parametersCollections);
-
- var callbackValue = GetJsonpCallback(context.Request);
- if (!string.IsNullOrWhiteSpace(callbackValue))
- {
- var callback = "callback=" + callbackValue;
- if (parameters.Contains("&" + callback)) parameters = parameters.Replace("&" + callback, string.Empty);
- if (parameters.Contains(callback + "&")) parameters = parameters.Replace(callback + "&", string.Empty);
- if (parameters.Contains("-" + callback)) parameters = parameters.Replace("-" + callback, string.Empty);
- if (parameters.EndsWith("&")) parameters = parameters.TrimEnd('&');
- }
- }
- else
- {
- parameters = "-" + string.Join("&", actionParameters);
- }
-
- if (parameters == "-") parameters = string.Empty;
-
- var cachekey = string.Format("{0}{1}:{2}", key, parameters, mediaType.MediaType);
- return cachekey;
- }
-
- private string GetJsonpCallback(HttpRequestMessage request)
- {
- var callback = string.Empty;
- if (request.Method == HttpMethod.Get)
- {
- var query = request.GetQueryNameValuePairs();
-
- if (query != null)
- {
- var queryVal = query.FirstOrDefault(x => x.Key.ToLower() == "callback");
- if (!queryVal.Equals(default(KeyValuePair))) callback = queryVal.Value;
- }
- }
- return callback;
- }
-
- private string GetValue(object val)
- {
- if (val is IEnumerable && !(val is string))
- {
- var concatValue = string.Empty;
- var paramArray = val as IEnumerable;
- return paramArray.Cast