专栏首页dotnet & javaWCF入门(12)

WCF入门(12)

前言

  上次写是小半年前的事情了,还在原来的公司,还在原来的项目,同时认识了不少人。外包公司总是有些不适应的地方,总在很闲和很忙之间徘徊。凌晨2点被客户电话叫醒,只为copy一个文件从一台服务器到另一台服务器,虽然那时候我才刚睡下。似乎好想吐槽……罢了。

  项目中有个http转https的需求还是印象深刻的。首先是证书的问题,通过看作者的asp.net的视频了解到IIS有Self-Signed Certificate 的东西可以用来方便的在IIS上部署需要https访问的站点而不需要去其他地方申请。然后是如何对WCF进行https配置。这一 点在视频第52集有讲到。

言归正传。

第12集 Backward compatible WCF contract changes WCF合约改变后的向后兼容性

  这一集主要内容来自https://msdn.microsoft.com/en-us/library/ff384251.aspx ,所以可以直接看上面的链接。

  一般来说WCF服务部署到生产环境后,因为客户端的代理类已经生成,所以,服务端不建议再做更改。但总会有避免不了要更改的情况。下面就通过2个表格来对典型的情况做一些说明。简单来说,DataContractSerializer 允许一下情况

① 缺失非必须参数,

② 忽视多余的参数。

③ Only the removal of operations or the addition or removal of required data causes problems with existing clients. (没看懂。。。)

表1: Service Contract的向后兼容性

服务端合约改变

对现有客户端的影响

对原有的Operation也就是方法增加参数

没有影响,服务端会使用该参数的默认值

移除原有的Operation的某些参数

没有影响,服务端直接忽略

改变参数的类型

如果类型之间可以转换,比如short到int,就没有问题,但是如果是不可转换的类型,比如int到DateTime,客户端就会得到异常

改变方法的返回值类型

如果新的返回值类型不能转换为客户端需要的类型,客户端就会获取到异常,否则不会

增加新的Operation

客户端无法调用到,所以不会有影响

移除Operation

如果客户端继续调用被删除的方法,则会得到异常,(使用未知的action)

表2:Data Contract的向后兼容性

Data Contact改变

对现有客户端的影响

添加非必须的成员变量(System.Runtime.Serialization.DataMemberAttribute特性中IsRequired=False)

没有影响,值被初始化为默认值

添加必须的成员变量(System.Runtime.Serialization.DataMemberAttribute特性中IsRequired=True)

有异常

移除非必须的成员

没有异常,但是数据丢失,

移除必须的成员

客户端接收到的response不符合客户端的代理类合约定义,所以会获取的异常

修改现有成员的数据类型

看类型是否兼容,不兼容则有异常

下面对表2中的第2项做个test, 权当练练手。。

1. 首先给IEmployeeService 加个GetEmployeeInfo的OperationContract,然后在EmployeeService里面实现。

        public string GetEmployeeInfo(Employee emp)
        {
            return String.Format("name= {0}, id= {1}", emp.Name, emp.Id);
        }

因为要试验当一个DataContract 在Client不知情的情况下添加一个IsRequired的DataMember之后对Client的影响,所以,简单起见,就直接接收一个Employee的参数。

2. 下面是Employee的定义:

    [DataContract]
    public class Employee
    {
        [DataMember(IsRequired = true)]
        public int Id { get; set; }
        [DataMember(IsRequired = false)]
        public String Name { get; set; }
        [DataMember]
        public Boolean Gender { get; set; }
        [DataMember]
        public DateTime DateOfBirth { get; set; }
        [DataMember]
        public short EmployeeType { get; set; }
        //[DataMember(IsRequired = true)]
        //public string City { get; set; }
    }

注意, Emploee类要用DataContract特性修饰。 原先是不带City属性,下面给他添加IsRequired的属性。

    [DataContract]
    public class Employee
    {
        [DataMember(IsRequired = true)]
        public int Id { get; set; }
        [DataMember(IsRequired = false)]
        public String Name { get; set; }
        [DataMember]
        public Boolean Gender { get; set; }
        [DataMember]
        public DateTime DateOfBirth { get; set; }
        [DataMember]
        public short EmployeeType { get; set; }
        [DataMember(IsRequired = true)]
        public string City { get; set; }
    }

3. 启动Service

4. 打开EmployeeServiceClient项目,查看里面的Employee定义,因为City属性是后来加的,所以代理类里面不带City属性。

    [Serializable]
    [DataContract(Name = "Employee", Namespace = "http://schemas.datacontract.org/2004/07/EmployeeService")]
    [DebuggerStepThrough]
    [GeneratedCode("System.Runtime.Serialization", "4.0.0.0")]
    public class Employee : IExtensibleDataObject, INotifyPropertyChanged
    {
        public Employee();

        [DataMember]
        public DateTime DateOfBirth { get; set; }
        [DataMember]
        public short EmployeeType { get; set; }
        public ExtensionDataObject ExtensionData { get; set; }
        [DataMember]
        public bool Gender { get; set; }
        [DataMember(IsRequired = true)]
        public int Id { get; set; }
        [DataMember]
        public string Name { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName);
    }

5. 编写如下测试代码:

protected void btnTest_Click(object sender, EventArgs e)
    {
        try {
            var client = new EmployeeServiceClient();
            var emp = new Employee() { Name = "Lou" };
            lbRstMsg.Text = client.GetEmployeeInfo(emp);
        } catch(Exception ex) {
            lbRstMsg.Text = ex.Message;
        }
    }

6. 点击测试按钮 得到如下结果:

由ErrorMessage中可知,服务端想得到一个City,但是没有获取到这个参数由于我们的测试代码里面没有也不能提供这个参数。

Thank you。 就这样把。 最后说一句,要视频的进群378190436

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute

    ASP.NET Core MVC 2.1 特意为构建 HTTP API 提供了一些小特性,今天主角就是 ApiControllerAttribute. (注:文...

    _淡定_
  • datatables 配套bootstrap3样式使用小结(1)

    公司CMS内容资讯站的后台管理界面用了大量的table来管理数据,试用了之后,感觉挺不错,推荐一下。

    _淡定_
  • [SpingBoot guides系列翻译]文件上传

    mkdir -p src/main/java/hello,其实也就是在IntelliJ里面新建一个空的Java项目,然后添加一个main.java.hellop...

    _淡定_
  • ABP框架学习之——数据校验

    易兒善
  • Unity高级(1)-服务器与网络交互

    HTTP/1.1 200 OK // 包含了HTTP协议版本、状态码、状态英文名称 Server: Apache-Coyote/1.1 ...

    雷潮
  • Unity高级(1)-服务器与网络交互

    HTTP/1.1 200 OK // 包含了HTTP协议版本、状态码、状态英文名称 Server: Apache-Coyote/1.1 ...

    啦啦啦
  • Java常用设计模式

    工厂是干嘛的,就是用来生产的嘛,这里说的工厂也是用来生产的,它是用来生产对象的。也就是说,有些对象我们可以在工厂里面生产,需要用时直接从工厂里面拿出来即可,而不...

    贪挽懒月
  • 初探Java设计模式2:结构型模式(代理模式,适配器模式等)

    转自https://javadoop.com/post/design-pattern

    Java技术江湖
  • 初探Java设计模式2:结构型模式(代理模式,适配器模式等)

    转自https://javadoop.com/post/design-pattern

    Java技术江湖
  • 访问者模式

    静态绑定,是重写的时候就断定要绑定那个,例如定义年轻演员的时候,重写的act方法,此时为静态绑定了KungFuRole,

    mySoul

扫码关注云+社区

领取腾讯云代金券