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
-using CacheControl.DBO;
1
+using System.Configuration;
2
 using iiie.CacheControl.Business.Attributes;
2
 using iiie.CacheControl.Business.Attributes;
3
 using iiie.CacheControl.Business.OutputCache;
3
 using iiie.CacheControl.Business.OutputCache;
4
 
4
 
6
 {
6
 {
7
     public class MyCacheOutputAttribute : TimeCacheControlAttribute
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
             CacheType = OutputCacheType.DataBase;
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
     public class ValuesController : ApiController
6
     public class ValuesController : ApiController
7
     {
7
     {
8
         // GET api/values
8
         // GET api/values
9
+        // Ignore all parameters
10
+        [MyCacheOutput(30, true, true)]
9
         public IEnumerable<string> Get()
11
         public IEnumerable<string> Get()
10
         {
12
         {
11
             return new string[] { "value1", "value2" };
13
             return new string[] { "value1", "value2" };
12
         }
14
         }
13
 
15
 
14
         // GET api/values/5
16
         // GET api/values/5
15
-        [MyCacheOutput(60)]
17
+        // Ignore post
18
+        [MyCacheOutput(30, false, true)]
16
         public string Get(int id)
19
         public string Get(int id)
17
         {
20
         {
18
-            return "value";
21
+            return "get value";
19
         }
22
         }
20
 
23
 
21
         // POST api/values
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
         // PUT api/values/5
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
     </handlers>
59
     </handlers>
60
   </system.webServer>
60
   </system.webServer>
61
   <connectionStrings>
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
   </connectionStrings>
63
   </connectionStrings>
64
   <entityFramework>
64
   <entityFramework>
65
     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
65
     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">

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

32
         /// </summary>
32
         /// </summary>
33
         protected bool ExcludeQueryStringFromCacheKey { get; set; }
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
         /// <summary>
45
         /// <summary>
36
         /// Define the cache type used to store cache
46
         /// Define the cache type used to store cache
37
         /// </summary>
47
         /// </summary>
43
 
53
 
44
         private IOutputCache _webCache;
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
         protected abstract bool IsValid(CacheDbo data);
56
         protected abstract bool IsValid(CacheDbo data);
52
 
57
 
53
         protected virtual CacheDbo CreateCacheUser()
58
         protected virtual CacheDbo CreateCacheUser()
91
 
96
 
92
             var config = actionContext.Request.GetConfiguration();
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
             var cacheKeyGenerator = config.CacheOutputConfiguration(CacheType).GetCacheKeyGenerator(actionContext.Request, CacheKeyGenerator);
101
             var cacheKeyGenerator = config.CacheOutputConfiguration(CacheType).GetCacheKeyGenerator(actionContext.Request, CacheKeyGenerator);
97
 
102
 
98
             _responseMediaType = GetExpectedMediaType(config, actionContext);
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
             var data = _webCache.Get(cachekey);
108
             var data = _webCache.Get(cachekey);
103
             if (data == null)
109
             if (data == null)
141
             var config = actionExecutedContext.Request.GetConfiguration().CacheOutputConfiguration(CacheType);
147
             var config = actionExecutedContext.Request.GetConfiguration().CacheOutputConfiguration(CacheType);
142
             var cacheKeyGenerator = config.GetCacheKeyGenerator(actionExecutedContext.Request, CacheKeyGenerator);
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
             if (!string.IsNullOrWhiteSpace(cachekey) && !(_webCache.Contains(cachekey)))
153
             if (!string.IsNullOrWhiteSpace(cachekey) && !(_webCache.Contains(cachekey)))
147
             {
154
             {

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

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

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

1
-using System.Collections;
2
-using System.Collections.Generic;
3
-using System.Linq;
1
+using System.Linq;
4
 using System.Net.Http;
2
 using System.Net.Http;
5
 using System.Net.Http.Headers;
3
 using System.Net.Http.Headers;
4
+using System.Web;
6
 using System.Web.Http.Controllers;
5
 using System.Web.Http.Controllers;
7
-using iiie.CacheControl.Business.HttpExtensions;
8
 using iiie.CacheControl.Business.OutputCache;
6
 using iiie.CacheControl.Business.OutputCache;
7
+using Newtonsoft.Json;
9
 
8
 
10
 namespace iiie.CacheControl.Business.CacheKey
9
 namespace iiie.CacheControl.Business.CacheKey
11
 {
10
 {
12
     public class DefaultCacheKeyGenerator : ICacheKeyGenerator
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
             if (!excludeQueryString)
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
             return cachekey;
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
 {
7
     public interface ICacheKeyGenerator
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
 using System;
1
 using System;
2
 using System.Linq;
2
 using System.Linq;
3
-using System.Linq.Expressions;
4
 using System.Net.Http;
3
 using System.Net.Http;
5
 using System.Reflection;
4
 using System.Reflection;
6
 using System.Web.Http;
5
 using System.Web.Http;
7
-using CacheControl.DBO;
8
 using iiie.CacheControl.Business.CacheKey;
6
 using iiie.CacheControl.Business.CacheKey;
9
 using iiie.CacheControl.Business.OutputCache;
7
 using iiie.CacheControl.Business.OutputCache;
10
 
8
 
22
             _cacheType = type;
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
         private static ICacheKeyGenerator TryActivateCacheKeyGenerator(Type generatorType)
23
         private static ICacheKeyGenerator TryActivateCacheKeyGenerator(Type generatorType)
66
         {
24
         {
67
             var hasEmptyOrDefaultConstructor =
25
             var hasEmptyOrDefaultConstructor =
90
                 ?? new DefaultCacheKeyGenerator();
48
                 ?? new DefaultCacheKeyGenerator();
91
         }
49
         }
92
 
50
 
93
-        public IOutputCache GetCacheOutputProvider(HttpRequestMessage request)
51
+        public IOutputCache GetCacheOutputProvider(HttpRequestMessage request, object outputCacheData)
94
         {
52
         {
95
             object cache;
53
             object cache;
96
             _configuration.Properties.TryGetValue(typeof(IOutputCache), out cache);
54
             _configuration.Properties.TryGetValue(typeof(IOutputCache), out cache);
101
             if (cacheOutputProvider == null)
59
             if (cacheOutputProvider == null)
102
             {
60
             {
103
                 if (_cacheType == OutputCacheType.DataBase)
61
                 if (_cacheType == OutputCacheType.DataBase)
62
+                {
104
                     cacheOutputProvider = new DbOutputCache();
63
                     cacheOutputProvider = new DbOutputCache();
64
+                    ((DbOutputCache) cacheOutputProvider).ConnectionString = outputCacheData as string;
65
+                }
105
                 else
66
                 else
106
                     cacheOutputProvider = new MemoryOutputCache();
67
                     cacheOutputProvider = new MemoryOutputCache();
107
             }
68
             }

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

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

+ 1
- 1
CacheControl/CacheControl.csproj View File

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

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

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

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

80
 #>
80
 #>
81
     }
81
     }
82
 
82
 
83
+	public <#=code.Escape(container)#>(String connectionString)
84
+        : base(connectionString)
85
+    {
86
+	}
87
+
83
     protected override void OnModelCreating(DbModelBuilder modelBuilder)
88
     protected override void OnModelCreating(DbModelBuilder modelBuilder)
84
     {
89
     {
85
         throw new UnintentionalCodeFirstException();
90
         throw new UnintentionalCodeFirstException();

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

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

Loading…
Cancel
Save