Browse Source

[CacheControl] Can use custom connection string; tests; can use post data

feature/authentication
Robin Thoni 9 years ago
parent
commit
54a2768262

+ 5
- 2
CacheControl-test/Controllers/MyCacheOutputAttribute.cs View File

@@ -1,4 +1,4 @@
1
-using CacheControl.DBO;
1
+using System.Configuration;
2 2
 using iiie.CacheControl.Business.Attributes;
3 3
 using iiie.CacheControl.Business.OutputCache;
4 4
 
@@ -6,9 +6,12 @@ namespace CacheControl_test.Controllers
6 6
 {
7 7
     public class MyCacheOutputAttribute : TimeCacheControlAttribute
8 8
     {
9
-        public MyCacheOutputAttribute(int seconds) : base(seconds)
9
+        public MyCacheOutputAttribute(int seconds, bool excludeGet = false, bool excludePost = false) : base(seconds)
10 10
         {
11 11
             CacheType = OutputCacheType.DataBase;
12
+            ExcludePostFromCacheKey = excludePost;
13
+            ExcludeQueryStringFromCacheKey = excludeGet;
14
+            OutputCacheData = ConfigurationManager.ConnectionStrings["ConnectionString42"].ConnectionString;
12 15
         }
13 16
     }
14 17
 }

+ 13
- 9
CacheControl-test/Controllers/ValuesController.cs View File

@@ -6,31 +6,35 @@ namespace CacheControl_test.Controllers
6 6
     public class ValuesController : ApiController
7 7
     {
8 8
         // GET api/values
9
+        // Ignore all parameters
10
+        [MyCacheOutput(30, true, true)]
9 11
         public IEnumerable<string> Get()
10 12
         {
11 13
             return new string[] { "value1", "value2" };
12 14
         }
13 15
 
14 16
         // GET api/values/5
15
-        [MyCacheOutput(60)]
17
+        // Ignore post
18
+        [MyCacheOutput(30, false, true)]
16 19
         public string Get(int id)
17 20
         {
18
-            return "value";
21
+            return "get value";
19 22
         }
20 23
 
21 24
         // POST api/values
22
-        public void Post([FromBody]string value)
25
+        // Ignore get
26
+        [MyCacheOutput(30, true)]
27
+        public string Post([FromBody]IEnumerable<int> value)
23 28
         {
29
+            return "post value";
24 30
         }
25 31
 
26 32
         // PUT api/values/5
27
-        public void Put(int id, [FromBody]string value)
28
-        {
29
-        }
30
-
31
-        // DELETE api/values/5
32
-        public void Delete(int id)
33
+        // cache all
34
+        [MyCacheOutput(30)]
35
+        public string Put([FromUri]int id, [FromBody]string value)
33 36
         {
37
+            return "put";
34 38
         }
35 39
     }
36 40
 }

+ 1
- 1
CacheControl-test/Web.config View File

@@ -59,7 +59,7 @@
59 59
     </handlers>
60 60
   </system.webServer>
61 61
   <connectionStrings>
62
-    <add name="CacheControlEntities" connectionString="metadata=res://*/DataAccess.CacheEntities.csdl|res://*/DataAccess.CacheEntities.ssdl|res://*/DataAccess.CacheEntities.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=CacheControl;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
62
+    <add name="ConnectionString42" connectionString="metadata=res://*/DataAccess.CacheEntities.csdl|res://*/DataAccess.CacheEntities.ssdl|res://*/DataAccess.CacheEntities.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=CacheControl;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
63 63
   </connectionStrings>
64 64
   <entityFramework>
65 65
     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">

+ 15
- 8
CacheControl/Business/Attributes/CacheControlAttribute.cs View File

@@ -32,6 +32,16 @@ namespace iiie.CacheControl.Attributes
32 32
         /// </summary>
33 33
         protected bool ExcludeQueryStringFromCacheKey { get; set; }
34 34
 
35
+        /// <summary>
36
+        /// Indicates if the post data must be used to control cache
37
+        /// </summary>
38
+        protected bool ExcludePostFromCacheKey { get; set; }
39
+
40
+        /// <summary>
41
+        /// Optionnal data used by ouput cache backend
42
+        /// </summary>
43
+        public object OutputCacheData { get; set; }
44
+
35 45
         /// <summary>
36 46
         /// Define the cache type used to store cache
37 47
         /// </summary>
@@ -43,11 +53,6 @@ namespace iiie.CacheControl.Attributes
43 53
 
44 54
         private IOutputCache _webCache;
45 55
 
46
-        protected void EnsureCache(HttpConfiguration config, HttpRequestMessage req)
47
-        {
48
-            _webCache = config.CacheOutputConfiguration(CacheType).GetCacheOutputProvider(req);
49
-        }
50
-
51 56
         protected abstract bool IsValid(CacheDbo data);
52 57
 
53 58
         protected virtual CacheDbo CreateCacheUser()
@@ -91,13 +96,14 @@ namespace iiie.CacheControl.Attributes
91 96
 
92 97
             var config = actionContext.Request.GetConfiguration();
93 98
 
94
-            EnsureCache(config, actionContext.Request);
99
+            _webCache = config.CacheOutputConfiguration(CacheType).GetCacheOutputProvider(actionContext.Request, OutputCacheData);
95 100
 
96 101
             var cacheKeyGenerator = config.CacheOutputConfiguration(CacheType).GetCacheKeyGenerator(actionContext.Request, CacheKeyGenerator);
97 102
 
98 103
             _responseMediaType = GetExpectedMediaType(config, actionContext);
99 104
 
100
-            var cachekey = cacheKeyGenerator.MakeCacheKey(actionContext, _responseMediaType, CacheType, ExcludeQueryStringFromCacheKey);
105
+            var cachekey = cacheKeyGenerator.MakeCacheKey(actionContext, _responseMediaType, CacheType,
106
+                ExcludeQueryStringFromCacheKey, ExcludePostFromCacheKey);
101 107
 
102 108
             var data = _webCache.Get(cachekey);
103 109
             if (data == null)
@@ -141,7 +147,8 @@ namespace iiie.CacheControl.Attributes
141 147
             var config = actionExecutedContext.Request.GetConfiguration().CacheOutputConfiguration(CacheType);
142 148
             var cacheKeyGenerator = config.GetCacheKeyGenerator(actionExecutedContext.Request, CacheKeyGenerator);
143 149
 
144
-            var cachekey = cacheKeyGenerator.MakeCacheKey(actionExecutedContext.ActionContext, _responseMediaType, CacheType, ExcludeQueryStringFromCacheKey);
150
+            var cachekey = cacheKeyGenerator.MakeCacheKey(actionExecutedContext.ActionContext, _responseMediaType,
151
+                CacheType, ExcludeQueryStringFromCacheKey, ExcludePostFromCacheKey);
145 152
 
146 153
             if (!string.IsNullOrWhiteSpace(cachekey) && !(_webCache.Contains(cachekey)))
147 154
             {

+ 0
- 1
CacheControl/Business/Attributes/TimeCacheControlAttribute.cs View File

@@ -1,6 +1,5 @@
1 1
 using System;
2 2
 using iiie.CacheControl.Attributes;
3
-using iiie.CacheControl.Business.OutputCache;
4 3
 using iiie.CacheControl.DBO;
5 4
 
6 5
 namespace iiie.CacheControl.Business.Attributes

+ 13
- 59
CacheControl/Business/CacheKey/DefaultCacheKeyGenerator.cs View File

@@ -1,80 +1,34 @@
1
-using System.Collections;
2
-using System.Collections.Generic;
3
-using System.Linq;
1
+using System.Linq;
4 2
 using System.Net.Http;
5 3
 using System.Net.Http.Headers;
4
+using System.Web;
6 5
 using System.Web.Http.Controllers;
7
-using iiie.CacheControl.Business.HttpExtensions;
8 6
 using iiie.CacheControl.Business.OutputCache;
7
+using Newtonsoft.Json;
9 8
 
10 9
 namespace iiie.CacheControl.Business.CacheKey
11 10
 {
12 11
     public class DefaultCacheKeyGenerator : ICacheKeyGenerator
13 12
     {
14
-        public virtual string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, OutputCacheType cacheType, bool excludeQueryString = false)
13
+        public virtual string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType,
14
+            OutputCacheType cacheType, bool excludeQueryString = false, bool excludePost = false)
15 15
         {
16
-            var controller = context.ControllerContext.ControllerDescriptor.ControllerName;
17
-            var action = context.ActionDescriptor.ActionName;
18
-            var key = context.Request.GetConfiguration().CacheOutputConfiguration(cacheType).MakeBaseCachekey(controller, action);
19
-            var actionParameters = context.ActionArguments.Where(x => x.Value != null).Select(x => x.Key + "=" + GetValue(x.Value));
20
-
21
-            string parameters;
16
+            string parameters = context.Request.Method.Method + "-" + context.Request.RequestUri.AbsolutePath;
22 17
 
23 18
             if (!excludeQueryString)
24 19
             {
25
-                var queryStringParameters =
26
-                    context.Request.GetQueryNameValuePairs()
27
-                           .Where(x => x.Key.ToLower() != "callback" && x.Key.ToLower() != "_")
28
-                           .Select(x => x.Key + "=" + x.Value);
29
-                var parametersCollections = actionParameters.Union(queryStringParameters);
30
-                parameters = "-" + string.Join("&", parametersCollections);
31
-
32
-                var callbackValue = GetJsonpCallback(context.Request);
33
-                if (!string.IsNullOrWhiteSpace(callbackValue))
34
-                {
35
-                    var callback = "callback=" + callbackValue;
36
-                    if (parameters.Contains("&" + callback)) parameters = parameters.Replace("&" + callback, string.Empty);
37
-                    if (parameters.Contains(callback + "&")) parameters = parameters.Replace(callback + "&", string.Empty);
38
-                    if (parameters.Contains("-" + callback)) parameters = parameters.Replace("-" + callback, string.Empty);
39
-                    if (parameters.EndsWith("&")) parameters = parameters.TrimEnd('&');
40
-                }
20
+                var pairs = context.Request.GetQueryNameValuePairs().OrderBy(x => x.Key);
21
+                parameters += "?" + string.Join("&", pairs.Select(x => HttpUtility.UrlEncode(x.Key)
22
+                    + "=" + HttpUtility.UrlEncode(x.Value)));
41 23
             }
42
-            else
24
+            if (!excludePost)
43 25
             {
44
-                parameters = "-" + string.Join("&", actionParameters);
26
+                parameters += "?" + string.Join("&", context.ActionArguments.Select(x => HttpUtility.UrlEncode(x.Key)
27
+                    + "=" + HttpUtility.UrlEncode(JsonConvert.SerializeObject(x.Value))));
45 28
             }
46 29
 
47
-            if (parameters == "-") parameters = string.Empty;
48
-
49
-            var cachekey = string.Format("{0}{1}:{2}", key, parameters, mediaType.MediaType);
30
+            var cachekey = string.Format("{0}:{1}", parameters, mediaType.MediaType);
50 31
             return cachekey;
51 32
         }
52
-
53
-        private string GetJsonpCallback(HttpRequestMessage request)
54
-        {
55
-            var callback = string.Empty;
56
-            if (request.Method == HttpMethod.Get)
57
-            {
58
-                var query = request.GetQueryNameValuePairs();
59
-
60
-                if (query != null)
61
-                {
62
-                    var queryVal = query.FirstOrDefault(x => x.Key.ToLower() == "callback");
63
-                    if (!queryVal.Equals(default(KeyValuePair<string, string>))) callback = queryVal.Value;
64
-                }
65
-            }
66
-            return callback;
67
-        }
68
-
69
-        private string GetValue(object val)
70
-        {
71
-            if (val is IEnumerable && !(val is string))
72
-            {
73
-                var concatValue = string.Empty;
74
-                var paramArray = val as IEnumerable;
75
-                return paramArray.Cast<object>().Aggregate(concatValue, (current, paramValue) => current + (paramValue + ";"));
76
-            }
77
-            return val.ToString();
78
-        }
79 33
     }
80 34
 }

+ 2
- 1
CacheControl/Business/CacheKey/ICacheKeyGenerator.cs View File

@@ -6,6 +6,7 @@ namespace iiie.CacheControl.Business.CacheKey
6 6
 {
7 7
     public interface ICacheKeyGenerator
8 8
     {
9
-        string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, OutputCacheType cacheType, bool excludeQueryString = false);
9
+        string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType,
10
+            OutputCacheType cacheType, bool excludeQueryString = false, bool excludePost = false);
10 11
     }
11 12
 }

+ 4
- 43
CacheControl/Business/HttpExtensions/CacheOutputConfiguration.cs View File

@@ -1,10 +1,8 @@
1 1
 using System;
2 2
 using System.Linq;
3
-using System.Linq.Expressions;
4 3
 using System.Net.Http;
5 4
 using System.Reflection;
6 5
 using System.Web.Http;
7
-using CacheControl.DBO;
8 6
 using iiie.CacheControl.Business.CacheKey;
9 7
 using iiie.CacheControl.Business.OutputCache;
10 8
 
@@ -22,46 +20,6 @@ namespace iiie.CacheControl.Business.HttpExtensions
22 20
             _cacheType = type;
23 21
         }
24 22
 
25
-        public void RegisterCacheOutputProvider(Func<IOutputCache> provider)
26
-        {
27
-            _configuration.Properties.GetOrAdd(typeof(IOutputCache), x => provider);
28
-        }
29
-
30
-        public void RegisterCacheKeyGeneratorProvider<T>(Func<T> provider)
31
-            where T : ICacheKeyGenerator
32
-        {
33
-            _configuration.Properties.GetOrAdd(typeof(T), x => provider);
34
-        }
35
-
36
-        public void RegisterDefaultCacheKeyGeneratorProvider(Func<ICacheKeyGenerator> provider)
37
-        {
38
-            RegisterCacheKeyGeneratorProvider(provider);
39
-        }
40
-
41
-        public string MakeBaseCachekey(string controller, string action)
42
-        {
43
-            return string.Format("{0}-{1}", controller.ToLower(), action.ToLower());
44
-        }
45
-
46
-        public string MakeBaseCachekey<T, U>(Expression<Func<T, U>> expression)
47
-        {
48
-            var method = expression.Body as MethodCallExpression;
49
-            if (method == null) throw new ArgumentException("Expression is wrong");
50
-
51
-            var methodName = method.Method.Name;
52
-            var nameAttribs = method.Method.GetCustomAttributes(typeof(ActionNameAttribute), false);
53
-            if (nameAttribs.Any())
54
-            {
55
-                var actionNameAttrib = (ActionNameAttribute)nameAttribs.FirstOrDefault();
56
-                if (actionNameAttrib != null)
57
-                {
58
-                    methodName = actionNameAttrib.Name;
59
-                }
60
-            }
61
-
62
-            return string.Format("{0}-{1}", typeof(T).Name.Replace("Controller", string.Empty).ToLower(), methodName.ToLower());
63
-        }
64
-
65 23
         private static ICacheKeyGenerator TryActivateCacheKeyGenerator(Type generatorType)
66 24
         {
67 25
             var hasEmptyOrDefaultConstructor =
@@ -90,7 +48,7 @@ namespace iiie.CacheControl.Business.HttpExtensions
90 48
                 ?? new DefaultCacheKeyGenerator();
91 49
         }
92 50
 
93
-        public IOutputCache GetCacheOutputProvider(HttpRequestMessage request)
51
+        public IOutputCache GetCacheOutputProvider(HttpRequestMessage request, object outputCacheData)
94 52
         {
95 53
             object cache;
96 54
             _configuration.Properties.TryGetValue(typeof(IOutputCache), out cache);
@@ -101,7 +59,10 @@ namespace iiie.CacheControl.Business.HttpExtensions
101 59
             if (cacheOutputProvider == null)
102 60
             {
103 61
                 if (_cacheType == OutputCacheType.DataBase)
62
+                {
104 63
                     cacheOutputProvider = new DbOutputCache();
64
+                    ((DbOutputCache) cacheOutputProvider).ConnectionString = outputCacheData as string;
65
+                }
105 66
                 else
106 67
                     cacheOutputProvider = new MemoryOutputCache();
107 68
             }

+ 14
- 7
CacheControl/Business/OutputCache/DbOutputCache.cs View File

@@ -1,16 +1,23 @@
1
-using System;
2
-using System.Linq;
3
-using CacheControl.DataAccess;
1
+using System.Linq;
2
+using iiie.CacheControl.DataAccess;
4 3
 using iiie.CacheControl.DBO;
5 4
 
6 5
 namespace iiie.CacheControl.Business.OutputCache
7 6
 {
8 7
     public class DbOutputCache : IOutputCache
9 8
     {
9
+        public string ConnectionString { get; set; }
10
+
11
+        private CacheControlEntities GetDb()
12
+        {
13
+            if (ConnectionString == null)
14
+                return new CacheControlEntities();
15
+            return new CacheControlEntities(ConnectionString);
16
+        }
10 17
 
11 18
         public override CacheDbo Get(string key)
12 19
         {
13
-            using (var db = new CacheControlEntities())
20
+            using (var db = GetDb())
14 21
             {
15 22
                 var item = db.T_Cache.FirstOrDefault(x => x.cachekey == key);
16 23
                 if (item == null)
@@ -27,7 +34,7 @@ namespace iiie.CacheControl.Business.OutputCache
27 34
 
28 35
         public override void Remove(string key)
29 36
         {
30
-            using (var db = new CacheControlEntities())
37
+            using (var db = GetDb())
31 38
             {
32 39
                 var item = db.T_Cache.FirstOrDefault(x => x.cachekey == key);
33 40
                 if (item != null)
@@ -40,7 +47,7 @@ namespace iiie.CacheControl.Business.OutputCache
40 47
 
41 48
         public override bool Contains(string key)
42 49
         {
43
-            using (var db = new CacheControlEntities())
50
+            using (var db = GetDb())
44 51
             {
45 52
                 return db.T_Cache.Any(x => x.cachekey == key);
46 53
             }
@@ -48,7 +55,7 @@ namespace iiie.CacheControl.Business.OutputCache
48 55
 
49 56
         public override void Add(string key, CacheDbo o)
50 57
         {
51
-            using (var db = new CacheControlEntities())
58
+            using (var db = GetDb())
52 59
             {
53 60
                 db.T_Cache.Add(new T_Cache
54 61
                 {

+ 1
- 1
CacheControl/CacheControl.csproj View File

@@ -7,7 +7,7 @@
7 7
     <ProjectGuid>{BA63D177-BE9E-41E0-89F5-3D134A26A604}</ProjectGuid>
8 8
     <OutputType>Library</OutputType>
9 9
     <AppDesignerFolder>Properties</AppDesignerFolder>
10
-    <RootNamespace>CacheControl</RootNamespace>
10
+    <RootNamespace>iiie.CacheControl</RootNamespace>
11 11
     <AssemblyName>CacheControl</AssemblyName>
12 12
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 13
     <FileAlignment>512</FileAlignment>

+ 6
- 1
CacheControl/DataAccess/CacheEntities.Context.cs View File

@@ -7,7 +7,7 @@
7 7
 // </auto-generated>
8 8
 //------------------------------------------------------------------------------
9 9
 
10
-namespace CacheControl.DataAccess
10
+namespace iiie.CacheControl.DataAccess
11 11
 {
12 12
     using System;
13 13
     using System.Data.Entity;
@@ -20,6 +20,11 @@ namespace CacheControl.DataAccess
20 20
         {
21 21
         }
22 22
     
23
+    	public CacheControlEntities(String connectionString)
24
+            : base(connectionString)
25
+        {
26
+    	}
27
+    
23 28
         protected override void OnModelCreating(DbModelBuilder modelBuilder)
24 29
         {
25 30
             throw new UnintentionalCodeFirstException();

+ 5
- 0
CacheControl/DataAccess/CacheEntities.Context.tt View File

@@ -80,6 +80,11 @@ foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
80 80
 #>
81 81
     }
82 82
 
83
+	public <#=code.Escape(container)#>(String connectionString)
84
+        : base(connectionString)
85
+    {
86
+	}
87
+
83 88
     protected override void OnModelCreating(DbModelBuilder modelBuilder)
84 89
     {
85 90
         throw new UnintentionalCodeFirstException();

+ 1
- 1
CacheControl/DataAccess/T_Cache.cs View File

@@ -7,7 +7,7 @@
7 7
 // </auto-generated>
8 8
 //------------------------------------------------------------------------------
9 9
 
10
-namespace CacheControl.DataAccess
10
+namespace iiie.CacheControl.DataAccess
11 11
 {
12 12
     using System;
13 13
     using System.Collections.Generic;

Loading…
Cancel
Save