阅读目录:html
做为一个Universal Windows Platform (UWP)开发者,若是你尝试使用http与web服务或其余服务端通信时,有多个API能够选择。 UWP中最多见并推荐使用的HTTP客户端API实现是System.Net.Http.HttpClient和Windows.Web.Http.HttpClient。 这些APIs相比旧的应该优先使用,好比旧APIs的WebClient和HttpWebRequest(尽管它的子集在UWP中是向后兼容的)。web
咱们收到一些关于问题反馈,关于这些APIs不一样之处,从功能上来讲两组APIs是上相等的,那在不一样场景下选择哪个呢,诸如此类的问题。 在这篇文章中,咱们会去尝试定位这些问题,理清楚这两组APIs的用途及使用场景。windows
第一个推荐AIP是System.Net.Http.HttpClient,它在Net 4.5中第一次出现,经过Nuget能够安装这个API的兼容版本,这样就能够在Net 4.0和windows Phone 8 Silverlight apps中使用。相比旧的HttpWebRequest API,这个API的目标是提供一个简单的,干净的抽象层,比较灵活的实现http客户端功能。 好比,它容许连接自定义处理器,开发者能够拦截每一个request和response,去实现自定义逻辑。 在windows8.1以后,全部功能都在.NET下面实现。 在windows10 UWP中这个API实现移到Windows.Web.Http和WinINet Http层上。api
另一个推荐API是Windows.Web.Http.HttpClient,这个API是Windows 8.1时开始引进的,在Windows Phone 8.1也是可使用的。 增长这个API的主要目是,把不一样windows应用开发语言(C#, VB, C++, JavaScript)下,不一样Http APIs合成一个,它支持上述APIs的全部特性。 大多数基础API都是从System.Net.Http派生的,在Windows HTTP基础上实现。数组
在Windows商店APP中使用这些API时,其支持的系统版本和程序语言以下所示:浏览器
在UWP中这些HTTP API都是可使用的,对于开发者来讲最大的问题是在APP中应该使用哪个。其答案取决去几个因素:缓存
是否须要结合本地UI收集用户证书,控制HTTP缓存读和写,或者经过指定的ssl客户端证书去作认证? 若是须要认证,那是应使用Windows.Web.Http.HttpClient。在如今的UWP中,Windows.Web.Http提供HTTP设置,它比System.Net.Http API更好的控制这些。 在将来的版本,也会增强支持System.Net.Http在UWP中的特性。服务器
是否考虑写跨平台的.NET代码(跨UWP/ASP.NET 5/IOS和Android)? 若是须要,那使用System.Net.Http API。它可让你写的代码复用在其余.Net平台上,好比ASP.Net 5和.NET桌面平台应用。 经过使用Xamarin,这些API在IOS和Android中也获得支持。cookie
如今就比较好理解为何会有两个类似APIs了,也了解怎么在两者之间进行选择,下面进一步了解这两个对象模型。网络
其HttpClient对象是最顶端的抽象模型,在HTTP协议client-server模型中它表示client这部分。其client能发出多个request请求(用HttpRequestMessage表示)到服务端上,从服务端接收响应(用HttpResponseMessage表示)。用HttpContent基类和它派生出的类,表示对象body和每一个request或response的content头部,好比StreamContent,MultipartContent和StringContent。它们表示各类http实体body内容。这些类都会提供ReadAs开头的一组方法,它能从请求或响应实体body中,以字符串形式、字节数组、流形式读取内容。
每个HttpClient对象下都有一个处理者对象,它表示client下全部与HTTP相关的配置。从概念上来讲,能够认为它是client部分下HTTP协议栈的表明。在客户端发送HTTP请求到服务端和传输数据到客户端上,它是很是可靠的。
在System.Net.Http API中默认处理者是HttpClientHandler。当你建立HttpClient对象实例时,会使用默认HTTP stack设置,自动帮你建立一个HttpClientHandler。若是你想修改默认一些设置,好比缓存行为,自动压缩,证书或代理,能够直接建立一个HttpClientHandler实例,修改它的属性,把它当作HttpClient构造函数的参数传入。这样HttpClient对象就会使用咱们自定义的处理器,以下:
HttpClientHandler myHandler = new HttpClientHandler(); myHandler.AllowAutoRedirect = false; HttpClient myClient = new HttpClient(myHandler);
System.Net.Http.HttpClient API设计中一个重要优点是:可以插入自定义处理器、在HttpClient对象下建立一连串的处理器。例如:构建一个app,它从web服务中请求一些数据。这时就能够自定义逻辑去处理HTTP服务端响应的4xx (客户端错误)和5xx (服务端错误),使用具体的重试步骤,好比尝试不一样的端口请求或添加一个用户认证。 还可能会想从业务逻辑部分分离出HTTP相关的工做,它只关心web服务的数据返回。
这就可使用自定义处理器类来完成,它从DelegatingHandler派生出,例如CustomHandler1,而后建立一个新实例,把它传入HttpClient构造函数。 DelegatingHandler类的InnerHandler属性被用指定下一个处理器,好比,能够添加个新的自定处理器(例CustomHandler2)处处理链上。处理链上最后一个处理者的InnerHandler,能够设置成HttpClientHandler的实例,它将传递请求到系统的HTTP协议栈上。 从概念上来看以下图:
下面是完成这部分的例子代码:
public class CustomHandler1 : DelegatingHandler { protected async override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { Debug.WriteLine("Processing request in Custom Handler 1"); HttpResponseMessage response = await base.SendAsync(request, cancellationToken); Debug.WriteLine("Processing response in Custom Handler 1"); return response; } }
public class CustomHandler2 : DelegatingHandler { // Similar code as CustomHandler1. } public class Foo { public void CreateHttpClientWithChain() { HttpClientHandler systemHandler = new HttpClientHandler(); CustomHandler1 myHandler1 = new CustomHandler1(); CustomHandler2 myHandler2 = new CustomHandler2(); // Chain the handlers together. myHandler1.InnerHandler = myHandler2; myHandler2.InnerHandler = systemHandler; // Create the client object with the topmost handler in the chain. HttpClient myClient = new HttpClient(myHandler1); } }
说明:
若是你试图发送一个请求到远程服务器端口上,其链上最后的处理器一般是HttpClientHandler,它实际是从系统HTTP协议栈层面发送这个请求或接收这个响应。做为一种选择,可使用一个模拟处理器,模拟发送请求到服务器上,返回一个伪造的响应,这能够用来单元测试。
在传递请求到内部处理器以前或响应处理器之上,添加一个处理逻辑,能减小性能消耗。这个处理器场景下,最好能避免使用耗时的同步操做。
关于链式处理概念的详细信息,能够看Henrik Nielsen的这篇博客,(注意文章参考的是ASP.NET Web API的API版本。它和本文讨论的.NET framework有一些细微的不一样,但在链式处理器上的概念是同样的)
Windows.Web.Http API的对象模型跟上面描述的System.Net.Http版本很是 ,它也有client entity的概念,一个处理器(在这叫“filter”过滤器),及在client和系统默认过滤器之间选择是否插入自定义逻辑。
其大多数类型是直接相似于System.Net.Http的类型的,以下:
在上面关于System.Net.Http API的链式处理器讨论,也可应用于Windows.Web.Http API,这里你能够建立自定义链式过滤器,传递它们到HttpClient对象的构造函数中。
关于HttpClient APIs中的大多数HTTP功能的通用实现,都能在网上或书上找到一些代码片断和相应介绍说明。关于完整的细节和指导,请查看Windows.Web.Http.HttpClient和System.Net.Http.HttpClient API各自的MSDN文档。
在HttpClient实例上修改全部请求的头部,使用下面的方式:
var myClient = new HttpClient(); myClient.DefaultRequestHeaders.Add("X-HeaderKey", "HeaderValue"); myClient.DefaultRequestHeaders.Referrer = new Uri("http://www.contoso.com");
只修改指定请求的头部,使用:
HttpRequestMessage myrequest = new HttpRequestMessage(); myrequest.Headers.Add("X-HeaderKey", "HeaderValue"); myrequest.Headers.Referrer = new Uri("http://www.contoso.com");
上面的方式一样适用于Windows.Web.Http API。
一些头部是用集合表示的,要使添加和移除方法去编辑它们。
HttpClient.DefaultRequestHeaders属性表示默认头部集合,它会在App层添加到头部。请求会在操做系统协议栈上被处理,附加的头部会在数据经过网卡发送以前被添加。
在the System.Net.Http API中,有两个方式去设置超时。 在client部分上设置全部请求的超时时间,使用:
myClient.Timeout = TimeSpan.FromSeconds(30);
在单个请求上设置超时,使用删除token方式:
var cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(30)); var httpClient = new HttpClient(); var resourceUri = new Uri("http://www.contoso.com"); try { HttpResponseMessage response = await httpClient.GetAsync(resourceUri, cts.Token); } catch (TaskCanceledException ex) { // Handle request being canceled due to timeout. } catch (HttpRequestException ex) { // Handle other possible exceptions. }
在Windows.Web.Http.HttpClient上没有超时属性,所以,必须使用上面介绍的删除token方式实现超时功能。
为了保护用户凭据信息,默认状况下Http协议栈在请求发出时,不能添加任务身份验证信息。如须要使用指定用户验证,使用下面的模式:
var myClientHandler = new HttpClientHandler(); myClientHandler.Credentials = new NetworkCredential(myUsername, myPassword);
对于Windows.Web.Http API,默认状况下,若是发出的请求是一个资源请求,会提供一个UI对话框,它要求用户进行确认。如想禁用这个UI对话框,设置HttpBaseProtocolFilter的属性AllowUI为false。 使用指定的验证替代:
var myFilter = new HttpBaseProtocolFilter(); myFilter.ServerCredential = new PasswordCredential(“fooBar”, myUsername, myPassword);
在上面的例子中,myUsername和myPassword是一个string字符串变量,一般是从用户UI输入或app配置设置中得到。
在UWP应用中,HttpClientHandler.Credentials能被设置为NULL,DefaultCredentials,类型NetworkCredential等值。
为了保护用户凭据信息,默认状况下API不会发送任何客户端凭据到服务器上。 使用客户端凭据认证代码以下:
var myClientHandler = new HttpClientHandler(); myClientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
使用客户端凭据认证有两个选项,默认是提供UI给用户选择一个证书信息。做为一种选择,你能够用程序设置一个客户端证书,以下:
var myFilter = new HttpBaseProtocolFilter(); myFilter.ClientCertificate = myCertificate;
为在两者API中任意一个使用客户端证书,你必须添加它到app的证书商店里,参考链接的这些构造。在“My”中企业APP也能使用已经存在的客户端证书。
对于HttpClientHandler.ClientCertificateOptions来讲,这有两个值能够设置:Automatic和Manual。设置Automatic会从APP证书商店里选择一个最匹配的客户端证书,用它来认证。设置Manual会确保不会发送客户端证书,即便服务器请求它。
对与两者APis来讲,代理设置会自动从IE/Edge浏览器中得到,它被全部的Http请求默认调用。这确保了,即便用户经过一个代理上网,也能自动链接工做。 两者API都不能再APP中提供一种方式去指定一个自定义的代理。不论如何,你能够选择设置HttpClientHandler.UseProxy(System.Net.Http中)为false不使用默认代理设置,在Windows.Web.Http设置HttpBaseProtocolFilter.UseProxy为false。
默认状况下,两者APIs都保存经过服务器发送的cookies,在相同的app容器内,自动添加上Cookies到那个URL的后续请求上。 这些Cookies被那个明确的URL读取, 添加新的自定义cookies。 两者APIs都有一个选项能禁止发送cookies到服务器上:在System.Net.Http上设置HttpClientHandler.UseCookies为false,在Windows.Web.Http设置HttpBaseProtocolFilter.CookieUsageBehavior为HttpCookieUsageBehavior.NoCookies。
在client处理器上,添加一个cookie到全部的请求上:
// 手工添加一个cookie myClientHandler.CookieContainer.Add(resourceUri, myCookie);
添加一个cookie到单个请求上:
HttpRequestMessage myRequest = new HttpRequestMessage(); myRequest.Headers.Add("Cookie", "user=foo; key=bar");
检查一个指定URI的全部Cookies:
var cookieCollection = myClientHandler.CookieContainer.GetCookies(resourceUri);
经过client,添加一个cookie到全部的发送请求上:
// 手工添加一个cookie filter.CookieManager.SetCookie(myCookie);
添加一个cookie到单个请求上,这个模式使用和上面的Windows.Web.Http API上是相同的。
管理cookies:
// 从一个指定URI上获取全部的cookies。 var cookieCollection = filter.CookieManager.GetCookies(resourceUri);
// 删除一个cookie。 filter.CookieManager.DeleteCookie(myCookie);
Windows.Web.Http API中,对于这几个APIs来讲,cookie管理器中的这些cookies都是共享的,由于它们都是在WinINet栈上实现的,好比:Windows.Web.Syndication, Windows.Web.AtomPub, XHR和其余的。所以不管使用哪一个api,都能经过服务器对请求的响应中得到cookie, 也可能会添加cookie到一个后续的HttpClient请求中,到一样的服务器中。
在操做系统的HTTP协议栈下,对每台服务器默认链接数是6。System.Net.Http HttpClient API不能提供一个方式去控制它,但在Windows.Web.Http API下是能够的,使用:
var myFilter = new HttpBaseProtocolFilter(); myFilter.MaxConnectionsPerServer = 15;
在windows10 UWP apps中,两者APIs都添加了对HTTP/2的默认支持。做为一个开发者,能够很好的利用这些优点,好比不须要代码变更就能下降延迟。 两者APIs(System.Net.Http和Windows.Web.Http)也容许明确禁止这项特性和强制使用HTTP 1.1或1.0.
从目前开始,我尝试继续添加一些高级请求特性,好比自定义服务器ssl证书的生效,在全部的地方都能添加处理器/过滤器到HttpClient对象上。为了在windows上写出优秀的apps,咱们很期待听到你须要在这些API上增长新特性。 你也能够在UserVoice提出想法。也能够加入 Windows Insiders program ,经过论坛或Windows Feedback app提交反馈。
这篇博客是微软网络APIs团队成员Sidharth Nabar写的。
译自 http://blogs.windows.com/buildingapps/2015/11/23/demystifying-httpclient-apis-in-the-universal-windows-platform/
这篇在上月底翻译的,一直没来得及整理。新工做在张江,原先住的太远单程一小时多,而后找房子、搬家、新工做环境适应。本准备要作win10开发,因此边研究win10边翻译了几篇,后来调整为优先桌面开发,开始研究hybird相关开发。