少有人走的路

勇哥的工业自动化技术网站

wcf的条件获取(Conditional Retrieval)

勇哥注:

条件获取(Conditional Retrieval):

客户端访问一个资源会对它进行缓存,当再次访问这个资源的时候,如果资源相比缓存来说没任何变化,就不会返回真正的资源,而是回复一个“标识”,表明资源并没有改变。

这个特性是http天生带有的,因此像wsHttpBind, webHttpBind, basicHttpBind,REST服务等,都可以使用。


http的条件获取机制是这样的:

下面是两次读同一资源的过程,客户端与服务端按序号顺序进行。

客户端:

    1。发送请求

    3。从回复中取得Etag报头,缓存起来

    4。为http请求加If-None-Match报头(内容就是第3步取得的Etab报头)

   6。收第二次请求的结果,要么是304空内容,要么是有内容。


服务端:

   2。返回body+Etag报头

   5。通过If-None-Match确认当前要发送的资源是不是一致,如果一致发304(Not Modified)的空消息

        如果不一致,则返回body+新的Etag报头


下面这个例子演示读写IO。

当读IO时发现并没有位改变过的时候,返回一个资源没有改变的标识,否则的话返回新的数据。


服务端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace ConsoleClient
{

    public class ReadWriteIO : IReadWriteIO
    {
        private static List<int> ioList = new List<int>() {1,1,1,1,1 };

        public IEnumerable<int> GetAll()
        {
            int hashcode= ioList.GetHashCode();
                    //立刻检查eTag,如果相同则会返回304错误
                    WebOperationContext.Current.IncomingRequest.CheckConditionalRetrieve(hashcode);
                    //到这里就是资源有变化了,返回etab+资源内容
                    WebOperationContext.Current.OutgoingResponse.SetETag(hashcode);
           return ioList;
        }

        public int GetBit(string bitno)
        {
            return ioList[int.Parse(bitno)];
        }

        public void WriteBit(WriteBitData data)
        {
            ioList[int.Parse(data.bitno)] = int.Parse(data.bitValue);
        }
    }

    [ServiceContract(Namespace ="www.skcircle.com")]
    public interface IReadWriteIO
    {
        [WebGet(UriTemplate ="all")]
        IEnumerable<int> GetAll();

        [WebInvoke(UriTemplate = "{bitno}", Method ="GET")]
        int GetBit(string bitno);

        [WebInvoke(UriTemplate = "/", Method = "POST", 
            RequestFormat = WebMessageFormat.Json, 
            ResponseFormat = WebMessageFormat.Json, 
            BodyStyle = WebMessageBodyStyle.Bare)]
        void WriteBit(WriteBitData data);
    }

    public class WriteBitData
    {
        public string bitno { get; set; }
        public string bitValue { get; set; }
    }

}

划重点:

  1.    private static List<int> ioList = new List<int>() {1,1,1,1,1 };

       ioList必须是static静态的。否则的话GetAll中每次取得的哈希码都不同。

  2.    检查etag的代码,见代码中的注释。



客户端代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void BtnGetall_Click(object sender, EventArgs e)
        {
            eTag = "";
            GetAll();
            GetAll();
        }

        string eTag;
        private void GetAll()
        {
            Uri uri = new Uri("http://127.0.0.1:9998/ReadWriteIO/all");
            var req=HttpWebRequest.Create(uri);
            if(!string.IsNullOrEmpty(eTag))
            {
                req.Headers.Add(HttpRequestHeader.IfNoneMatch, eTag);
            }
            req.Method = "GET";
            try
            {
                var res= req.GetResponse();
                eTag = res.Headers[HttpResponseHeader.ETag];
                using (StreamReader read = new StreamReader(res.GetResponseStream(), Encoding.UTF8))
                {
                   RtbMsg.AppendText($"{read.ReadToEnd()}\r\n");
                }
            }
            catch(WebException ex)
            {
                var res = ex.Response as HttpWebResponse;
                if (res == null) throw;
                if(res.StatusCode== HttpStatusCode.NotModified)
                {
                    RtbMsg.AppendText("IO状态没有发生变化");
                    return;
                }
                throw;
            }

        }
    }
}

划重点:

因为是REST服务的调用,即然可以通过浏览器访问地址:http://127.0.0.1:9998/ReadWriteIO/all

那么当然也可以通过HttpWebRequest类得到一样的访问效果。

这种方式的好处是客户端不需要服务引用,整什么代理类,我只要知道一个域名就可以了。



客户端效果如下:

第二次取相同资源的时候,服务器抛出了异常。

表示资源没有变化。

image.png


本文源码下载:


链接:https://pan.baidu.com/s/12MscgB6MmppB8B5kOWgdeQ 

提取码:tv0y 

--来自百度网盘超级会员V6勇哥的分享



发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接

Powered By Z-BlogPHP 1.7.3

Copyright www.skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864