web api 缓存类

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Web.Http.Filters;
  6 using System.Net.Http.Headers;
  7 using System.Net.Http;
  8 using System.Threading;
  9 using System.Net.Http.Formatting;
 10 using System.Web.Http.Controllers;
 11 using System.Linq.Expressions;
 12 using System.Reflection;
 13 using System.Threading.Tasks;
 14 using System.Collections;
 15 using System.Net;
 16 using System.Runtime.Caching;
 17 using System.Web.Http;
 18
 19
 20
 21 namespace Cashlibary
 22 {
 23     public class CacheOutputAttribute : ActionFilterAttribute
 24     {
 25         private const string CurrentRequestMediaType = "CacheOutput:CurrentRequestMediaType";
 26         protected static MediaTypeHeaderValue DefaultMediaType = new MediaTypeHeaderValue("application/json") { CharSet = Encoding.UTF8.HeaderName };
 27
 28         /// <summary>
 29         /// Cache enabled only for requests when Thread.CurrentPrincipal is not set
 30         /// </summary>
 31         public bool AnonymousOnly { get; set; }
 32
 33         /// <summary>
 34         /// 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
 35         /// </summary>
 36         public bool MustRevalidate { get; set; }
 37
 38         /// <summary>
 39         /// Do not vary cache by querystring values
 40         /// </summary>
 41         public bool ExcludeQueryStringFromCacheKey { get; set; }
 42
 43         /// <summary>
 44         /// How long response should be cached on the server side (in seconds)
 45         /// </summary>
 46         public int ServerTimeSpan { get; set; }
 47
 48         /// <summary>
 49         /// Corresponds to CacheControl MaxAge HTTP header (in seconds)
 50         /// </summary>
 51         public int ClientTimeSpan { get; set; }
 52
 53         /// <summary>
 54         /// Corresponds to CacheControl NoCache HTTP header
 55         /// </summary>
 56         public bool NoCache { get; set; }
 57
 58         /// <summary>
 59         /// Corresponds to CacheControl Private HTTP header. Response can be cached by browser but not by intermediary cache
 60         /// </summary>
 61         public bool Private { get; set; }
 62
 63         /// <summary>
 64         /// Class used to generate caching keys
 65         /// </summary>
 66         public Type CacheKeyGenerator { get; set; }
 67
 68         // cache repository
 69         private IApiOutputCache _webApiCache;
 70
 71         protected virtual void EnsureCache(HttpConfiguration config, HttpRequestMessage req)
 72         {
 73             _webApiCache = config.CacheOutputConfiguration().GetCacheOutputProvider(req);
 74         }
 75
 76         internal IModelQuery<DateTime, CacheTime> CacheTimeQuery;
 77
 78         protected virtual bool IsCachingAllowed(HttpActionContext actionContext, bool anonymousOnly)
 79         {
 80             if (anonymousOnly)
 81             {
 82                 if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
 83                 {
 84                     return false;
 85                 }
 86             }
 87
 88             if (actionContext.ActionDescriptor.GetCustomAttributes<IgnoreCacheOutputAttribute>().Any())
 89             {
 90                 return false;
 91             }
 92
 93             return actionContext.Request.Method == HttpMethod.Post;
 94         }
 95
 96         protected virtual void EnsureCacheTimeQuery()
 97         {
 98             if (CacheTimeQuery == null) ResetCacheTimeQuery();
 99         }
100
101         protected void ResetCacheTimeQuery()
102         {
103             CacheTimeQuery = new ShortTime(ServerTimeSpan, ClientTimeSpan);
104         }
105
106         protected virtual MediaTypeHeaderValue GetExpectedMediaType(HttpConfiguration config, HttpActionContext actionContext)
107         {
108             MediaTypeHeaderValue responseMediaType = null;
109
110             var negotiator = config.Services.GetService(typeof(IContentNegotiator)) as IContentNegotiator;
111             var returnType = actionContext.ActionDescriptor.ReturnType;
112
113             if (negotiator != null && returnType != typeof(HttpResponseMessage) && (returnType != typeof(IHttpActionResult) || typeof(IHttpActionResult).IsAssignableFrom(returnType)))
114             {
115                 var negotiatedResult = negotiator.Negotiate(returnType, actionContext.Request, config.Formatters);
116
117                 if (negotiatedResult == null)
118                 {
119                     return DefaultMediaType;
120                 }
121
122                 responseMediaType = negotiatedResult.MediaType;
123                 if (string.IsNullOrWhiteSpace(responseMediaType.CharSet))
124                 {
125                     responseMediaType.CharSet = Encoding.UTF8.HeaderName;
126                 }
127             }
128             else
129             {
130                 if (actionContext.Request.Headers.Accept != null)
131                 {
132                     responseMediaType = actionContext.Request.Headers.Accept.FirstOrDefault();
133                     if (responseMediaType == null || !config.Formatters.Any(x => x.SupportedMediaTypes.Contains(responseMediaType)))
134                     {
135                         return DefaultMediaType;
136                     }
137                 }
138             }
139
140             return responseMediaType;
141         }
142
143         public override void OnActionExecuting(HttpActionContext actionContext)
144         {
145             if (actionContext == null) throw new ArgumentNullException("actionContext");
146
147             if (!IsCachingAllowed(actionContext, AnonymousOnly)) return;
148
149             var config = actionContext.Request.GetConfiguration();
150
151             EnsureCacheTimeQuery();
152             EnsureCache(config, actionContext.Request);
153
154             var cacheKeyGenerator = config.CacheOutputConfiguration().GetCacheKeyGenerator(actionContext.Request, CacheKeyGenerator);
155
156             var responseMediaType = GetExpectedMediaType(config, actionContext);
157             actionContext.Request.Properties[CurrentRequestMediaType] = responseMediaType;
158             var cachekey = cacheKeyGenerator.MakeCacheKey(actionContext, responseMediaType, ExcludeQueryStringFromCacheKey);
159
160             if (!_webApiCache.Contains(cachekey)) return;
161
162             if (actionContext.Request.Headers.IfNoneMatch != null)
163             {
164                 var etag = _webApiCache.Get<string>(cachekey + Constants.EtagKey);
165                 if (etag != null)
166                 {
167                     if (actionContext.Request.Headers.IfNoneMatch.Any(x => x.Tag == etag))
168                     {
169                         var time = CacheTimeQuery.Execute(DateTime.Now);
170                         var quickResponse = actionContext.Request.CreateResponse(HttpStatusCode.NotModified);
171                         ApplyCacheHeaders(quickResponse, time);
172                         actionContext.Response = quickResponse;
173                         return;
174                     }
175                 }
176             }
177
178             var val = _webApiCache.Get<byte[]>(cachekey);
179             if (val == null) return;
180
181             var contenttype = _webApiCache.Get<MediaTypeHeaderValue>(cachekey + Constants.ContentTypeKey) ?? new MediaTypeHeaderValue(cachekey.Split(new[] { ‘:‘ }, 2)[1].Split(‘;‘)[0]);
182
183             actionContext.Response = actionContext.Request.CreateResponse();
184             actionContext.Response.Content = new ByteArrayContent(val);
185
186             actionContext.Response.Content.Headers.ContentType = contenttype;
187             var responseEtag = _webApiCache.Get<string>(cachekey + Constants.EtagKey);
188             if (responseEtag != null) SetEtag(actionContext.Response, responseEtag);
189
190             var cacheTime = CacheTimeQuery.Execute(DateTime.Now);
191             ApplyCacheHeaders(actionContext.Response, cacheTime);
192         }
193
194         public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
195         {
196             if (actionExecutedContext.ActionContext.Response == null || !actionExecutedContext.ActionContext.Response.IsSuccessStatusCode) return;
197
198             if (!IsCachingAllowed(actionExecutedContext.ActionContext, AnonymousOnly)) return;
199
200             var cacheTime = CacheTimeQuery.Execute(DateTime.Now);
201             if (cacheTime.AbsoluteExpiration > DateTime.Now)
202             {
203                 var httpConfig = actionExecutedContext.Request.GetConfiguration();
204                 var config = httpConfig.CacheOutputConfiguration();
205                 var cacheKeyGenerator = config.GetCacheKeyGenerator(actionExecutedContext.Request, CacheKeyGenerator);
206
207                 var responseMediaType = actionExecutedContext.Request.Properties[CurrentRequestMediaType] as MediaTypeHeaderValue ?? GetExpectedMediaType(httpConfig, actionExecutedContext.ActionContext);
208                 var cachekey = cacheKeyGenerator.MakeCacheKey(actionExecutedContext.ActionContext, responseMediaType, ExcludeQueryStringFromCacheKey);
209
210                 if (!string.IsNullOrWhiteSpace(cachekey) && !(_webApiCache.Contains(cachekey)))
211                 {
212                     SetEtag(actionExecutedContext.Response, CreateEtag(actionExecutedContext, cachekey, cacheTime));
213
214                     var responseContent = actionExecutedContext.Response.Content;
215
216                     if (responseContent != null)
217                     {
218                         var baseKey = config.MakeBaseCachekey(actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName, actionExecutedContext.ActionContext.ActionDescriptor.ActionName);
219                         var contentType = responseContent.Headers.ContentType;
220                         string etag = actionExecutedContext.Response.Headers.ETag.Tag;
221                         //ConfigureAwait false to avoid deadlocks
222                         var content = await responseContent.ReadAsByteArrayAsync().ConfigureAwait(false);
223
224                         responseContent.Headers.Remove("Content-Length");
225
226                         _webApiCache.Add(baseKey, string.Empty, cacheTime.AbsoluteExpiration);
227                         _webApiCache.Add(cachekey, content, cacheTime.AbsoluteExpiration, baseKey);
228
229
230                         _webApiCache.Add(cachekey + Constants.ContentTypeKey,
231                                         contentType,
232                                         cacheTime.AbsoluteExpiration, baseKey);
233
234
235                         _webApiCache.Add(cachekey + Constants.EtagKey,
236                                         etag,
237                                         cacheTime.AbsoluteExpiration, baseKey);
238                     }
239                 }
240             }
241
242             ApplyCacheHeaders(actionExecutedContext.ActionContext.Response, cacheTime);
243         }
244
245         protected virtual void ApplyCacheHeaders(HttpResponseMessage response, CacheTime cacheTime)
246         {
247             if (cacheTime.ClientTimeSpan > TimeSpan.Zero || MustRevalidate || Private)
248             {
249                 var cachecontrol = new CacheControlHeaderValue
250                 {
251                     MaxAge = cacheTime.ClientTimeSpan,
252                     MustRevalidate = MustRevalidate,
253                     Private = Private
254                 };
255
256                 response.Headers.CacheControl = cachecontrol;
257             }
258             else if (NoCache)
259             {
260                 response.Headers.CacheControl = new CacheControlHeaderValue { NoCache = true };
261                 response.Headers.Add("Pragma", "no-cache");
262             }
263         }
264
265         protected virtual string CreateEtag(HttpActionExecutedContext actionExecutedContext, string cachekey, CacheTime cacheTime)
266         {
267             return Guid.NewGuid().ToString();
268         }
269
270         private static void SetEtag(HttpResponseMessage message, string etag)
271         {
272             if (etag != null)
273             {
274                 var eTag = new EntityTagHeaderValue(@"""" + etag.Replace("\"", string.Empty) + @"""");
275                 message.Headers.ETag = eTag;
276             }
277         }
278     }
279
280     public interface ICacheKeyGenerator
281     {
282         string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false);
283     }
284     public sealed class Constants
285     {
286         public const string ContentTypeKey = ":response-ct";
287         public const string EtagKey = ":response-etag";
288     }
289
290     public class DefaultCacheKeyGenerator : ICacheKeyGenerator
291     {
292         public virtual string MakeCacheKey(HttpActionContext context, MediaTypeHeaderValue mediaType, bool excludeQueryString = false)
293         {
294             var controller = context.ControllerContext.ControllerDescriptor.ControllerType.FullName;
295             var action = context.ActionDescriptor.ActionName;
296             var key = context.Request.GetConfiguration().CacheOutputConfiguration().MakeBaseCachekey(controller, action);
297             var actionParameters = context.ActionArguments.Where(x => x.Value != null).Select(x => x.Key + "=" + GetValue(x.Value));
298
299             string parameters;
300
301             if (!excludeQueryString)
302             {
303                 var queryStringParameters =
304                     context.Request.GetQueryNameValuePairs()
305                            .Where(x => x.Key.ToLower() != "callback")
306                            .Select(x => x.Key + "=" + x.Value);
307                 var parametersCollections = actionParameters.Union(queryStringParameters);
308                 parameters = "-" + string.Join("&", parametersCollections);
309
310                 var callbackValue = GetJsonpCallback(context.Request);
311                 if (!string.IsNullOrWhiteSpace(callbackValue))
312                 {
313                     var callback = "callback=" + callbackValue;
314                     if (parameters.Contains("&" + callback)) parameters = parameters.Replace("&" + callback, string.Empty);
315                     if (parameters.Contains(callback + "&")) parameters = parameters.Replace(callback + "&", string.Empty);
316                     if (parameters.Contains("-" + callback)) parameters = parameters.Replace("-" + callback, string.Empty);
317                     if (parameters.EndsWith("&")) parameters = parameters.TrimEnd(‘&‘);
318                 }
319             }
320             else
321             {
322                 parameters = "-" + string.Join("&", actionParameters);
323             }
324
325             if (parameters == "-") parameters = string.Empty;
326
327             var cachekey = string.Format("{0}{1}:{2}", key, parameters, mediaType);
328             return cachekey;
329         }
330
331         private string GetJsonpCallback(HttpRequestMessage request)
332         {
333             var callback = string.Empty;
334             if (request.Method == HttpMethod.Get)
335             {
336                 var query = request.GetQueryNameValuePairs();
337
338                 if (query != null)
339                 {
340                     var queryVal = query.FirstOrDefault(x => x.Key.ToLower() == "callback");
341                     if (!queryVal.Equals(default(KeyValuePair<string, string>))) callback = queryVal.Value;
342                 }
343             }
344             return callback;
345         }
346
347         private string GetValue(object val)
348         {
349             if (val is IEnumerable && !(val is string))
350             {
351                 var concatValue = string.Empty;
352                 var paramArray = val as IEnumerable;
353                 return paramArray.Cast<object>().Aggregate(concatValue, (current, paramValue) => current + (paramValue + ";"));
354             }
355             return val.ToString();
356         }
357     }
358
359
360     public class CacheOutputConfiguration
361     {
362         private readonly HttpConfiguration _configuration;
363
364         public CacheOutputConfiguration(HttpConfiguration configuration)
365         {
366             _configuration = configuration;
367         }
368
369         public void RegisterCacheOutputProvider(Func<IApiOutputCache> provider)
370         {
371             _configuration.Properties.GetOrAdd(typeof(IApiOutputCache), x => provider);
372         }
373
374         public void RegisterCacheKeyGeneratorProvider<T>(Func<T> provider)
375             where T : ICacheKeyGenerator
376         {
377             _configuration.Properties.GetOrAdd(typeof(T), x => provider);
378         }
379
380         public void RegisterDefaultCacheKeyGeneratorProvider(Func<ICacheKeyGenerator> provider)
381         {
382             RegisterCacheKeyGeneratorProvider(provider);
383         }
384
385         public string MakeBaseCachekey(string controller, string action)
386         {
387             return string.Format("{0}-{1}", controller.ToLower(), action.ToLower());
388         }
389
390         public string MakeBaseCachekey<T, U>(Expression<Func<T, U>> expression)
391         {
392             var method = expression.Body as MethodCallExpression;
393             if (method == null) throw new ArgumentException("Expression is wrong");
394
395             var methodName = method.Method.Name;
396             var nameAttribs = method.Method.GetCustomAttributes(typeof(ActionNameAttribute), false);
397             if (nameAttribs.Any())
398             {
399                 var actionNameAttrib = (ActionNameAttribute)nameAttribs.FirstOrDefault();
400                 if (actionNameAttrib != null)
401                 {
402                     methodName = actionNameAttrib.Name;
403                 }
404             }
405
406             return string.Format("{0}-{1}", typeof(T).FullName.ToLower(), methodName.ToLower());
407         }
408
409         private static ICacheKeyGenerator TryActivateCacheKeyGenerator(Type generatorType)
410         {
411             var hasEmptyOrDefaultConstructor =
412                 generatorType.GetConstructor(Type.EmptyTypes) != null ||
413                 generatorType.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
414                 .Any(x => x.GetParameters().All(p => p.IsOptional));
415             return hasEmptyOrDefaultConstructor
416                 ? Activator.CreateInstance(generatorType) as ICacheKeyGenerator
417                 : null;
418         }
419
420         public ICacheKeyGenerator GetCacheKeyGenerator(HttpRequestMessage request, Type generatorType)
421         {
422             generatorType = generatorType ?? typeof(ICacheKeyGenerator);
423             object cache;
424             _configuration.Properties.TryGetValue(generatorType, out cache);
425
426             var cacheFunc = cache as Func<ICacheKeyGenerator>;
427
428             var generator = cacheFunc != null
429                 ? cacheFunc()
430                 : request.GetDependencyScope().GetService(generatorType) as ICacheKeyGenerator;
431
432             return generator
433                 ?? TryActivateCacheKeyGenerator(generatorType)
434                 ?? new DefaultCacheKeyGenerator();
435         }
436
437         public IApiOutputCache GetCacheOutputProvider(HttpRequestMessage request)
438         {
439             object cache;
440             _configuration.Properties.TryGetValue(typeof(IApiOutputCache), out cache);
441
442             var cacheFunc = cache as Func<IApiOutputCache>;
443
444             var cacheOutputProvider = cacheFunc != null ? cacheFunc() : request.GetDependencyScope().GetService(typeof(IApiOutputCache)) as IApiOutputCache ?? new MemoryCacheDefault();
445             return cacheOutputProvider;
446         }
447     }
448
449     public static class HttpConfigurationExtensions
450     {
451         public static CacheOutputConfiguration CacheOutputConfiguration(this HttpConfiguration config)
452         {
453             return new CacheOutputConfiguration(config);
454         }
455     }
456     public sealed class IgnoreCacheOutputAttribute : Attribute
457     {
458     }
459
460     public class CacheTime
461     {
462         // client cache length in seconds
463         public TimeSpan ClientTimeSpan { get; set; }
464
465         public DateTimeOffset AbsoluteExpiration { get; set; }
466     }
467     public interface IApiOutputCache
468     {
469         void RemoveStartsWith(string key);
470
471         T Get<T>(string key) where T : class;
472
473         [Obsolete("Use Get<T> instead")]
474         object Get(string key);
475
476         void Remove(string key);
477
478         bool Contains(string key);
479
480         void Add(string key, object o, DateTimeOffset expiration, string dependsOnKey = null);
481
482         IEnumerable<string> AllKeys { get; }
483     }
484
485     public class ShortTime : IModelQuery<DateTime, CacheTime>
486     {
487         private readonly int serverTimeInSeconds;
488         private readonly int clientTimeInSeconds;
489
490         public ShortTime(int serverTimeInSeconds, int clientTimeInSeconds)
491         {
492             if (serverTimeInSeconds < 0)
493                 serverTimeInSeconds = 0;
494
495             this.serverTimeInSeconds = serverTimeInSeconds;
496
497             if (clientTimeInSeconds < 0)
498                 clientTimeInSeconds = 0;
499
500             this.clientTimeInSeconds = clientTimeInSeconds;
501         }
502
503         public CacheTime Execute(DateTime model)
504         {
505             var cacheTime = new CacheTime
506             {
507                 AbsoluteExpiration = model.AddSeconds(serverTimeInSeconds),
508                 ClientTimeSpan = TimeSpan.FromSeconds(clientTimeInSeconds)
509             };
510
511             return cacheTime;
512         }
513     }
514     public interface IModelQuery<in TModel, out TResult>
515     {
516         TResult Execute(TModel model);
517     }
518     public class MemoryCacheDefault : IApiOutputCache
519     {
520         private static readonly MemoryCache Cache = MemoryCache.Default;
521
522         public void RemoveStartsWith(string key)
523         {
524             lock (Cache)
525             {
526                 Cache.Remove(key);
527             }
528         }
529
530         public T Get<T>(string key) where T : class
531         {
532             var o = Cache.Get(key) as T;
533             return o;
534         }
535
536         [Obsolete("Use Get<T> instead")]
537         public object Get(string key)
538         {
539             return Cache.Get(key);
540         }
541
542         public void Remove(string key)
543         {
544             lock (Cache)
545             {
546                 Cache.Remove(key);
547             }
548         }
549
550         public bool Contains(string key)
551         {
552             return Cache.Contains(key);
553         }
554
555         public void Add(string key, object o, DateTimeOffset expiration, string dependsOnKey = null)
556         {
557             var cachePolicy = new CacheItemPolicy
558             {
559                 AbsoluteExpiration = expiration
560             };
561
562             if (!string.IsNullOrWhiteSpace(dependsOnKey))
563             {
564                 cachePolicy.ChangeMonitors.Add(
565                     Cache.CreateCacheEntryChangeMonitor(new[] { dependsOnKey })
566                 );
567             }
568             lock (Cache)
569             {
570                 Cache.Add(key, o, cachePolicy);
571             }
572         }
573
574         public IEnumerable<string> AllKeys
575         {
576             get
577             {
578                 return Cache.Select(x => x.Key);
579             }
580         }
581     }
582
583     // 使用方法 [CacheOutput(ClientTimeSpan = 350, ServerTimeSpan = 50)]
584
585
586
587 }
时间: 2024-10-12 08:15:37

web api 缓存类的相关文章

[Asp.net web api]缓存

摘要 为了提高接口的性能,我们常做的优化就包括缓存,对经常访问但变化不大的数据进行缓存.或者使用http的缓存,减少请求的次数. web api缓存 在提供的api,我们也可以实现缓存,来减少访问的次数.有个比较好的组件,供我们使用. 通过Nuget安装WebApi.OutputCache.V2开源组件,项目地址:https://github.com/filipw/Strathweb.CacheOutput 使用 [RoutePrefix("api/user")] public cla

asp.net web api——BundleConfig类的使用

BundleConfig设置好,然后在页面就能引用 public class BundleConfig { // 有关捆绑的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkId=301862 public static void RegisterBundles(BundleCollection bundles) { bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "

ASP.NET Web API实现缓存的2种方式

在ASP.NET Web API中实现缓存大致有2种思路.一种是通过ETag, 一种是通过类似ASP.NET MVC中的OutputCache. 通过ETag实现缓存 首先安装cachecow.server install-package cachecow.server 在WebApiConfig中. public static class WebApiConfig { public static HttpConfiguraiton Register() { var config = new H

Web API应用架构在Winform混合框架中的应用(1)

在<Web API应用架构设计分析(1)>和<Web API应用架构设计分析(2)>中对WebAPI的架构进行了一定的剖析,在当今移动优先的口号下,传统平台都纷纷开发了属于自己的Web API平台,方便各种终端系统的接入,很多企业的需求都是以Web API优先的理念来设计整个企业应用体系的.Web API作为整个纽带的核心,在整个核心层需要考虑到统一性.稳定性.以及安全性等方面因素.本文主要介绍,Web API应用架构,在Winform整合中的角色,以及如何实现在Winform混合

Web API接口 安全验证

在上篇随笔<Web API应用架构设计分析(1)>,我对Web API的各种应用架构进行了概括性的分析和设计,Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端(包括浏览器,手机和平板电脑等移动设备)的框架,本篇继续这个主题,介绍如何利用ASP.NET Web API 来设计Web API层以及相关的调用处理. 1.Web API的接口访问分类 Web API接口的访问方式,大概可以分为几类: 1)一个是使用用户令牌,通过Web API接口进行数据访问.这种方式,可

Web API应用架构设计分析(2)

在上篇随笔<Web API应用架构设计分析(1)>,我对Web API的各种应用架构进行了概括性的分析和设计,Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端(包括浏览器,手机和平板电脑等移动设备)的框架,本篇继续这个主题,介绍如何利用ASP.NET Web API 来设计Web API层以及相关的调用处理. 1.Web API的接口访问分类 Web API接口的访问方式,大概可以分为几类: 1)一个是使用用户令牌,通过Web API接口进行数据访问.这种方式,可

ASP.NET Web API 2 对 CORS 的支持

CORS概念 跨域资源共享 (CORS) 是一种万维网联合会 (W3C) 规范(通常被认为是 HTML5 的一部分),它可让 JavaScript 克服由浏览器施加的同域策略安全限制. 所谓同域策略,就是 JavaScript 只能对包含网页的同一个域进行 AJAX 回调(其中,“域”就是主机名.协议和端口号的组合). 例如,http://foo.com 中某个网页上的 JavaScript 无法对 http://bar.com(或 http://www.foo.com.https://foo.

Web API 2 对 CORS 的支持

原文:Web API 2 对 CORS 的支持 Web API 2 对 CORS 的支持 CORS概念 跨域资源共享 (CORS) 是一种万维网联合会 (W3C) 规范(通常被认为是 HTML5 的一部分),它可让 JavaScript 克服由浏览器施加的同域策略安全限制. 所谓同域策略,就是 JavaScript 只能对包含网页的同一个域进行 AJAX 回调(其中,“域”就是主机名.协议和端口号的组合). 例如,http://foo.com 中某个网页上的 JavaScript 无法对 htt

Web API 令牌

http://blog.csdn.net/qq289523052/article/details/47750021 拉 Web API数据传输加密 2015-08-18 12:03 15781人阅读 评论(1) 收藏 举报 分类: Web API 目录(?)[+] 1.Web API的接口访问分类 Web API接口的访问方式,大概可以分为几类: 1)一个是使用用户令牌,通过Web API接口进行数据访问.这种方式,可以有效识别用户的身份,为用户接口返回用户相关的数据,如包括用户信息维护.密码修