揭秘Windows10 UWP中的httpclient接口[2]
阅读目录:
概述
作为一个Universal Windows Platform (UWP)开发者,如果你尝试使用http与web服务或其他服务端通讯时,有多个API可以选择。 UWP中最常见并推荐使用的HTTP客户端API实现是System.Net.Http.HttpClient和Windows.Web.Http.HttpClient。 这些APIs相比旧的应该优先使用,比如旧APIs的WebClient和HttpWebRequest(尽管它的子集在UWP中是向后兼容的)。
我们收到一些关于问题反馈,关于这些APIs不同之处,从功能上来说两组APIs是上相等的,那在不同场景下选择哪一个呢,诸如此类的问题。 在这篇文章中,我们会去尝试定位这些问题,理清楚这两组APIs的用途及使用场景。
第一个推荐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是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中也得到支持。
现在就比较好理解为什么会有两个相似APIs了,也了解怎么在二者之间进行选择,下面进一步了解这两个对象模型。
System.Net.Http
其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
Windows.Web.Http API的对象模型跟上面描述的System.Net.Http版本非常 ,它也有client entity的概念,一个处理器(在这叫“filter”过滤器),及在client和系统默认过滤器之间选择是否插入自定义逻辑。
其大多数类型是直接类似于System.Net.Http的类型的,如下:
在上面关于System.Net.Http API的链式处理器讨论,也可应用于Windows.Web.Http API,这里你可以创建自定义链式过滤器,传递它们到HttpClient对象的构造函数中。
HTTP的常用功能
关于HttpClient APIs中的大多数HTTP功能的通用实现,都能在网上或书上找到一些代码片段和相应介绍说明。关于完整的细节和指导,请查看Windows.Web.Http.HttpClient和System.Net.Http.HttpClient API各自的MSDN文档。
修改头部
System.Net.Http:
在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:
上面的方式同样适用于Windows.Web.Http API。
说明
一些头部是用集合表示的,要使添加和移除方法去编辑它们。
HttpClient.DefaultRequestHeaders属性表示默认头部集合,它会在App层添加到头部。请求会在操作系统协议栈上被处理,附加的头部会在数据通过网卡发送之前被添加。
设置超时
System.Net.Http:
在the System.Net.Http API中,有两个方式去设置超时。 在client部分上设置所有请求的超时时间,使用:
myClient.Timeout = TimeSpan.FromSeconds();
在单个请求上设置超时,使用删除token方式:
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds());
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:
在Windows.Web.Http.HttpClient上没有超时属性,因此,必须使用上面介绍的删除token方式实现超时功能。
使用身份验证凭据
System.Net.Http:
为了保护用户凭据信息,默认情况下Http协议栈在请求发出时,不能添加任务身份验证信息。如需要使用指定用户验证,使用下面的模式:
var myClientHandler = new HttpClientHandler();
myClientHandler.Credentials = new NetworkCredential(myUsername, myPassword);
Windows.Web.Http:
对于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等值。
使用客户端证书
System.Net.Http:
为了保护用户凭据信息,默认情况下API不会发送任何客户端凭据到服务器上。 使用客户端凭据认证代码如下:
var myClientHandler = new HttpClientHandler();
myClientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
Windows.Web.Http:
使用客户端凭据认证有两个选项,默认是提供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。
cookie处理
默认情况下,二者APIs都保存通过服务器发送的cookies,在相同的app容器内,自动添加上Cookies到那个URL的后续请求上。 这些Cookies被那个明确的URL读取, 添加新的自定义cookies。 二者APIs都有一个选项能禁止发送cookies到服务器上:在System.Net.Http上设置HttpClientHandler.UseCookies为false,在Windows.Web.Http设置HttpBaseProtocolFilter.CookieUsageBehavior为HttpCookieUsageBehavior.NoCookies。
System.Net.Http:
在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);
Windows.Web.Http:
通过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 = ;
最新更新
在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相关开发。
揭秘Windows10 UWP中的httpclient接口[2]的更多相关文章
- python中调用httpclient接口的实例代码
#coding=utf-8 import httplib,urllib #get调用 httpClient=None try: params=urllib.urlencode({'account':' ...
- 讲讲我在Windows10(uwp)开发中遇到的一些坑.
7月29日发布的Windows10正式版,当天安装好以后,在网络不太好的情况下,经过多次尝试终于装上了Visual Studio 2015和Windows 10 10240的SDK.这两周一直在开发U ...
- Windows10(uwp)开发中的侧滑
还是在持续的开发一款Windows10的应用中,除了上篇博客讲讲我在Windows10(uwp)开发中遇到的一些坑,其实还有很多不完善的地方,比如(UIElement.Foreground).(Gra ...
- WebApi接口 - 如何在应用中调用webapi接口
很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...
- 淘宝UWP中的100个为什么
从淘宝UWP第一版发布到现在,已经有十个月了,期间收到了用户各种各样的反馈,感谢这些用户的反馈,指导我们不断的修正.完善应用.但是也有一部分需求或建议,由于资源或技术的限制,目前确实无法做到,只能对广 ...
- UWP中重用C/C++代码时踩过的一些坑
标题中提到的UWP,主要是指用C#来写UWP的主工程,开发过程中可能需要调用C/C++实现的库. 为什么需要调用C/C++的库呢,举个例子,开源库OpenSSL实现了许多加密算法,稳定快速,我们想在应 ...
- 我的面板我做主 -- 淘宝UWP中自定义Panel的实现
在Windows10 UWP开发平台上内置的XMAL布局面板包括RelativePanel.StackPanel.Grid.VariableSizedWrapGrid 和 Canvas.在开发淘宝UW ...
- HttpClient接口测试之会话保持
HttpClient接口测试之会话保持 HttpClient4.X自带会话保持功能,使用同一个HttpClient未关闭的连接即可保持登陆会话,如果多个HttpClient想要使用一个登陆会话 ...
- Windows10 UWP开发 - 响应式设计
Windows10 UWP开发 - 响应式设计 本篇随笔与大家简单讨论一下在开发适配不同分辨率.宽高比的Windows10 Universal App布局时的可行方式与小技巧.经验均从实践中总结, ...
随机推荐
- 本人提供微软系.NET技术顾问服务,欢迎企业咨询!
背景: 1:目前微软系.NET技术高端人才缺少. 2:企业很难直接招到高端技术人才. 3:本人提供.NET技术顾问,保障你的产品或项目在正确的技术方向. 技术顾问服务 硬服务项: 1:提供技术.决策. ...
- 为C# as 类型转换及Assembly.LoadFrom埋坑!
背景: 不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有) 效果是这样的: 之后,有小部分用户反映,工具用不了(没反应或有异常)~~~ 然后,建议小部分用户换个电脑 ...
- Node.js:path、url、querystring模块
Path模块 该模块提供了对文件或目录路径处理的方法,使用require('path')引用. 1.获取文件路径最后部分basename 使用basename(path[,ext])方法来获取路径的最 ...
- WebGIS中等值面展示的相关方案简析
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 等值面是气象.环保等相关项目上常用到的效果展示.在传统的CS项 ...
- 代码的坏味道(14)——重复代码(Duplicate Code)
坏味道--重复代码(Duplicate Code) 重复代码堪称为代码坏味道之首.消除重复代码总是有利无害的. 特征 两个代码片段看上去几乎一样. 问题原因 重复代码通常发生在多个程序员同时在同一程序 ...
- http status code
属于转载 http status code:200:成功,服务器已成功处理了请求,通常这表示服务器提供了请求的网页 404:未找到,服务器未找到 201-206都表示服务器成功处理了请求的状态代码,说 ...
- 常用 meta 整理
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 --> <meta name="HandheldFriendly" con ...
- 如何解决流程开发中SheetRadioButtonList页面取值问题
分享一个常见的取值问题. 应用场景: SheetRadioButtonList控件,点击其中一项执行事件操作.如果是页面加载的情况下,值就无法取到. 具体原因如下: 我给SheetRadioButto ...
- Android Studio —— 创建Menu菜单项
大多数android程序的右上角都会设置一个菜单按钮比如微信的界面右上角的加号. 这个需要在layout同级目录下新建文件夹命名为menu,再右击新建的menu新建xml文件:
- 手动导入swift三方danielgindi/Charts到OC工程中教程
1.到github网址上下载zip压缩包https://github.com/danielgindi/Charts 2.然后将解压后的文件夹整个拖到自己的工程文件夹下(很多教程只让拖xcodeproj ...