首页 > 代码库 > 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cookie 读写; 自定义 HttpFilter; 其他

重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cookie 读写; 自定义 HttpFilter; 其他

[源码下载]


重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cookie 读写; 自定义 HttpFilter; 其他



作者:webabcd


介绍
重新想象 Windows 8.1 Store Apps 之通信的新特性

  • 通过 HttpBaseProtocolFilter 控制缓存逻辑,以及如何通过 HttpBaseProtocolFilter 管理 cookie
  • 自定义 HttpFilter
  • 其他



示例
HTTP 服务端
WebServer/HttpDemo.aspx.cs

/* * 用于响应 http 请求 */using System;using System.IO;using System.Threading;using System.Web;namespace WebServer{    public partial class HttpDemo : System.Web.UI.Page    {        protected void Page_Load(object sender, EventArgs e)        {            // 停 3 秒,以方便测试 http 请求的取消            Thread.Sleep(3000);            var action = Request.QueryString["action"];            switch (action)            {                case "getString": // 响应 http get string                     Response.Write("hello webabcd: " + DateTime.Now.ToString("hh:mm:ss"));                    break;                case "getStream": // 响应 http get stream                     Response.Write("hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd");                    break;                case "postString": // 响应 http post string                     Response.Write(string.Format("param1:{0}, param2:{1}, referrer:{2}", Request.Form["param1"], Request.Form["param2"], Request.UrlReferrer));                    break;                case "postStream": // 响应 http post stream                     using (StreamReader reader = new StreamReader(Request.InputStream))                    {                        if (Request.InputStream.Length > 1024 * 100)                        {                            // 接收的数据太大,则显示“数据接收成功”                            Response.Write("数据接收成功");                        }                        else                        {                            // 显示接收到的数据                            string body = reader.ReadToEnd();                            Response.Write(Server.HtmlEncode(body));                        }                    }                     break;                case "uploadFile": // 处理上传文件的请求                    for (int i = 0; i < Request.Files.Count; i++)                    {                        string key = Request.Files.GetKey(i);                        HttpPostedFile file = Request.Files.Get(key);                        string savePath = @"d:\" + file.FileName;                        // 保存文件                        file.SaveAs(savePath);                        Response.Write(string.Format("key: {0}, fileName: {1}, savePath: {2}", key, file.FileName, savePath));                        Response.Write("\n");                    }                    break;                case "outputCookie": // 用于显示服务端获取到的 cookie 信息                    for (int i = 0; i < Request.Cookies.Count; i++)                    {                        HttpCookie cookie = Request.Cookies[0];                        Response.Write(string.Format("cookieName: {0}, cookieValue: {1}", cookie.Name, cookie.Value));                        Response.Write("\n");                    }                    break;                case "outputCustomHeader": // 用于显示一个自定义的 http header                    Response.Write("myRequestHeader: " + Request.Headers["myRequestHeader"]);                    break;                default:                    break;            }            Response.End();        }    }}


1、演示如何通过 HttpBaseProtocolFilter 控制缓存逻辑,以及如何通过 HttpBaseProtocolFilter 管理 cookie
HttpBaseProtocolFilterDemo.xaml

<Page    x:Class="Windows81.Communication.HTTP.HttpBaseProtocolFilterDemo"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:Windows81.Communication.HTTP"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d">    <Grid Background="Transparent">        <StackPanel Margin="120 0 0 0">            <TextBlock Name="lblMsg" FontSize="14.667" />            <Button Name="btnCacheControl" Content="通过 HttpBaseProtocolFilter 控制缓存逻辑" Click="btnCacheControl_Click" Margin="0 10 0 0" />            <Button Name="btnCookie" Content="通过 HttpBaseProtocolFilter 管理 cookie" Click="btnCookie_Click" Margin="0 10 0 0" />        </StackPanel>    </Grid></Page>

HttpBaseProtocolFilterDemo.xaml.cs

/* * 演示如何通过 HttpBaseProtocolFilter 控制缓存逻辑,以及如何通过 HttpBaseProtocolFilter 管理 cookie *  *  * 注: * 1、HttpBaseProtocolFilter 实现了 IHttpFilter 接口(也就是说如果想要一个自定义 HttpFilter 的话,只要实现 IHttpFilter 接口即可) * 2、本例仅演示通过 HttpBaseProtocolFilter 控制缓存逻辑以及管理 cookie,HttpBaseProtocolFilter 的其它功能请参见文档 */using System;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Navigation;using Windows.Web.Http;using Windows.Web.Http.Filters;namespace Windows81.Communication.HTTP{    public sealed partial class HttpBaseProtocolFilterDemo : Page    {        private HttpClient _httpClient;        private HttpBaseProtocolFilter _filter;        public HttpBaseProtocolFilterDemo()        {            this.InitializeComponent();        }        protected override void OnNavigatedFrom(NavigationEventArgs e)        {            // 释放资源            if (_filter != null)            {                _filter.Dispose();                _filter = null;            }            if (_httpClient != null)            {                _httpClient.Dispose();                _httpClient = null;            }                    }        // 演示如何通过 HttpBaseProtocolFilter 控制缓存逻辑        private async void btnCacheControl_Click(object sender, RoutedEventArgs e)        {            _filter = new HttpBaseProtocolFilter();            // 实例化 HttpClient 时,指定此 HttpClient 所关联的 IHttpFilter 对象            _httpClient = new HttpClient(_filter);            try            {                // 获取到 http 响应的数据后写入缓存的行为                //     NoCache - 不写入缓存                //     Default - 默认行为,一般会写入缓存(默认值)                _filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;                // 请求 http 时,从缓存获取数据的逻辑                //     Default - 使用 RFC 2616 中由 IETF 指定的缓存算法(默认值)                //     MostRecent - 尽可能使用本地 HTTP 缓存,但应始终询问服务器是否有更新的内容可用                //     OnlyFromCache - 只使用本地 HTTP 缓存中的数据,适合脱机的场景                _filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.Default;                HttpResponseMessage response = await _httpClient.GetAsync(new Uri("http://localhost:39630/HttpDemo.aspx?action=getString"));                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;                lblMsg.Text += Environment.NewLine;                lblMsg.Text += await response.Content.ReadAsStringAsync();                lblMsg.Text += Environment.NewLine;            }            catch (Exception ex)            {                lblMsg.Text += ex.ToString();                lblMsg.Text += Environment.NewLine;            }        }        // 演示如何通过 HttpBaseProtocolFilter 管理 cookie        private async void btnCookie_Click(object sender, RoutedEventArgs e)        {            _httpClient = new HttpClient();            try            {                // 构造一个 cookie(需要指定 cookie 的 name, domain, path)                HttpCookie cookie = new HttpCookie("name", "localhost", "/");                cookie.Value = "webabcd";                cookie.Expires = DateTimeOffset.Now.AddDays(1);                cookie.Secure = false;                cookie.HttpOnly = false;                // 通过 HttpBaseProtocolFilter 写入 cookie(也可以获取 cookie 或者删除 cookie)                HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();                bool replaced = filter.CookieManager.SetCookie(cookie, false);                // 请求 http 时会带上相应的 cookie                HttpResponseMessage response = await _httpClient.GetAsync(new Uri("http://localhost:39630/HttpDemo.aspx?action=outputCookie"));                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;                lblMsg.Text += Environment.NewLine;                lblMsg.Text += await response.Content.ReadAsStringAsync();                lblMsg.Text += Environment.NewLine;            }            catch (Exception ex)            {                lblMsg.Text += ex.ToString();                lblMsg.Text += Environment.NewLine;            }        }    }}


2、演示如何使用自定义的 HttpFilter
MyHttpFilter.cs

/* * 实现 IHttpFilter 接口,开发一个自定义的 HttpFilter *  *  * 本 HttpFilter 会在请求和响应的 http header 中添加一条自定义数据 */using System;using System.Runtime.InteropServices.WindowsRuntime;using Windows.Foundation;using Windows.Web.Http;using Windows.Web.Http.Filters;namespace Windows81.Communication.HTTP{    public class MyHttpFilter : IHttpFilter    {        private HttpBaseProtocolFilter _innerFilter;        public MyHttpFilter()        {            _innerFilter = new HttpBaseProtocolFilter();        }        // IHttpFilter 唯一的一个需要实现的方法        public IAsyncOperationWithProgress<HttpResponseMessage, HttpProgress> SendRequestAsync(HttpRequestMessage request)        {            return AsyncInfo.Run<HttpResponseMessage, HttpProgress>(async (cancellationToken, progress) =>            {                // 添加一个自定义 request http header                request.Headers.Add("myRequestHeader", "request webabcd");                // 借用 HttpBaseProtocolFilter 来完成 SendRequestAsync() 的工作                HttpResponseMessage response = await _innerFilter.SendRequestAsync(request).AsTask(cancellationToken, progress);                cancellationToken.ThrowIfCancellationRequested();                // 添加一个自定义 response http header                response.Headers.Add("myResponseHeader", "response webabcd");                return response;            });        }        public void Dispose()        {            _innerFilter.Dispose();            GC.SuppressFinalize(this);        }    }}

CustomHttpFilter.xaml

<Page    x:Class="Windows81.Communication.HTTP.CustomHttpFilter"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:Windows81.Communication.HTTP"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d">    <Grid Background="Transparent">        <StackPanel Margin="120 0 0 0">            <TextBlock Name="lblMsg" FontSize="14.667" />            <Button Name="btnDemo" Content="自定义 HttpFilter" Click="btnDemo_Click" Margin="0 10 0 0" />            <Button Name="btnCancel" Content="cancel" Click="btnCancel_Click" Margin="0 10 0 0" />        </StackPanel>    </Grid></Page>

CustomHttpFilter.xaml.cs

/* * 演示如何使用自定义的 HttpFilter *  *  * 自定义 HttpFilter 需要实现 IHttpFilter 接口,请参见:MyHttpFilter.cs */using System;using System.Threading;using System.Threading.Tasks;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Navigation;using Windows.Web.Http;namespace Windows81.Communication.HTTP{    public sealed partial class CustomHttpFilter : Page    {        private HttpClient _httpClient;        private CancellationTokenSource _cts;        // 自定义的 HttpFilter        private MyHttpFilter _filter;        public CustomHttpFilter()        {            this.InitializeComponent();        }        protected override void OnNavigatedFrom(NavigationEventArgs e)        {            // 释放资源            if (_filter != null)            {                _filter.Dispose();                _filter = null;            }            if (_httpClient != null)            {                _httpClient.Dispose();                _httpClient = null;            }            if (_cts != null)            {                _cts.Dispose();                _cts = null;            }        }        private async void btnDemo_Click(object sender, RoutedEventArgs e)        {            _filter = new MyHttpFilter();            // 实例化 HttpClient 时,指定此 HttpClient 所关联的 IHttpFilter 对象            _httpClient = new HttpClient(_filter);            _cts = new CancellationTokenSource();            try            {                HttpResponseMessage response = await _httpClient.GetAsync(new Uri("http://localhost:39630/HttpDemo.aspx?action=outputCustomHeader")).AsTask(_cts.Token);                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;                lblMsg.Text += Environment.NewLine;                lblMsg.Text += "myResponseHeader: " + response.Headers["myResponseHeader"];                lblMsg.Text += Environment.NewLine;                // IHttpContent.ReadAsStringAsync() - 获取 string 类型的响应数据                // IHttpContent.ReadAsBufferAsync() - 获取 IBuffer 类型的响应数据                // IHttpContent.ReadAsInputStreamAsync() - 获取 IInputStream 类型的响应数据                lblMsg.Text += await response.Content.ReadAsStringAsync();                lblMsg.Text += Environment.NewLine;            }            catch (TaskCanceledException)            {                lblMsg.Text += "取消了";                lblMsg.Text += Environment.NewLine;            }            catch (Exception ex)            {                lblMsg.Text += ex.ToString();                lblMsg.Text += Environment.NewLine;            }        }        private void btnCancel_Click(object sender, RoutedEventArgs e)        {            // 取消 http 请求            if (_cts != null)            {                _cts.Cancel();                _cts.Dispose();                _cts = null;            }        }    }}


3、其他
Other.xaml

<Page    x:Class="Windows81.Communication.Other"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:Windows81.Communication"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    mc:Ignorable="d">    <Grid Background="Transparent">        <StackPanel Margin="120 0 0 0">            <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap">                <Run>1、实时通信支持 Windows.Web.Http API 了(仍然要求 app 必须在锁屏上),关于实时通信请参见:http://www.cnblogs.com/webabcd/archive/2013/10/28/3391694.html</Run>                <LineBreak />                <Run>2、增加了对 Geofence 的支持,即某设备在进入或退出某地理区域后可以向 app 发出通知。Windows.Devices.Geolocation.Geofencing 命名空间用于 Geofence 管理, LocationTrigger 用于后台任务触发 Geofence 事件</Run>                <LineBreak />                <Run>3、支持设备的 WiFi 直连,参见 Windows.Devices.WifiDirect 命名空间</Run>            </TextBlock>        </StackPanel>    </Grid></Page>



OK
[源码下载]