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().Aggregate(concatValue, (current, paramValue) => current + (paramValue + ";")); - } - return val.ToString(); - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/HttpConfigurationExtensions.cs b/src/WebAPI.OutputCache/HttpConfigurationExtensions.cs deleted file mode 100644 index 7ca0203..0000000 --- a/src/WebAPI.OutputCache/HttpConfigurationExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Web.Http; - -namespace WebAPI.OutputCache -{ - public static class HttpConfigurationExtensions - { - public static CacheOutputConfiguration CacheOutputConfiguration(this HttpConfiguration config) - { - return new CacheOutputConfiguration(config); - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/ICacheKeyGenerator.cs b/src/WebAPI.OutputCache/ICacheKeyGenerator.cs deleted file mode 100644 index 8224f76..0000000 --- a/src/WebAPI.OutputCache/ICacheKeyGenerator.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Net.Http.Headers; -using System.Web.Http.Controllers; - -namespace WebAPI.OutputCache -{ - public interface ICacheKeyGenerator - { - string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false); - } -} diff --git a/src/WebAPI.OutputCache/InvalidateCacheOutputAttribute.cs b/src/WebAPI.OutputCache/InvalidateCacheOutputAttribute.cs deleted file mode 100644 index d71730b..0000000 --- a/src/WebAPI.OutputCache/InvalidateCacheOutputAttribute.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Net.Http; -using System.Web.Http.Filters; - -namespace WebAPI.OutputCache -{ - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] - public sealed class InvalidateCacheOutputAttribute : BaseCacheAttribute - { - private string _controller; - private readonly string _methodName; - - public InvalidateCacheOutputAttribute(string methodName) - : this(methodName, null) - { - } - - public InvalidateCacheOutputAttribute(string methodName, Type type = null) - { - _controller = type != null ? type.Name.Replace("Controller", string.Empty) : null; - _methodName = methodName; - } - - public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) - { - if (actionExecutedContext.Response != null && !actionExecutedContext.Response.IsSuccessStatusCode) return; - _controller = _controller ?? actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName; - - var config = actionExecutedContext.Request.GetConfiguration(); - EnsureCache(config, actionExecutedContext.Request); - - var key = actionExecutedContext.Request.GetConfiguration().CacheOutputConfiguration().MakeBaseCachekey(_controller, _methodName); - if (WebApiCache.Contains(key)) - { - WebApiCache.RemoveStartsWith(key); - } - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/Properties/AssemblyInfo.cs b/src/WebAPI.OutputCache/Properties/AssemblyInfo.cs deleted file mode 100644 index b2e652f..0000000 --- a/src/WebAPI.OutputCache/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +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")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WebAPI.OutputCache")] -[assembly: AssemblyCopyright("Copyright © 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: InternalsVisibleTo("WebAPI.OutputCache.Tests")] - -// 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("73559c35-3a0c-449c-b137-886cfc45e446")] - -// 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/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilCacheAttribute.cs b/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilCacheAttribute.cs deleted file mode 100644 index 8a3918c..0000000 --- a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilCacheAttribute.cs +++ /dev/null @@ -1,26 +0,0 @@ -using WebApi.OutputCache.Core.Time; - -namespace WebAPI.OutputCache.TimeAttributes -{ - public sealed class CacheOutputUntilAttribute : CacheOutputAttribute - { - /// - /// Cache item until absolute expiration 2012/01/01 @ 17h45 - /// - /// 2012 - /// 1 - /// 1 - /// 17 - /// 45 - /// 0 - public CacheOutputUntilAttribute(int year, - int month, - int day, - int hour = 0, - int minute = 0, - int second = 0) - { - CacheTimeQuery = new SpecificTime(year, month, day, hour, minute, second); - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilThisMonthAttribute.cs b/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilThisMonthAttribute.cs deleted file mode 100644 index 6e54cef..0000000 --- a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilThisMonthAttribute.cs +++ /dev/null @@ -1,22 +0,0 @@ -using WebApi.OutputCache.Core.Time; - -namespace WebAPI.OutputCache.TimeAttributes -{ - public sealed class CacheOutputUntilThisMonthAttribute : CacheOutputAttribute - { - /// - /// Cache item until absolute expiration THIS YEAR / THIS MONTH / 01 @ 17h45 - /// - /// 1 - /// 17 - /// 45 - /// 0 - public CacheOutputUntilThisMonthAttribute(int day, - int hour = 0, - int minute = 0, - int second = 0) - { - CacheTimeQuery = new ThisMonth(day, hour, minute, second); - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilThisYearAttribute.cs b/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilThisYearAttribute.cs deleted file mode 100644 index 8c13e12..0000000 --- a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilThisYearAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -using WebApi.OutputCache.Core.Time; - -namespace WebAPI.OutputCache.TimeAttributes -{ - public sealed class CacheOutputUntilThisYearAttribute : CacheOutputAttribute - { - /// - /// Cache item until absolute expiration THIS YEAR / 01 / 01 @ 17h45 - /// - /// 1 - /// 1 - /// 17 - /// 45 - /// 0 - public CacheOutputUntilThisYearAttribute(int month, - int day, - int hour = 0, - int minute = 0, - int second = 0) - { - CacheTimeQuery = new ThisYear(month, day, hour, minute, second); - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilToday.cs b/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilToday.cs deleted file mode 100644 index 6d3506c..0000000 --- a/src/WebAPI.OutputCache/TimeAttributes/CacheOutputUntilToday.cs +++ /dev/null @@ -1,20 +0,0 @@ -using WebApi.OutputCache.Core.Time; - -namespace WebAPI.OutputCache.TimeAttributes -{ - public sealed class CacheOutputUntilToday : CacheOutputAttribute - { - /// - /// Cache item until absolute expiration today @ 17h45 - /// - /// 17 - /// 45 - /// 0 - public CacheOutputUntilToday(int hour = 23, - int minute = 59, - int second = 59) - { - CacheTimeQuery = new ThisDay(hour, minute, second); - } - } -} \ No newline at end of file diff --git a/src/WebAPI.OutputCache/WebAPI.OutputCache.csproj b/src/WebAPI.OutputCache/WebAPI.OutputCache.csproj deleted file mode 100644 index 71deb2e..0000000 --- a/src/WebAPI.OutputCache/WebAPI.OutputCache.csproj +++ /dev/null @@ -1,91 +0,0 @@ - - - - - Debug - AnyCPU - {4F32DC89-081B-4264-92F8-F3371A088EB4} - Library - Properties - WebAPI.OutputCache - WebAPI.OutputCache - v4.0 - 512 - - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\WebAPI.OutputCache.XML - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\WebAPI.OutputCache.XML - - - - ..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll - - - - - ..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll - - - ..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll - - - ..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll - - - - ..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll - - - - - - - - - - - - - - - - - - - - - - - - {3e45fa0b-c465-4de9-9bc3-40a606b73e84} - WebApi.OutputCache.Core - - - - - - \ No newline at end of file diff --git a/src/WebAPI.OutputCache/packages.config b/src/WebAPI.OutputCache/packages.config deleted file mode 100644 index 5db908c..0000000 --- a/src/WebAPI.OutputCache/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs b/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs index 2619778..da54c3d 100644 --- a/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs +++ b/src/WebApi.OutputCache.V2/CacheOutputAttribute.cs @@ -18,7 +18,7 @@ namespace WebApi.OutputCache.V2 { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - public class CacheOutputAttribute : FilterAttribute, IActionFilter + public class CacheOutputAttribute : ActionFilterAttribute { protected static MediaTypeHeaderValue DefaultMediaType = new MediaTypeHeaderValue("application/json") {CharSet = Encoding.UTF8.HeaderName}; @@ -125,7 +125,7 @@ protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration co return responseMediaType; } - private void OnActionExecuting(HttpActionContext actionContext) + public override void OnActionExecuting(HttpActionContext actionContext) { if (actionContext == null) throw new ArgumentNullException("actionContext"); @@ -175,7 +175,7 @@ private void OnActionExecuting(HttpActionContext actionContext) ApplyCacheHeaders(actionContext.Response, cacheTime); } - private async Task OnActionExecuted(HttpActionExecutedContext actionExecutedContext) + public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { if (actionExecutedContext.ActionContext.Response == null || !actionExecutedContext.ActionContext.Response.IsSuccessStatusCode) return; @@ -257,67 +257,5 @@ private static void SetEtag(HttpResponseMessage message, string etag) message.Headers.ETag = eTag; } } - - Task IActionFilter.ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation) - { - if (actionContext == null) - { - throw new ArgumentNullException("actionContext"); - } - - if (continuation == null) - { - throw new ArgumentNullException("continuation"); - } - - OnActionExecuting(actionContext); - - if (actionContext.Response != null) - { - return Task.FromResult(actionContext.Response); - } - - return CallOnActionExecutedAsync(actionContext, cancellationToken, continuation); - } - - private async Task CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation) - { - cancellationToken.ThrowIfCancellationRequested(); - - HttpResponseMessage response = null; - Exception exception = null; - try - { - response = await continuation(); - } - catch (Exception e) - { - exception = e; - } - - try - { - var executedContext = new HttpActionExecutedContext(actionContext, exception) { Response = response }; - await OnActionExecuted(executedContext); - - if (executedContext.Response != null) - { - return executedContext.Response; - } - - if (executedContext.Exception != null) - { - ExceptionDispatchInfo.Capture(executedContext.Exception).Throw(); - } - } - catch (Exception e) - { - actionContext.Response = null; - ExceptionDispatchInfo.Capture(e).Throw(); - } - - throw new InvalidOperationException(GetType().Name); - } - } } diff --git a/src/WebApi.OutputCache.V2/WebApi.OutputCache.V2.csproj b/src/WebApi.OutputCache.V2/WebApi.OutputCache.V2.csproj index 26def86..ec90dfa 100644 --- a/src/WebApi.OutputCache.V2/WebApi.OutputCache.V2.csproj +++ b/src/WebApi.OutputCache.V2/WebApi.OutputCache.V2.csproj @@ -45,13 +45,13 @@ - - False - ..\..\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 - - False - ..\..\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 @@ -71,7 +71,6 @@ - diff --git a/src/WebApi.OutputCache.V2/packages.config b/src/WebApi.OutputCache.V2/packages.config index 06a23b3..8d24fa1 100644 --- a/src/WebApi.OutputCache.V2/packages.config +++ b/src/WebApi.OutputCache.V2/packages.config @@ -1,6 +1,6 @@  - - - + + + \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/.gitignore b/test/WebAPI.OutputCache.Tests/.gitignore deleted file mode 100644 index e796d48..0000000 --- a/test/WebAPI.OutputCache.Tests/.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/test/WebAPI.OutputCache.Tests/CacheKeyGeneratorRegistrationTests.cs b/test/WebAPI.OutputCache.Tests/CacheKeyGeneratorRegistrationTests.cs deleted file mode 100644 index 71524ec..0000000 --- a/test/WebAPI.OutputCache.Tests/CacheKeyGeneratorRegistrationTests.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Web.Http; -using System.Web.Http.Controllers; -using Autofac; -using Autofac.Integration.WebApi; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class CacheKeyGeneratorRegistrationTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/"; - private Mock _cache; - private Mock _keyGenerator; - - [SetUp] - public void init() - { - Thread.CurrentPrincipal = null; - - _cache = new Mock(); - _keyGenerator = new Mock(); - - var conf = new HttpConfiguration(); - - var builder = new ContainerBuilder(); - builder.RegisterInstance(_cache.Object); - - conf.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build()); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void registered_default_is_used() - { - _server.Configuration.CacheOutputConfiguration().RegisterDefaultCacheKeyGeneratorProvider(() => _keyGenerator.Object); - - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "sample/Get_c100_s100").Result; - - _keyGenerator.VerifyAll(); - } - - [Test] - public void last_registered_default_is_used() - { - _server.Configuration.CacheOutputConfiguration().RegisterDefaultCacheKeyGeneratorProvider(() => { - Assert.Fail("First registration should have been overwritten"); - return null; - }); - _server.Configuration.CacheOutputConfiguration().RegisterDefaultCacheKeyGeneratorProvider(() => _keyGenerator.Object); - - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "sample/Get_c100_s100").Result; - - _keyGenerator.VerifyAll(); - } - - [Test] - public void specific_registration_does_not_affect_default() - { - _server.Configuration.CacheOutputConfiguration().RegisterDefaultCacheKeyGeneratorProvider(() => _keyGenerator.Object); - _server.Configuration.CacheOutputConfiguration().RegisterCacheKeyGeneratorProvider(() => new FailCacheKeyGenerator()); - - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "sample/Get_c100_s100").Result; - - _keyGenerator.VerifyAll(); - } - - [Test] - public void selected_generator_with_internal_registration_is_used() - { - _server.Configuration.CacheOutputConfiguration().RegisterCacheKeyGeneratorProvider(() => new InternalRegisteredCacheKeyGenerator("internal")); - - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "cachekey/get_internalregistered").Result; - - _cache.Verify(s => s.Add(It.Is(x => x == "internal"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "cachekey-get_internalregistered")), Times.Once()); - } - - [Test] - public void custom_unregistered_cache_key_generator_called() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "cachekey/get_unregistered").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "unregistered")), Times.Once()); - } - - #region Helper classes - private class FailCacheKeyGenerator : ICacheKeyGenerator - { - public string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false) - { - Assert.Fail("This cache key generator should never be invoked"); - return "fail"; - } - } - - public class InternalRegisteredCacheKeyGenerator : ICacheKeyGenerator - { - private readonly string _key; - - public InternalRegisteredCacheKeyGenerator(string key) - { - _key = key; - } - - public string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false) - { - return _key; - } - } - #endregion - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/CacheKeyGeneratorTests.cs b/test/WebAPI.OutputCache.Tests/CacheKeyGeneratorTests.cs deleted file mode 100644 index 02636ac..0000000 --- a/test/WebAPI.OutputCache.Tests/CacheKeyGeneratorTests.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Web.Http; -using System.Web.Http.Controllers; -using Autofac; -using Autofac.Integration.WebApi; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - class CacheKeyGeneratorTests - { - public class CustomCacheKeyGenerator : ICacheKeyGenerator - { - public string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false) - { - return "custom_key"; - } - } - - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/"; - private Mock _cache; - private Mock _keyGeneratorA; - private CustomCacheKeyGenerator _keyGeneratorB; - - [SetUp] - public void init() - { - Thread.CurrentPrincipal = null; - - _cache = new Mock(); - _keyGeneratorA = new Mock(); - _keyGeneratorB = new CustomCacheKeyGenerator(); - - var conf = new HttpConfiguration(); - var builder = new ContainerBuilder(); - builder.RegisterInstance(_cache.Object); - // this should become the default cache key generator - builder.RegisterInstance(_keyGeneratorA.Object).As(); - builder.RegisterInstance(_keyGeneratorB); - - conf.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build()); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void custom_default_cache_key_generator_called_and_key_used() - { - var client = new HttpClient(_server); - _keyGeneratorA.Setup(k => k.MakeCacheKey(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns("keykeykey") - .Verifiable("Key generator was never called"); - // use the samplecontroller to show that no changes are required to existing code - var result = client.GetAsync(_url + "sample/Get_c100_s100").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "keykeykey")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "keykeykey"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "keykeykey:response-ct"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); - - _keyGeneratorA.VerifyAll(); - } - - [Test] - public void custom_cache_key_generator_called() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "cachekey/get_custom_key").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "custom_key")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "custom_key"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "cachekey-get_custom_key")), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "custom_key:response-ct"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "cachekey-get_custom_key")), Times.Once()); - } - } -} diff --git a/test/WebAPI.OutputCache.Tests/ClientSideTests.cs b/test/WebAPI.OutputCache.Tests/ClientSideTests.cs deleted file mode 100644 index d47f871..0000000 --- a/test/WebAPI.OutputCache.Tests/ClientSideTests.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System; -using System.Linq; -using System.Net.Http; -using System.Web.Http; -using NUnit.Framework; -using WebApi.OutputCache.Core.Time; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class ClientSideTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/sample/"; - - [TestFixtureSetUp] - public void fixture_init() - { - var conf = new HttpConfiguration(); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void maxage_mustrevalidate_false_headers_correct() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c100_s100").Result; - - Assert.AreEqual(TimeSpan.FromSeconds(100), result.Headers.CacheControl.MaxAge); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void no_cachecontrol_when_clienttimeout_is_zero() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c0_s100").Result; - - Assert.IsNull(result.Headers.CacheControl); - } - - [Test] - public void no_cachecontrol_when_request_not_succes() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_request_httpResponseException_noCache").Result; - - Assert.IsNull(result.Headers.CacheControl); - } - - [Test] - public void no_cachecontrol_when_request_exception() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_request_exception_noCache").Result; - - Assert.IsNull(result.Headers.CacheControl); - } - [Test] - public void maxage_cachecontrol_when_no_content() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_request_noContent").Result; - - Assert.IsNotNull(result.Headers.CacheControl); - Assert.AreEqual(TimeSpan.FromSeconds(50), result.Headers.CacheControl.MaxAge); - } - - - [Test] - public void maxage_mustrevalidate_headers_correct_with_clienttimeout_zero_with_must_revalidate() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c0_s100_mustR").Result; - - Assert.IsTrue(result.Headers.CacheControl.MustRevalidate); - Assert.AreEqual(TimeSpan.Zero, result.Headers.CacheControl.MaxAge); - } - - - [Test] - public void nocache_headers_correct() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_nocache").Result; - - Assert.IsTrue(result.Headers.CacheControl.NoCache, - "NoCache in result headers was expected to be true when CacheOutput.NoCache=true."); - Assert.IsTrue(result.Headers.Contains("Pragma"), - "result headers does not contain expected Pragma."); - Assert.IsTrue(result.Headers.GetValues("Pragma").Contains("no-cache"), - "expected no-cache Pragma was not found"); - } - - [Test] - public void maxage_mustrevalidate_true_headers_correct() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c50_mustR").Result; - - Assert.AreEqual(TimeSpan.FromSeconds(50), result.Headers.CacheControl.MaxAge); - Assert.IsTrue(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void maxage_private_true_headers_correct() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c50_private").Result; - - Assert.AreEqual(TimeSpan.FromSeconds(50), result.Headers.CacheControl.MaxAge); - Assert.IsTrue(result.Headers.CacheControl.Private); - } - - [Test] - public void maxage_mustrevalidate_headers_correct_with_cacheuntil() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_until25012015_1700").Result; - var clientTimeSpanSeconds = new SpecificTime(2015, 01, 25, 17, 0, 0).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds; - var resultCacheControlSeconds = ((TimeSpan) result.Headers.CacheControl.MaxAge).TotalSeconds; - Assert.IsTrue(Math.Round(clientTimeSpanSeconds - resultCacheControlSeconds) == 0); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void maxage_mustrevalidate_headers_correct_with_cacheuntil_today() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_until2355_today").Result; - - Assert.IsTrue(Math.Round(new ThisDay(23,55,59).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds - ((TimeSpan)result.Headers.CacheControl.MaxAge).TotalSeconds) == 0); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void maxage_mustrevalidate_headers_correct_with_cacheuntil_this_month() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_until27_thismonth").Result; - - Assert.IsTrue(Math.Round(new ThisMonth(27,0,0,0).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds - ((TimeSpan)result.Headers.CacheControl.MaxAge).TotalSeconds) == 0); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void maxage_mustrevalidate_headers_correct_with_cacheuntil_this_year() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_until731_thisyear").Result; - - Assert.IsTrue(Math.Round(new ThisYear(7, 31, 0, 0, 0).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds - ((TimeSpan)result.Headers.CacheControl.MaxAge).TotalSeconds) == 0); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void maxage_mustrevalidate_headers_correct_with_cacheuntil_this_year_with_revalidate() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_until731_thisyear_mustrevalidate").Result; - - Assert.IsTrue(Math.Round(new ThisYear(7, 31, 0, 0, 0).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds - ((TimeSpan)result.Headers.CacheControl.MaxAge).TotalSeconds) == 0); - Assert.IsTrue(result.Headers.CacheControl.MustRevalidate); - } - - [Test] - public void private_true_headers_correct() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_private").Result; - - Assert.IsTrue(result.Headers.CacheControl.Private); - } - - [TestFixtureTearDown] - public void fixture_dispose() - { - if (_server != null) _server.Dispose(); - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/ConfigurationTests.cs b/test/WebAPI.OutputCache.Tests/ConfigurationTests.cs deleted file mode 100644 index e69df4a..0000000 --- a/test/WebAPI.OutputCache.Tests/ConfigurationTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Net.Http; -using System.Web.Http; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class ConfigurationTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/sample/"; - private Mock _cache; - - [Test] - public void cache_singleton_in_pipeline() - { - _cache = new Mock(); - - var conf = new HttpConfiguration(); - conf.CacheOutputConfiguration().RegisterCacheOutputProvider(() => _cache.Object); - - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c100_s100").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(2)); - - var result2 = client.GetAsync(_url + "Get_c100_s100").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(4)); - - _server.Dispose(); - } - - [Test] - public void cache_singleton() - { - var cache = new MemoryCacheDefault(); - - var conf = new HttpConfiguration(); - conf.CacheOutputConfiguration().RegisterCacheOutputProvider(() => cache); - - object cache1; - conf.Properties.TryGetValue(typeof(IApiOutputCache), out cache1); - - object cache2; - conf.Properties.TryGetValue(typeof(IApiOutputCache), out cache2); - - Assert.AreSame(((Func)cache1)(), ((Func)cache2)()); - } - - [Test] - public void cache_instance() - { - var conf = new HttpConfiguration(); - conf.CacheOutputConfiguration().RegisterCacheOutputProvider(() => new MemoryCacheDefault()); - - object cache1; - conf.Properties.TryGetValue(typeof(IApiOutputCache), out cache1); - - object cache2; - conf.Properties.TryGetValue(typeof(IApiOutputCache), out cache2); - - Assert.AreNotSame(((Func)cache1)(), ((Func)cache2)()); - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/ConnegTests.cs b/test/WebAPI.OutputCache.Tests/ConnegTests.cs deleted file mode 100644 index d990c48..0000000 --- a/test/WebAPI.OutputCache.Tests/ConnegTests.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Web.Http; -using Autofac; -using Autofac.Integration.WebApi; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class ConnegTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/sample/"; - private Mock _cache; - - [SetUp] - public void init() - { - _cache = new Mock(); - - var conf = new HttpConfiguration(); - var builder = new ContainerBuilder(); - builder.RegisterInstance(_cache.Object); - - conf.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build()); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void subsequent_xml_request_is_not_cached() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c100_s100").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:application/json"), It.IsAny(), It.Is(x => x < DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); - - var req = new HttpRequestMessage(HttpMethod.Get, _url + "Get_c100_s100"); - req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml")); - - var result2 = client.SendAsync(req).Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml"), It.IsAny(), It.Is(x => x < DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); - - } - - [TearDown] - public void fixture_dispose() - { - if (_server != null) _server.Dispose(); - } - } -} diff --git a/test/WebAPI.OutputCache.Tests/InlineInvalidateTests.cs b/test/WebAPI.OutputCache.Tests/InlineInvalidateTests.cs deleted file mode 100644 index 1ea8d24..0000000 --- a/test/WebAPI.OutputCache.Tests/InlineInvalidateTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Net.Http; -using System.Threading; -using System.Web.Http; -using Autofac; -using Autofac.Integration.WebApi; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class InlineInvalidateTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/inlineinvalidate/"; - private Mock _cache; - - [SetUp] - public void init() - { - Thread.CurrentPrincipal = null; - - _cache = new Mock(); - - var conf = new HttpConfiguration(); - var builder = new ContainerBuilder(); - builder.RegisterInstance(_cache.Object); - - conf.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build()); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void inline_call_to_invalidate_is_correct() - { - var client = new HttpClient(_server); - - var result = client.PostAsync(_url + "Post", new StringContent(string.Empty)).Result; - - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "inlineinvalidate-get_c100_s100")), Times.Exactly(1)); - } - - [Test] - public void inline_call_to_invalidate_using_expression_tree_is_correct() - { - var client = new HttpClient(_server); - var result = client.PutAsync(_url + "Put", new StringContent(string.Empty)).Result; - - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "inlineinvalidate-get_c100_s100")), Times.Exactly(1)); - } - - [Test] - public void inline_call_to_invalidate_using_expression_tree_with_param_is_correct() - { - var client = new HttpClient(_server); - var result = client.DeleteAsync(_url + "Delete_parameterized").Result; - - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "inlineinvalidate-get_c100_s100_with_param")), Times.Exactly(1)); - } - - [Test] - public void inline_call_to_invalidate_using_expression_tree_with_custom_action_name_is_correct() - { - var client = new HttpClient(_server); - var result = client.DeleteAsync(_url + "Delete_non_standard_name").Result; - - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "inlineinvalidate-getbyid")), Times.Exactly(1)); - } - - [TearDown] - public void fixture_dispose() - { - if (_server != null) _server.Dispose(); - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/InvalidateTests.cs b/test/WebAPI.OutputCache.Tests/InvalidateTests.cs deleted file mode 100644 index ccfba37..0000000 --- a/test/WebAPI.OutputCache.Tests/InvalidateTests.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Threading; -using System.Web.Http; -using Autofac; -using Autofac.Integration.WebApi; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class InvalidateTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/sample/"; - private Mock _cache; - - [SetUp] - public void init() - { - Thread.CurrentPrincipal = null; - - _cache = new Mock(); - - var conf = new HttpConfiguration(); - var builder = new ContainerBuilder(); - builder.RegisterInstance(_cache.Object); - - conf.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build()); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void regular_invalidate_works_on_post() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.PostAsync(_url + "Post", new StringContent(string.Empty)).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); - } - - [Test] - public void regular_invalidate_on_two_methods_works_on_post() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.PostAsync(_url + "Post_2_invalidates", new StringContent(string.Empty)).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Exactly(1)); - } - - [Test] - public void controller_level_invalidate_on_three_methods_works_on_post() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.PostAsync("http://www.strathweb.com/api/autoinvalidate/Post", new StringContent(string.Empty)).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-etag_match_304")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-etag_match_304")), Times.Exactly(1)); - } - - [Test] - public void controller_level_invalidate_on_three_methods_works_on_put() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.PutAsync("http://www.strathweb.com/api/autoinvalidate/Put", new StringContent(string.Empty)).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-etag_match_304")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-etag_match_304")), Times.Exactly(1)); - } - - [Test] - public void controller_level_invalidate_on_three_methods_works_on_delete() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.DeleteAsync("http://www.strathweb.com/api/autoinvalidate/Delete").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidate-etag_match_304")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-get_s50_exclude_fakecallback")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidate-etag_match_304")), Times.Exactly(1)); - } - - [Test] - public void controller_level_invalidate_with_type_check_does_not_invalidate_on_no_type_match() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.PostAsync("http://www.strathweb.com/api/autoinvalidatewithtype/Post", new StringContent(string.Empty)).Result; - - Assert.True(result2.IsSuccessStatusCode); - _cache.Verify(s => s.Contains(It.IsAny()), Times.Never()); - _cache.Verify(s => s.RemoveStartsWith(It.IsAny()), Times.Never()); - } - - [Test] - public void controller_level_invalidate_with_type_check_invalidates_only_methods_with_types_matched() - { - SetupCacheForAutoInvalidate(); - var client = new HttpClient(_server); - - var result2 = client.PostAsync("http://www.strathweb.com/api/autoinvalidatewithtype/PostString", "hi", new JsonMediaTypeFormatter()).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidatewithtype-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidatewithtype-get_c100_s100_array")), Times.Exactly(1)); - _cache.Verify(s => s.Contains(It.Is(x => x == "autoinvalidatewithtype-get_s50_exclude_fakecallback")), Times.Never()); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidatewithtype-get_c100_s100")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidatewithtype-get_c100_s100_array")), Times.Exactly(1)); - _cache.Verify(s => s.RemoveStartsWith(It.Is(x => x == "autoinvalidatewithtype-get_s50_exclude_fakecallback")), Times.Never()); - } - - private void SetupCacheForAutoInvalidate() - { - _cache.Setup(x => x.Contains(It.Is(s => s == "sample-get_s50_exclude_fakecallback"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "sample-get_c100_s100"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "autoinvalidate-get_c100_s100"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "autoinvalidate-get_s50_exclude_fakecallback"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "autoinvalidate-etag_match_304"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "autoinvalidatewithtype-get_c100_s100"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "autoinvalidatewithtype-get_s50_exclude_fakecallback"))).Returns(true); - _cache.Setup(x => x.Contains(It.Is(s => s == "autoinvalidatewithtype-get_c100_s100_array"))).Returns(true); - } - - [TearDown] - public void fixture_dispose() - { - if (_server != null) _server.Dispose(); - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/Properties/AssemblyInfo.cs b/test/WebAPI.OutputCache.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index a07cf7b..0000000 --- a/test/WebAPI.OutputCache.Tests/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.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WebAPI.OutputCache.Tests")] -[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("a3aa26bd-d83e-42ef-bf3b-39875348ae0b")] - -// 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/test/WebAPI.OutputCache.Tests/ServerSideTests.cs b/test/WebAPI.OutputCache.Tests/ServerSideTests.cs deleted file mode 100644 index be5fcfc..0000000 --- a/test/WebAPI.OutputCache.Tests/ServerSideTests.cs +++ /dev/null @@ -1,296 +0,0 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Security.Principal; -using System.Threading; -using System.Web.Http; -using Autofac; -using Autofac.Integration.WebApi; -using Moq; -using NUnit.Framework; -using WebApi.OutputCache.Core; -using WebApi.OutputCache.Core.Cache; - -namespace WebAPI.OutputCache.Tests -{ - [TestFixture] - public class ServerSideTests - { - private HttpServer _server; - private string _url = "http://www.strathweb.com/api/sample/"; - private Mock _cache; - - [SetUp] - public void init() - { - Thread.CurrentPrincipal = null; - - _cache = new Mock(); - - var conf = new HttpConfiguration(); - var builder = new ContainerBuilder(); - builder.RegisterInstance(_cache.Object); - - conf.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build()); - conf.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{action}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - - _server = new HttpServer(conf); - } - - [Test] - public void set_cache_to_predefined_value() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c100_s100").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); - } - - [Test] - public void set_cache_to_predefined_value_c100_s0() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_c100_s0").Result; - - // NOTE: Should we expect the _cache to not be called at all if the ServerTimeSpan is 0? - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s0:application/json")), Times.Once()); - // NOTE: Server timespan is 0, so there should not have been any Add at all. - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s0"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Never()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s0:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(1)), It.Is(x => x == "sample-get_c100_s0")), Times.Never()); - } - - [Test] - public void not_cache_when_request_not_succes() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_request_httpResponseException_noCache").Result; - - _cache.Verify(s => s.Contains(It.IsAny()), Times.Once()); - _cache.Verify(s => s.Add(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); - } - - [Test] - public void not_cache_when_request_exception() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_request_exception_noCache").Result; - - _cache.Verify(s => s.Contains(It.IsAny()), Times.Once()); - _cache.Verify(s => s.Add(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); - } - - [Test] - public void not_cache_add_when_no_content() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_request_noContent").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_request_nocontent:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); - } - - [Test] - public void set_cache_to_predefined_value_respect_formatter_through_accept_header() - { - var client = new HttpClient(_server); - var req = new HttpRequestMessage(HttpMethod.Get, _url + "Get_c100_s100"); - req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml")); - var result = client.SendAsync(req).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); - } - - [Test] - public void set_cache_to_predefined_value_respect_formatter_through_content_type() - { - var client = new HttpClient(_server); - var req = new HttpRequestMessage(HttpMethod.Get, _url + "Get_c100_s100"); - req.Content = new StringContent(""); - req.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml"); - var result = client.SendAsync(req).Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); - } - - [Test] - public void set_cache_dont_exclude_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_false/1?xxx=2").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_false-id=1&xxx=2:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false-id=1&xxx=2:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_false")), Times.Once()); - } - - [Test] - public void set_cache_dont_exclude_querystring_duplicate_action_arg_in_querystring_is_still_excluded() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_false/1?id=1").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_false-id=1:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_false")), Times.Once()); - } - - [Test] - public void set_cache_do_exclude_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_true/1?xxx=1").Result; - - //check - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json")), Times.Exactly(2)); - - //base - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - - //actual - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_true")), Times.Once()); - } - - [Test] - public void set_cache_do_exclude_querystring_do_not_exclude_action_arg_even_if_passed_as_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_true?id=1").Result; - - //check - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json")), Times.Exactly(2)); - - //base - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - - //actual - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_true")), Times.Once()); - } - - [Test] - public void callback_at_the_end_is_excluded_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?id=1&callback=abc").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); - } - - [Test] - public void callback_at_the_beginning_is_excluded_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?callback=abc&id=1").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); - } - - [Test] - public void callback_in_the_middle_is_excluded_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?de=xxx&callback=abc&id=1").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1&de=xxx:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1&de=xxx:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); - } - - [Test] - public void callback_alone_is_excluded_querystring() - { - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?callback=abc").Result; - - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); - } - - [Test] - public void no_caching_if_user_authenticated_and_flag_set_to_off() - { - SetCurrentThreadIdentity("Filip"); - var client = new HttpClient(_server); - var result = client.GetAsync(_url + "Get_s50_c50_anonymousonly").Result; - - Assert.True(result.IsSuccessStatusCode); - Assert.IsNull(result.Headers.CacheControl); - _cache.Verify(s => s.Add(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); - } - - [Test] - public void etag_match_304_if_none_match() - { - _cache.Setup(x => x.Contains(It.Is(i => i.Contains("etag_match_304")))).Returns(true); - _cache.Setup(x => x.Get(It.Is(i => i.Contains("etag_match_304") && i.Contains(Constants.EtagKey)))) - .Returns(@"""abc"""); - - var client = new HttpClient(_server); - var req = new HttpRequestMessage(HttpMethod.Get, _url + "etag_match_304"); - req.Headers.IfNoneMatch.Add(new EntityTagHeaderValue(@"""abc""")); - var result = client.SendAsync(req).Result; - - Assert.AreEqual(TimeSpan.FromSeconds(50), result.Headers.CacheControl.MaxAge); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - Assert.AreEqual(HttpStatusCode.NotModified, result.StatusCode); - } - - [Test] - public void etag_not_match_304_if_none_match() - { - _cache.Setup(x => x.Contains(It.Is(i => i.Contains("etag_match_304")))).Returns(true); - _cache.Setup(x => x.Get(It.Is(i => i.Contains("etag_match_304") && i.Contains(Constants.EtagKey)))) - .Returns((object)new EntityTagHeaderValue(@"""abcdef""")); - - var client = new HttpClient(_server); - var req = new HttpRequestMessage(HttpMethod.Get, _url + "etag_match_304"); - req.Headers.IfNoneMatch.Add(new EntityTagHeaderValue(@"""abc""")); - var result = client.SendAsync(req).Result; - - Assert.AreEqual(TimeSpan.FromSeconds(50), result.Headers.CacheControl.MaxAge); - Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); - Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); - } - - - //[Test] - //public void must_add_querystring_to_cache_params() - //{ - // var client = new HttpClient(_server); - // var result = client.GetAsync(_url + "cachekey/get_custom_key").Result; - - // _cache.Verify(s => s.Contains(It.Is(x => x == "custom_key")), Times.Exactly(2)); - // _cache.Verify(s => s.Add(It.Is(x => x == "custom_key"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "cachekey-get_custom_key")), Times.Once()); - // _cache.Verify(s => s.Add(It.Is(x => x == "custom_key:response-ct"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "cachekey-get_custom_key")), Times.Once()); - //} - - [TearDown] - public void fixture_dispose() - { - if (_server != null) _server.Dispose(); - } - - private static void SetCurrentThreadIdentity(string username) - { - var customIdentity = new Mock(); - customIdentity.SetupGet(x => x.IsAuthenticated).Returns(true); - var threadCurrentPrincipal = new GenericPrincipal(customIdentity.Object, new string[] { "CustomUser" }); - Thread.CurrentPrincipal = threadCurrentPrincipal; - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/TestControllers/AutoInvalidateController.cs b/test/WebAPI.OutputCache.Tests/TestControllers/AutoInvalidateController.cs deleted file mode 100644 index dd88c34..0000000 --- a/test/WebAPI.OutputCache.Tests/TestControllers/AutoInvalidateController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Web.Http; - -namespace WebAPI.OutputCache.Tests.TestControllers -{ - [AutoInvalidateCacheOutput] - public class AutoInvalidateController : ApiController - { - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_c100_s100() - { - return "test"; - } - - [CacheOutput(ServerTimeSpan = 50)] - public string Get_s50_exclude_fakecallback(int id = 0, string callback = null, string de = null) - { - return "test"; - } - - [HttpGet] - [CacheOutput(AnonymousOnly = true, ClientTimeSpan = 50, ServerTimeSpan = 50)] - public string etag_match_304() - { - return "value"; - } - - public void Post() - { - //do nothing - } - - public void Put() - { - //do nothing - } - - public void Delete() - { - //do nothing - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/TestControllers/AutoInvalidateWithTypeController.cs b/test/WebAPI.OutputCache.Tests/TestControllers/AutoInvalidateWithTypeController.cs deleted file mode 100644 index 5a0a2eb..0000000 --- a/test/WebAPI.OutputCache.Tests/TestControllers/AutoInvalidateWithTypeController.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Generic; -using System.Web.Http; - -namespace WebAPI.OutputCache.Tests.TestControllers -{ - [AutoInvalidateCacheOutput(TryMatchType = true)] - public class AutoInvalidateWithTypeController : ApiController - { - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_c100_s100() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public List Get_c100_s100_array() - { - return new List {"test"}; - } - - [CacheOutput(ServerTimeSpan = 50)] - public int Get_s50_exclude_fakecallback(int id = 0, string callback = null, string de = null) - { - return 7; - } - - public void Post() - { - //this should not invalidate - } - - public void PostString([FromBody]string x) - { - //this should invalidate string & ienumerable - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/TestControllers/CacheKeyController.cs b/test/WebAPI.OutputCache.Tests/TestControllers/CacheKeyController.cs deleted file mode 100644 index 920a1fb..0000000 --- a/test/WebAPI.OutputCache.Tests/TestControllers/CacheKeyController.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Net.Http.Headers; -using System.Web.Http; -using System.Web.Http.Controllers; - -namespace WebAPI.OutputCache.Tests.TestControllers -{ - public class CacheKeyController : ApiController - { - private class UnregisteredCacheKeyGenerator : ICacheKeyGenerator - { - public string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false) - { - return "unregistered"; - } - } - - [CacheOutput(CacheKeyGenerator = typeof(CacheKeyGeneratorTests.CustomCacheKeyGenerator), ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_custom_key() - { - return "test"; - } - - [CacheOutput(CacheKeyGenerator = typeof(UnregisteredCacheKeyGenerator))] - public string Get_unregistered() - { - return "test"; - } - - [CacheOutput(CacheKeyGenerator = typeof(CacheKeyGeneratorRegistrationTests.InternalRegisteredCacheKeyGenerator), ServerTimeSpan = 100)] - public string Get_internalregistered() - { - return "test"; - } - } -} diff --git a/test/WebAPI.OutputCache.Tests/TestControllers/InlineInvalidateController.cs b/test/WebAPI.OutputCache.Tests/TestControllers/InlineInvalidateController.cs deleted file mode 100644 index 4ca6197..0000000 --- a/test/WebAPI.OutputCache.Tests/TestControllers/InlineInvalidateController.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Web.Http; - -namespace WebAPI.OutputCache.Tests.TestControllers -{ - public class InlineInvalidateController : ApiController - { - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_c100_s100() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_c100_s100_with_param(int id) - { - return "test"; - } - - [ActionName("getById")] - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_c100_s100(int id) - { - return "test"; - } - - [CacheOutput(ServerTimeSpan = 50)] - public string Get_s50_exclude_fakecallback(int id = 0, string callback = null, string de = null) - { - return "test"; - } - - [HttpGet] - [CacheOutput(AnonymousOnly = true, ClientTimeSpan = 50, ServerTimeSpan = 50)] - public string etag_match_304() - { - return "value"; - } - - public void Post() - { - var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request); - cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey("InlineInvalidate", "Get_c100_s100")); - - //do nothing - } - - public void Put() - { - var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request); - cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey((InlineInvalidateController x) => x.Get_c100_s100())); - - //do nothing - } - - public void Delete_non_standard_name() - { - var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request); - cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey((InlineInvalidateController x) => x.Get_c100_s100(7))); - } - - public void Delete_parameterized() - { - var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request); - cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey((InlineInvalidateController x) => x.Get_c100_s100_with_param(7))); - - //do nothing - } - } -} \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/TestControllers/SampleController.cs b/test/WebAPI.OutputCache.Tests/TestControllers/SampleController.cs deleted file mode 100644 index 230e762..0000000 --- a/test/WebAPI.OutputCache.Tests/TestControllers/SampleController.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System.Net; -using System.Net.Http; -using System.Web.Http; -using WebAPI.OutputCache.TimeAttributes; - -namespace WebAPI.OutputCache.Tests.TestControllers -{ - public class SampleController : ApiController - { - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 100)] - public string Get_c100_s100() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 100, ServerTimeSpan = 0)] - public string Get_c100_s0() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 0, ServerTimeSpan = 100)] - public string Get_c0_s100() - { - return "test"; - } - - [CacheOutput(NoCache=true)] - public string Get_nocache() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 0, ServerTimeSpan = 100, MustRevalidate = true)] - public string Get_c0_s100_mustR() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 50, MustRevalidate = true)] - public string Get_c50_mustR() - { - return "test"; - } - - [CacheOutput(ClientTimeSpan = 50, Private = true)] - public string Get_c50_private() - { - return "test"; - } - - [CacheOutput(Private = true)] - public string Get_private() - { - return "test"; - } - - [CacheOutput(ServerTimeSpan = 50)] - public string Get_s50_exclude_fakecallback(int? id = null, string callback = null, string de = null) - { - return "test"; - } - - [CacheOutput(ServerTimeSpan = 50, ExcludeQueryStringFromCacheKey = false)] - public string Get_s50_exclude_false(int id) - { - return "test"+id; - } - - [CacheOutput(ServerTimeSpan = 50, ExcludeQueryStringFromCacheKey = true)] - public string Get_s50_exclude_true(int id) - { - return "test" + id; - } - - [CacheOutputUntil(2015,01,25,17,00)] - public string Get_until25012015_1700() - { - return "test"; - } - - [CacheOutputUntilToday(23,55)] - public string Get_until2355_today() - { - return "value"; - } - - [CacheOutputUntilThisMonth(27)] - public string Get_until27_thismonth() - { - return "value"; - } - - [CacheOutputUntilThisYear(7,31)] - public string Get_until731_thisyear() - { - return "value"; - } - - [CacheOutputUntilThisYear(7, 31, MustRevalidate = true)] - public string Get_until731_thisyear_mustrevalidate() - { - return "value"; - } - - [CacheOutput(AnonymousOnly = true, ClientTimeSpan = 50, ServerTimeSpan = 50)] - public string Get_s50_c50_anonymousonly() - { - return "value"; - } - - [HttpGet] - [CacheOutput(AnonymousOnly = true, ClientTimeSpan = 50, ServerTimeSpan = 50)] - public string etag_match_304() - { - return "value"; - } - - [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)] - public string Get_request_exception_noCache() - { - throw new System.Exception("Fault shouldn't cache"); - } - - [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)] - public string Get_request_httpResponseException_noCache() - { - throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Conflict){ReasonPhrase = "Fault shouldn't cache"}); - } - - [CacheOutput(ClientTimeSpan = 50, ServerTimeSpan = 50)] - public HttpResponseMessage Get_request_noContent() - { - return Request.CreateResponse(HttpStatusCode.Accepted); - } - - [InvalidateCacheOutput("Get_c100_s100")] - public void Post() - { - //do nothing - } - - [InvalidateCacheOutput("Get_c100_s100")] - [InvalidateCacheOutput("Get_s50_exclude_fakecallback")] - public void Post_2_invalidates() - { - //do nothing - } - } -} diff --git a/test/WebAPI.OutputCache.Tests/WebAPI.OutputCache.Tests.csproj b/test/WebAPI.OutputCache.Tests/WebAPI.OutputCache.Tests.csproj deleted file mode 100644 index 94c67b6..0000000 --- a/test/WebAPI.OutputCache.Tests/WebAPI.OutputCache.Tests.csproj +++ /dev/null @@ -1,124 +0,0 @@ - - - - - Debug - AnyCPU - {C5DFB349-FA13-41A1-9F11-332E88664DF7} - Library - Properties - WebAPI.OutputCache.Tests - WebAPI.OutputCache.Tests - v4.0 - 512 - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\Autofac.3.0.0-beta2\lib\net40\Autofac.dll - - - ..\..\packages\Autofac.3.0.0-beta2\lib\net40\Autofac.Configuration.dll - - - ..\..\packages\Autofac.WebApi.3.0.0-beta2\lib\net40\Autofac.Integration.WebApi.dll - - - ..\..\packages\Moq.4.0.10827\lib\NET40\Moq.dll - - - ..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll - - - False - ..\..\packages\NUnit.2.6.2\lib\nunit.framework.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 - - - - - - - - - - - - Code - - - Code - - - Code - - - Code - - - Code - - - Code - - - - - - - - Code - - - - - {3e45fa0b-c465-4de9-9bc3-40a606b73e84} - WebApi.OutputCache.Core - - - {4f32dc89-081b-4264-92f8-f3371a088eb4} - WebApi.OutputCache - - - - - Designer - - - - - - \ No newline at end of file diff --git a/test/WebAPI.OutputCache.Tests/packages.config b/test/WebAPI.OutputCache.Tests/packages.config deleted file mode 100644 index 8193585..0000000 --- a/test/WebAPI.OutputCache.Tests/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/test/WebApi.OutputCache.V2.Tests/ClientSideTests.cs b/test/WebApi.OutputCache.V2.Tests/ClientSideTests.cs index c16eb13..845b9ac 100644 --- a/test/WebApi.OutputCache.V2.Tests/ClientSideTests.cs +++ b/test/WebApi.OutputCache.V2.Tests/ClientSideTests.cs @@ -123,7 +123,7 @@ public void maxage_mustrevalidate_headers_correct_with_cacheuntil() { var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_until25012015_1700").Result; - var clientTimeSpanSeconds = new SpecificTime(2015, 01, 25, 17, 0, 0).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds; + var clientTimeSpanSeconds = new SpecificTime(2017, 01, 25, 17, 0, 0).Execute(DateTime.Now).ClientTimeSpan.TotalSeconds; var resultCacheControlSeconds = ((TimeSpan) result.Headers.CacheControl.MaxAge).TotalSeconds; Assert.IsTrue(Math.Round(clientTimeSpanSeconds - resultCacheControlSeconds) == 0); Assert.IsFalse(result.Headers.CacheControl.MustRevalidate); diff --git a/test/WebApi.OutputCache.V2.Tests/ConfigurationTests.cs b/test/WebApi.OutputCache.V2.Tests/ConfigurationTests.cs index 0c940e3..fb894cf 100644 --- a/test/WebApi.OutputCache.V2.Tests/ConfigurationTests.cs +++ b/test/WebApi.OutputCache.V2.Tests/ConfigurationTests.cs @@ -33,10 +33,10 @@ public void cache_singleton_in_pipeline() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_c100_s100").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json; charset=utf-8")), Times.Exactly(2)); var result2 = client.GetAsync(_url + "Get_c100_s100").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(4)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json; charset=utf-8")), Times.Exactly(4)); _server.Dispose(); } diff --git a/test/WebApi.OutputCache.V2.Tests/ConnegTests.cs b/test/WebApi.OutputCache.V2.Tests/ConnegTests.cs index 7515cee..ea51c53 100644 --- a/test/WebApi.OutputCache.V2.Tests/ConnegTests.cs +++ b/test/WebApi.OutputCache.V2.Tests/ConnegTests.cs @@ -42,15 +42,15 @@ public void subsequent_xml_request_is_not_cached() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_c100_s100").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:application/json"), It.IsAny(), It.Is(x => x < DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json; charset=utf-8")), Times.Exactly(2)); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x < DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); var req = new HttpRequestMessage(HttpMethod.Get, _url + "Get_c100_s100"); req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml")); var result2 = client.SendAsync(req).Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml")), Times.Exactly(2)); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml"), It.IsAny(), It.Is(x => x < DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml; charset=utf-8")), Times.Exactly(2)); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml; charset=utf-8"), It.IsAny(), It.Is(x => x < DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); } diff --git a/test/WebApi.OutputCache.V2.Tests/ServerSideTests.cs b/test/WebApi.OutputCache.V2.Tests/ServerSideTests.cs index cf8044d..4d0dc88 100644 --- a/test/WebApi.OutputCache.V2.Tests/ServerSideTests.cs +++ b/test/WebApi.OutputCache.V2.Tests/ServerSideTests.cs @@ -48,9 +48,9 @@ public void set_cache_to_predefined_value() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_c100_s100").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); } [Test] @@ -60,10 +60,10 @@ public void set_cache_to_predefined_value_c100_s0() var result = client.GetAsync(_url + "Get_c100_s0").Result; // NOTE: Should we expect the _cache to not be called at all if the ServerTimeSpan is 0? - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s0:application/json")), Times.Once()); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s0:application/json; charset=utf-8")), Times.Once()); // NOTE: Server timespan is 0, so there should not have been any Add at all. _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s0"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Never()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s0:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(1)), It.Is(x => x == "sample-get_c100_s0")), Times.Never()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s0:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(1)), It.Is(x => x == "sample-get_c100_s0")), Times.Never()); } [Test] @@ -92,7 +92,7 @@ public void not_cache_add_when_no_content() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_request_noContent").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_request_nocontent:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_request_nocontent:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); } @@ -104,9 +104,9 @@ public void set_cache_to_predefined_value_respect_formatter_through_accept_heade req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml")); var result = client.SendAsync(req).Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Once()); } [Test] @@ -118,9 +118,9 @@ public void set_cache_to_predefined_value_respect_formatter_through_content_type req.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml"); var result = client.SendAsync(req).Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_c100_s100:text/xml; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_c100_s100:text/xml; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(100)), It.Is(x => x == "sample-get_c100_s100")), Times.Exactly(1)); } [Test] @@ -129,9 +129,9 @@ public void set_cache_dont_exclude_querystring() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_s50_exclude_false/1?xxx=2").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_false-id=1&xxx=2:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_false-id=1&xxx=2:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false-id=1&xxx=2:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_false")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false-id=1&xxx=2:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_false")), Times.Once()); } [Test] @@ -140,9 +140,9 @@ public void set_cache_dont_exclude_querystring_duplicate_action_arg_in_querystri var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_s50_exclude_false/1?id=1").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_false-id=1:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_false-id=1:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_false")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_false-id=1:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_false")), Times.Once()); } [Test] @@ -152,13 +152,13 @@ public void set_cache_do_exclude_querystring() var result = client.GetAsync(_url + "Get_s50_exclude_true/1?xxx=1").Result; //check - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json; charset=utf-8")), Times.Exactly(2)); //base _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); //actual - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_true")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_true")), Times.Once()); } [Test] @@ -168,13 +168,13 @@ public void set_cache_do_exclude_querystring_do_not_exclude_action_arg_even_if_p var result = client.GetAsync(_url + "Get_s50_exclude_true?id=1").Result; //check - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json; charset=utf-8")), Times.Exactly(2)); //base _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); //actual - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_true")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_true-id=1:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_true")), Times.Once()); } [Test] @@ -183,9 +183,9 @@ public void callback_at_the_end_is_excluded_querystring() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?id=1&callback=abc").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); } [Test] @@ -194,9 +194,9 @@ public void callback_at_the_beginning_is_excluded_querystring() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?callback=abc&id=1").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); } [Test] @@ -205,9 +205,9 @@ public void callback_in_the_middle_is_excluded_querystring() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?de=xxx&callback=abc&id=1").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1&de=xxx:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1&de=xxx:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1&de=xxx:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback-id=1&de=xxx:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); } [Test] @@ -216,9 +216,9 @@ public void callback_alone_is_excluded_querystring() var client = new HttpClient(_server); var result = client.GetAsync(_url + "Get_s50_exclude_fakecallback?callback=abc").Result; - _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback:application/json")), Times.Exactly(2)); + _cache.Verify(s => s.Contains(It.Is(x => x == "sample-get_s50_exclude_fakecallback:application/json; charset=utf-8")), Times.Exactly(2)); _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), null), Times.Once()); - _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback:application/json"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); + _cache.Verify(s => s.Add(It.Is(x => x == "sample-get_s50_exclude_fakecallback:application/json; charset=utf-8"), It.IsAny(), It.Is(x => x <= DateTime.Now.AddSeconds(50)), It.Is(x => x == "sample-get_s50_exclude_fakecallback")), Times.Once()); } [Test] diff --git a/test/WebApi.OutputCache.V2.Tests/TestControllers/SampleController.cs b/test/WebApi.OutputCache.V2.Tests/TestControllers/SampleController.cs index 15de43b..88bcaec 100644 --- a/test/WebApi.OutputCache.V2.Tests/TestControllers/SampleController.cs +++ b/test/WebApi.OutputCache.V2.Tests/TestControllers/SampleController.cs @@ -73,7 +73,7 @@ public string Get_s50_exclude_true(int id) return "test" + id; } - [CacheOutputUntil(2015,01,25,17,00)] + [CacheOutputUntil(2017,01,25,17,00)] public string Get_until25012015_1700() { return "test"; diff --git a/test/WebApi.OutputCache.V2.Tests/WebApi.OutputCache.V2.Tests.csproj b/test/WebApi.OutputCache.V2.Tests/WebApi.OutputCache.V2.Tests.csproj index 4bcee4b..aeb85fa 100644 --- a/test/WebApi.OutputCache.V2.Tests/WebApi.OutputCache.V2.Tests.csproj +++ b/test/WebApi.OutputCache.V2.Tests/WebApi.OutputCache.V2.Tests.csproj @@ -46,9 +46,9 @@ ..\..\packages\Moq.4.0.10827\lib\NET40\Moq.dll - - False + ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + True False @@ -57,13 +57,13 @@ - - False - ..\..\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 - - False - ..\..\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 @@ -102,6 +102,7 @@ + diff --git a/test/WebApi.OutputCache.V2.Tests/app.config b/test/WebApi.OutputCache.V2.Tests/app.config new file mode 100644 index 0000000..7e9deb7 --- /dev/null +++ b/test/WebApi.OutputCache.V2.Tests/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/WebApi.OutputCache.V2.Tests/packages.config b/test/WebApi.OutputCache.V2.Tests/packages.config index d36a76b..e313f79 100644 --- a/test/WebApi.OutputCache.V2.Tests/packages.config +++ b/test/WebApi.OutputCache.V2.Tests/packages.config @@ -1,10 +1,10 @@  - - - - - - - + + + + + + + \ No newline at end of file