通过扩展让ASP.NET Web API支持W3C的CORS规范

简介:

让ASP.NET Web API支持JSONP和W3C的CORS规范是解决“跨域资源共享”的两种途径,在《通过扩展让ASP.NET Web API支持JSONP》中我们实现了前者,并且在《W3C的CORS Specification》一文中我们对W3C的CORS规范进行了详细介绍,现在我们通过一个具体的实例来演示如何利用ASP.NET Web API具有的扩展点来实现针对CORS的支持。

目录
一、ActionFilter OR HttpMessageHandler
二、用于定义CORS资源授权策略的特性——CorsAttribute
三、实施CORS授权检验的HttpMessageHandler——CorsMessageHandler
四、CorsMessageHandler针对简单跨域资源请求的授权检验
五、CorsMessageHandler针对Preflight Request的授权检验

一、ActionFilter OR HttpMessageHandler

通过上面针对W3C的CORS规范的介绍,我们知道跨域资源共享实现的途径就是资源的提供者利用预定义的响应报头表明自己是否将提供的资源授权给了客户端JavaScript程序,而支持CORS的浏览器利用这些响应报头决定是否允许JavaScript程序操作返回的资源。对于ASP .NET Web API来说,如果我们具有一种机制能够根据预定义的资源授权规则自动生成和添加针对CORS的响应报头,那么资源的跨域共享就迎刃而解了。

那么如何利用ASP.NET Web API的扩展实现针对CORS响应报头的自动添加呢?可能有人首先想到的是利用HttpActionFilter在目标Action方法执行之后自动添加CORS响应报头。这种解决方案对于简单跨域资源请求是没有问题的,但是不要忘了:对于非简单跨域资源请求,浏览器会采用“预检(Preflight)”机制。目标Action方法只会在处理真正跨域资源请求的过程中才会执行,但是对于采用“OPTIONS”作为HTTP方法的预检请求,根本找不到匹配的目标Action方法。

为了能够有效地应付浏览器采用的预检机制,我们只能在ASP.NET Web API的消息处理管道级别实现对提供资源的授权检验和对CORS响应报头的添加。我们只需要为此创建一个自定义的HttpMessageHandler即可,不过在此之前我们先来介绍用于定义资源授权策略的CorsAttribute特性。

二、用于定义CORS资源授权策略的特性——CorsAttribute

我们将具有如下定义的CorsAttribute特性直接应用到某个HttpController或者定义其中的某个Action方法上来定义相关的资源授权策略。简单起见,我们的授权策略只考虑请求站点,而忽略请求提供的自定义报头和携带的用户凭证。如下面的代码片断所示,CorsAttribute具有一个只读属性AllowOrigins表示一组被授权站点对应的Uri数组,具体站点列表在构造函数中指定。另一个只读属性ErrorMessage表示在请求没有通过授权检验情况下返回的错误消息。

   1: [AttributeUsage( AttributeTargets.Class| AttributeTargets.Method)]
   2: public class CorsAttribute: Attribute
   3: {
   4:     public Uri[]      AllowOrigins { get; private set; }
   5:     public string     ErrorMessage { get; private set; }
   6:  
   7:     public CorsAttribute(params string[] allowOrigins)
   8:     {
   9:         this.AllowOrigins = (allowOrigins ?? new string[0]).Select(origin => new Uri(origin)).ToArray();
  10:     }
  11:  
  12:     public bool TryEvaluate(HttpRequestMessage request, out IDictionary<string, string> headers)
  13:     {
  14:         headers = null;
  15:         string origin = request.Headers.GetValues("Origin").First();
  16:         Uri originUri = new Uri(origin);
  17:         if (this.AllowOrigins.Contains(originUri))
  18:         {
  19:             headers = this.GenerateResponseHeaders(request);
  20:             return true;
  21:         }
  22:         this.ErrorMessage = "Cross-origin request denied";
  23:         return false;
  24:     }
  25:  
  26:     private IDictionary<string, string> GenerateResponseHeaders(HttpRequestMessage request)
  27:     {
  28:         //设置响应报头"Access-Control-Allow-Methods"
  29:         string origin = request.Headers.GetValues("Origin").First();
  30:         Dictionary<string, string> headers = new Dictionary<string, string>();
  31:         headers.Add("Access-Control-Allow-Origin", origin);
  32:         if (request.IsPreflightRequest())
  33:         {
  34:             //设置响应报头"Access-Control-Request-Headers"
  35:             //和"Access-Control-Allow-Headers"
  36:             headers.Add("Access-Control-Allow-Methods", "*");
  37:             string requestHeaders = request.Headers.GetValues("Access-Control-Request-Headers").FirstOrDefault();
  38:             if (!string.IsNullOrEmpty(requestHeaders))
  39:             {
  40:                 headers.Add("Access-Control-Allow-Headers", requestHeaders);
  41:             }
  42:         }
  43:         return headers;
  44:     }
  45: }

我们将针对请求的资源授权检查定义在TryEvaluate方法中,其返回至表示请求是否通过了授权检查,输出参数headers通过返回的字典对象表示最终添加的CORS响应报头。在该方法中,我们从指定的HttpRequestMessage对象中提取表示请求站点的“Origin”报头值。如果请求站点没有在通过AllowOrigins属性表示的授权站点内,则意味着请求没有通过授权检查,在此情况下我们会将ErrorMessage属性设置为“Cross-origin request denied”。

在请求成功通过授权检查的情况下,我们调用另一个方法GenerateResponseHeaders根据请求生成我们需要的CORS响应报头。如果当前为简单跨域资源请求,只会返回针对“Access-Control-Allow-Origin”的响应报头,其值为请求站点。对于预检请求来说,我们还需要额外添加针对“Access-Control-Request-Headers”和“Access-Control-Allow-Methods”的响应报头。对于前者,我们直接采用请求的“Access-Control-Request-Headers”报头值,而后者被直接设置为“*”。

在上面的程序中,我们通过调用HttpRequestMessage的扩展方法IsPreflightRequest来判断是否是一个预检请求,该方法定义如下。从给出的代码片断可以看出,我们判断预检请求的条件是:包含报头“Origin”和“Access-Control-Request-Method”的HTTP-OPTIONS请求。

   1: public static class HttpRequestMessageExtensions
   2: {
   3:     public static bool IsPreflightRequest(this HttpRequestMessage request)
   4:     {
   5:         return request.Method == HttpMethod.Options &&
   6:             request.Headers.GetValues("Origin").Any() &&
   7:             request.Headers.GetValues("Access-Control-Request-Method").Any();
   8:     }
   9: }

 

三、实施CORS授权检验的HttpMessageHandler——CorsMessageHandler

针对跨域资源共享的实现最终体现在具有如下定义的CorsMessageHandler类型上,它直接继承自DelegatingHandler。在实现的SendAsync方法中,CorsMessageHandler利用应用在目标Action方法或者HttpController类型上CorsAttribute来对请求实施授权检验,最终将生成的CORS报头添加到响应报头列表中。

   1: public class CorsMessageHandler: DelegatingHandler
   2: {
   3:     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   4:     {
   5:         //得到描述目标Action的HttpActionDescriptor
   6:         HttpMethod originalMethod = request.Method;
   7:         bool isPreflightRequest = request.IsPreflightRequest();
   8:         if (isPreflightRequest)
   9:         {
  10:             string method = request.Headers.GetValues("Access-Control-Request-Method").First();
  11:             request.Method = new HttpMethod(method);
  12:         }
  13:         HttpConfiguration configuration = request.GetConfiguration();
  14:         HttpControllerDescriptor controllerDescriptor = configuration.Services.GetHttpControllerSelector().SelectController(request);
  15:         HttpControllerContext controllerContext = new HttpControllerContext(request.GetConfiguration(), request.GetRouteData(), request)
  16:         {
  17:             ControllerDescriptor = controllerDescriptor
  18:         };
  19:         HttpActionDescriptor actionDescriptor = configuration.Services.GetActionSelector().SelectAction(controllerContext);
  20:  
  21:         //根据HttpActionDescriptor得到应用的CorsAttribute特性
  22:         CorsAttribute corsAttribute = actionDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault()??
  23:             controllerDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault();
  24:         if(null == corsAttribute)
  25:         {
  26:             return base.SendAsync(request, cancellationToken);
  27:         }
  28:  
  29:         //利用CorsAttribute实施授权并生成响应报头
  30:         IDictionary<string,string> headers;
  31:         request.Method = originalMethod;
  32:         bool authorized = corsAttribute.TryEvaluate(request, out headers);
  33:         HttpResponseMessage response;
  34:         if (isPreflightRequest)
  35:         {
  36:             if (authorized)
  37:             {
  38:                 response = new HttpResponseMessage(HttpStatusCode.OK);                   
  39:             }
  40:             else
  41:             {
  42:                 response = request.CreateErrorResponse(HttpStatusCode.BadRequest, corsAttribute.ErrorMessage);
  43:             }
  44:         }
  45:         else
  46:         {
  47:             response = base.SendAsync(request, cancellationToken).Result;                
  48:         }
  49:  
  50:         //添加响应报头
  51:         foreach (var item in headers)
  52:         {
  53:             response.Headers.Add(item.Key, item.Value);
  54:         }
  55:         return Task.FromResult<HttpResponseMessage>(response);
  56:     }
  57: }

具体来说,我们通过注册到当前ServicesContainer上的HttpActionSelector根据请求得到描述目标Action的HttpActionDescriptor对象,为此我们需要根据请求手工生成作为HttpActionSelector的SelectAction方法参数的HttpControllerContext对象。对此有一点需要注意:由于预检请求采用的HTTP方法为“OPTIONS”,我们需要将其替换成代表真正跨域资源请求的HTTP方法,也就是预检请求的“Access-Control-Request-Method”报头值。

在得到描述目标Action的HttpActionDescriptor对象后,我们调用其GetCustomAttributes<T>方法得到应用在Action方法上的CorsAttribute特性。如果这样的特性不存在,在调用同名方法得到应用在HttpController类型上的CorsAttribute特性。

接下来我们调用CorsAttribute的TryEvaluate方法对请求实施资源授权检查并得到一组CORS响应报头,作为参数的HttpRequestMessage对象的HTTP方法应该恢复其原有的值。对于预检请求,在请求通过授权检查之后我们会创建一个状态为“200, OK”的响应,否则会根据错误消息创建创建一个状态为“400, Bad Request”的响应。

对于非预检请求来说(可能是简单跨域资源请求,也可能是继预检请求之后发送的真正的跨域资源请求),我们调用基类的SendAsync方法将请求交付给后续的HttpMessageHandler进行处理并最终得到最终的响应。我们最终将调用CorsAttribute的TryEvaluate方法得到的响应报头逐一添加到响应报头列表中。

四、CorsMessageHandler针对简单跨域资源请求的授权检验

接下来我们通过于一个简单的实例来演示同源策略针对跨域Ajax请求的限制。如图右图所示,我们利用Visual Studio在同一个解决方案中创建了两个Web应用。从项目名称可以看出,WebApi和MvcApp分别为ASP.NET Web API和MVC应用,后者是Web API的调用者。我们直接采用默认的IIS Express作为两个应用的宿主,并且固定了端口号:WebApi和MvcApp的端口号分别为“3721”和“9527”,所以指向两个应用的URI肯定不可能是同源的。我们在WebApi应用中定义了如下一个继承自ApiController的ContactsController类型,它具有的唯一Action方法GetAllContacts返回一组联系人列表。

如下面的代码片断所示,用于获取所有联系人列表的Action方法GetAllContacts返回一个JsonResult<IEnumerable<Contact>>对象,但是该方法上面应用了我们定义的CorsAttribute特性,并将“http://localhost:9527”(客户端ASP.NET MVC应用的站点)设置为允许授权的站点。

   1: public class ContactsController : ApiController
   2: {
   3:     [Cors("http://localhost:9527")] 
   4:     public IHttpActionResult GetAllContacts()
   5:     {
   6:         Contact[] contacts = new Contact[]
   7:         {
   8:             new Contact{ Name="张三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},
   9:             new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},
  10:             new Contact{ Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"},
  11:         };
  12:         return Json<IEnumerable<Contact>>(contacts);
  13:     }
  14: }

在Global.asax中,我们采用如下的方式将一个CorsMessageHandler对象添加到ASP.NET Web API的消息处理管道中。

   1: public class WebApiApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsMessageHandler ());
   6:         //其他操作
   7:     }
   8: }

接下来们在MvcApp应用中定义如下一个HomeController,默认的Action方法Index会将对应的View呈现出来。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View();
   6:     }
   7: }

如下所示的是Action方法Index对应View的定义。我们的目的在于:当页面成功加载之后以Ajax请求的形式调用上面定义的Web API获取联系人列表,并将自呈现在页面上。如下面的代码片断所示,Ajax调用和返回数据的呈现是通过调用jQuery的getJSON方法完成的。在此基础上直接调用我们的ASP.NET MVC程序照样会得到如右图所示的结果.

   1: <html>
   2: <head>
   3:     <title>联系人列表</title>
   4: <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>
   1:  
   2: </head>
   3: <body>
   4:     <ul id="contacts"></ul>
   5:     <script type="text/javascript">
   6:         $(function ()
   7:         {
   8:             var url = "http://localhost:3721/api/contacts";
   9:             $.getJSON(url, null, function (contacts) {
  10:                 $.each(contacts, function (index, contact)
  11:                 {
  12:                     var html = "<li><ul>";
  13:                     html += "<li>Name: " + contact.Name + "</li>";
  14:                     html += "<li>Phone No:" + contact.PhoneNo + "</li>";
  15:                     html += "<li>Email Address: " + contact.EmailAddress + "</li>";
  16:                     html += "</ul>";
  17:                     $("#contacts").append($(html));
  18:                 });
  19:             });
  20:         });
  21:     
</script>
   5: </body>
   6: </html>

如果我们利用Fiddler来检测针对Web API调用的Ajax请求,如下所示的请求和响应内容会被捕捉到,我们可以清楚地看到利用CorsMessageHandler添加的“Access-Control-Allow-Origin”报头出现在响应的报头集合中。

   1: GET http://localhost:3721/api/contacts HTTP/1.1
   2: Host: localhost:3721
   3: Connection: keep-alive
   4: Accept: application/json, text/javascript, */*; q=0.01
   5: Origin: http://localhost:9527
   6: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
   7: Referer: http://localhost:9527/
   8: Accept-Encoding: gzip,deflate,sdch
   9: Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4
  10:  
  11: HTTP/1.1 200 OK
  12: Cache-Control: no-cache
  13: Pragma: no-cache
  14: Content-Length: 205
  15: Content-Type: application/json; charset=utf-8
  16: Expires: -1
  17: Server: Microsoft-IIS/8.0
  18: Access-Control-Allow-Origin: http://localhost:9527 
  19: X-AspNet-Version: 4.0.30319
  20: X-SourceFiles: =?UTF-8?B?RTpc5oiR55qE6JGX5L2cXEFTUC5ORVQgV2ViIEFQSeahhuaetuaPnmFxOZXcgU2FtcGxlc1xDaGFwdGVyIDE0XFMxNDAzXFdlYkFwaVxhcGlcY29udGFjdHM=?=
  21: X-Powered-By: ASP.NET
  22: Date: Wed, 04 Dec 2013 01:50:01 GMT
  23:  
  24: [{"Name":"张三","PhoneNo":"123","EmailAddress":"zhangsan@gmail.com"},{"Name":"李四","PhoneNo":"456","EmailAddress":"lisi@gmail.com"},{"Name":"王五","PhoneNo":"789","EmailAddress":wangwu@gmail.com}]

 

五、CorsMessageHandler针对Preflight Request的授权检验

从上面给出的请求和响应内容可以确定Web API的调用采用的是“简单跨域资源请求”,所以并没有采用“预检”机制。如何需要迫使浏览器采用预检机制,就需要了解我们在《W3C的CORS Specification》上面提到的简单跨域资源请求具有的两个条件

  • 采用简单HTTP方法(GET、HEAD和POST);
  • 不具有非简单请求报头的自定义报头。

只要打破其中任何一个条件就会迫使浏览器采用预检机制,我们选择为请求添加额外的自定义报头。在ASP.NET MVC应用用户调用Web API的View中,针对Ajax请求调用Web API的JavaScript程序被改写成如下的形式:我们在发送Ajax请求之前利用setRequestHeader函数添加了两个名称分别为“'X-Custom-Header1”和“'X-Custom-Header2”的自定义报头。

   1: <html>
   2: <head>
   3:     <title>联系人列表</title>
   4: <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>
   1:  
 
   
   2: </head>
 
   
   3: <body>
 
   
   4:     <ul id="contacts"></ul>
 
   
   5:     <script type="text/javascript">
 
   
   6:         $(function ()
 
   
   7:         {
 
   
   8:             $.ajax({
 
   
   9:                 url         : 'http://localhost:3721/api/contacts',
 
   
  10:                 type        : 'GET',
 
   
  11:                 success     : listContacts,
 
   
  12:                 beforeSend  : setRequestHeader
 
   
  13:             });
 
   
  14:         });
 
   
  15:  
 
   
  16:         function listContacts(contacts)
 
   
  17:         {
 
   
  18:             $.each(contacts, function (index, contact) {
 
   
  19:                 var html = "<li><ul>";
 
   
  20:                 html += "<li>Name: " + contact.Name + "</li>";
 
   
  21:                 html += "<li>Phone No:" + contact.PhoneNo + "</li>";
 
   
  22:                 html += "<li>Email Address: " + contact.EmailAddress + "</li>";
 
   
  23:                 html += "</ul>";
 
   
  24:                 $("#contacts").append($(html));
 
   
  25:             });
 
   
  26:         }
 
   
  27:  
 
   
  28:         function setRequestHeader(xmlHttpRequest)
 
   
  29:         {
 
   
  30:             xmlHttpRequest.setRequestHeader('X-Custom-Header1', 'Foo');
 
   
  31:             xmlHttpRequest.setRequestHeader('X-Custom-Header2', 'Bar');
 
   
  32:         }
 
   
  33:     
 </script>
   5: </body>
   6: </html>

再次运行我们的ASP.NET MVC程序,依然会得正确的输出结果,但是针对Web API的调用则会涉及到两次消息交换,分别针对预检请求和真正的跨域资源请求。从下面给出的两次消息交换涉及到的请求和响应内容可以看出:自定义的两个报头名称会出现在采用“OPTIONS”作为HTTP方法的预检请求的“Access-Control-Request-Headers”报头中,利用CorsMessageHandler添加的3个报头(“Access-Control-Allow-Origin”、“Access-Control-Allow-Methods”和“Access-Control-Allow-Headers”)均出现在针对预检请求的响应中。

   1: OPTIONS http://localhost:3721/api/contacts HTTP/1.1
   2: Host: localhost:3721
   3: Connection: keep-alive
   4: Cache-Control: max-age=0
   5: Access-Control-Request-Method: GET 
   6: Origin: http://localhost:9527
   7: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
   8: Access-Control-Request-Headers: accept, x-custom-header1, x-custom-header2 
   9: Accept: */*
  10: Referer: http://localhost:9527/
  11: Accept-Encoding: gzip,deflate,sdch
  12: Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4
  13:  
  14: HTTP/1.1 200 OK
  15: Cache-Control: no-cache
  16: Pragma: no-cache
  17: Expires: -1
  18: Server: Microsoft-IIS/8.0
  19: Access-Control-Allow-Origin: http://localhost:9527 
  20: Access-Control-Allow-Methods: * 
  21: Access-Control-Allow-Headers: accept, x-custom-header1, x-custom-header2 
  22: X-AspNet-Version: 4.0.30319
  23: X-SourceFiles: =?UTF-8?B??=
  24: X-Powered-By: ASP.NET
  25: Date: Wed, 04 Dec 2013 02:11:16 GMT
  26: Content-Length: 0
  27:  
  28: --------------------------------------------------------------------------------
  29: GET http://localhost:3721/api/contacts HTTP/1.1
  30: Host: localhost:3721
  31: Connection: keep-alive
  32: Accept: */*
  33: X-Custom-Header1: Foo
  34: Origin: http://localhost:9527
  35: X-Custom-Header2: Bar
  36: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
  37: Referer: http://localhost:9527/
  38: Accept-Encoding: gzip,deflate,sdch
  39: Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4
  40:  
  41: HTTP/1.1 200 OK
  42: Cache-Control: no-cache
  43: Pragma: no-cache
  44: Content-Length: 205
  45: Content-Type: application/json; charset=utf-8
  46: Expires: -1
  47: Server: Microsoft-IIS/8.0
  48: Access-Control-Allow-Origin: http://localhost:9527
  49: X-AspNet-Version: 4.0.30319
  50: X-SourceFiles: =?UTF-8?B?RTpc5oiR55qE6JGX5L2cXEFTUC5ORVQgV2ViIEFQSeahhuaetuaPreenmFxOZXcgU2FtcGxlc1xDaGFwdGVyIDE0XF9udGFjdHM=?=
  51: X-Powered-By: ASP.NET
  52: Date: Wed, 04 Dec 2013 02:11:16 GMT
  53:  
  54: [{"Name":"张三","PhoneNo":"123","EmailAddress":"zhangsan@gmail.com"},{"Name":"李四","PhoneNo":"456","EmailAddress":"lisi@gmail.com"},{"Name":"王五","PhoneNo":"789","EmailAddress":wangwu@gmail.com}]

 

CORS系列文章
[1] 同源策略与JSONP
[2] 利用扩展让ASP.NET Web API支持JSONP
[3] W3C的CORS规范
[4] 利用扩展让ASP.NET Web API支持CORS
[5] ASP.NET Web API自身对CORS的支持: 从实例开始
[6] ASP.NET Web API自身对CORS的支持: CORS授权策略的定义和提供
[7] ASP.NET Web API自身对CORS的支持: CORS授权检验的实施
[8] ASP.NET Web API自身对CORS的支持: CorsMessageHandler

作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
101 3
|
3月前
|
编解码 前端开发 JavaScript
.NET_web前端框架_layui_栅格布局
【8月更文挑战第27天】
47 4
|
1月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
90 9
|
2月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
95 3
|
2月前
|
开发框架 前端开发 .NET
VB.NET中如何利用ASP.NET进行Web开发
在VB.NET中利用ASP.NET进行Web开发是一个常见的做法,特别是在需要构建动态、交互式Web应用程序时。ASP.NET是一个由微软开发的开源Web应用程序框架,它允许开发者使用多种编程语言(包括VB.NET)来创建Web应用程序。
59 5
|
1月前
|
前端开发 JavaScript 搜索推荐
对WEB标准以及W3C的理解与认识
对WEB标准以及W3C的理解与认识
43 0
|
1月前
|
监控 安全 API
Docker + .NET API:简化部署和扩展
Docker + .NET API:简化部署和扩展
39 0
|
1月前
|
监控 安全 API
最完美的扩展Docker + .NET API:简化部署和扩展
最完美的扩展Docker + .NET API:简化部署和扩展
72 0
|
3月前
|
开发框架 监控 .NET
开发者的革新利器:ASP.NET Core实战指南,构建未来Web应用的高效之道
【8月更文挑战第28天】本文探讨了如何利用ASP.NET Core构建高效、可扩展的Web应用。ASP.NET Core是一个开源、跨平台的框架,具有依赖注入、配置管理等特性。文章详细介绍了项目结构规划、依赖注入配置、中间件使用及性能优化方法,并讨论了安全性、可扩展性以及容器化的重要性。通过这些技术要点,开发者能够快速构建出符合现代Web应用需求的应用程序。
57 0