• 重新想象 Windows 8.1 Store Apps (90)


    [源码下载]


    重新想象 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("
    ");
                        }
                        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("
    ");
                        }
                        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
    [源码下载]

  • 相关阅读:
    <Android 应用 之路> 天气预报(五)
    Java图形界面开发—列出指定目录
    解决The Network Adapter could not establish the connection
    <Android 应用 之路> 天气预报(四)
    Java集合框架—List
    Java集合框架—Map
    C#工程缺少IIS组件无法打开的解决办法
    关于com工程依赖的一些总结
    C:移位运算符
    void类型及void指针
  • 原文地址:https://www.cnblogs.com/webabcd/p/3911643.html
Copyright © 2020-2023  润新知