关于已部署的WCF服务升级的问题
在日常的开发过程中,我们会经常迭代发布不同的版本,所以WCF服务的接口也会经常处于变动的状态,比如在传递实体类中新加一个字段、修改参数名称等等关于服务升级的问题。但是我们不可能让已发布的版本重新引用新的服务,这是不现实的,所以我们在升级WCF服务时,一定要让服务兼容以前的版本。现在我们分别介绍关于服务升级的几个常用情况。
一、参数变动
我们来实现最初的版本1.0,新建一个服务接口,服务实现很简单,在Output窗口中简单输出服务接收到的参数值。
[ServiceContract]
public interface ITestingService
{
[OperationContract]
void AddUser(string id, string username, int age);
}
public class TestingService : ITestingService
{
public void AddUser(string id, string username, int age)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", username)); System.Diagnostics.Debug.WriteLine(string.Format("age = {0}", age));
}
}
在客户端引用1.0版本的服务,调用服务接口
class Program
{
static void Main(string[] args)
{
var testingServiceClient = new TestingServiceClient(); testingServiceClient.AddUser("", "James", ); Console.ReadKey();
}
}
在服务端的Output输出结果如下
1.添加参数
考虑一种特别常用的情形,我需要添加一个新的字段,以便得到更多的信息,我们需要升级服务至2.0,所以我们需要修改接口和实现。最终的结果当然是不影响引用1.0服务的客户端的继续使用。
让我们修改接口和实现。
[ServiceContract]
public interface ITestingService
{
[OperationContract]
void AddUser(string id, string username, int age, string city);
}
public class TestingService : ITestingService
{
public void AddUser(string id, string username, int age, string city)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", username)); System.Diagnostics.Debug.WriteLine(string.Format("age = {0}", age)); System.Diagnostics.Debug.WriteLine(string.Format("city = {0}", city));
}
}
首先我们需要保证引用1.0服务的客户端的继续使用,所以我们先测试引用1.0服务的客户端。
从测试结果可以看到,在引用旧的服务的客户端在调用新的服务时,可以正常调用,只是新添加的字段是默认值。这是正确的结果,因为在旧的客户端传递过来的数据中不包含新添加的字段的信息,自然新添加的字段的值是默认的值。
2.删除不再需要的参数
紧接1.0版本,假设在新的2.0版本中不再需要age的值,所以需要在接口中删除这个参数,所以需要修改接口和实现。
[ServiceContract]
public interface ITestingService
{
[OperationContract]
void AddUser(string id, string username);
}
public class TestingService : ITestingService
{
public void AddUser(string id, string username)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", username));
}
}
首先我们需要保证引用1.0服务的客户端的继续使用,所以我们先测试引用1.0服务的客户端。
从测试结果可以看到,在引用旧的服务的客户端在调用新的服务时,可以正常调用。
3.修改参数名(重构)
紧接1.0版本,假设在新的2.0版本中需要修改username名为name,所以需要修改接口和实现。
[ServiceContract]
public interface ITestingService
{
[OperationContract]
void AddUser(string id, string name);
}
public class TestingService : ITestingService
{
public void AddUser(string id, string name)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", name));
}
}
在保证客户端不引用新的服务的前提下,我们测试客户端的服务调用情况。
从结果可以看到,如果修改了参数的名称则会影响到旧版本客户端的使用,难道没有别的什么方法可以解决这个问题么?答案是有的,如果想要重构但是不想改动客户端代码的话,那么可以给参数加上一个MessageParameter的属性,代码如下:
[ServiceContract]
public interface ITestingService
{
[OperationContract]
void AddUser(string id, [MessageParameter(Name = "username")]string name);
}
重新测试旧版本的客户端,可以看到最终的结果又恢复正常。
二、实体的变动
在第一部分我们谈论的是参数的变动,在第二部分我们变化实体中属性的变动。先来定义最初的1.0服务版本。
[DataContract]
public class User
{
[DataMember]
public string Id
{
get;
set;
} [DataMember]
public string Name
{
get;
set;
} [DataMember]
public int Age
{
get;
set;
} }
[ServiceContract]
public interface ITestingService
{
[OperationContract]
void AddUser(User user);
}
public class TestingService : ITestingService
{
public void AddUser(User user)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", user.Id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", user.Name)); System.Diagnostics.Debug.WriteLine(string.Format("age = {0}", user.Age));
}
}
客户端引用最初的服务
class Program
{
static void Main(string[] args)
{
var testingServiceClient = new TestingServiceClient(); var user = new User() { Id = "", Name = "Tommy", Age = }; testingServiceClient.AddUser(user); Console.ReadKey();
}
}
测试结果如下
1.在实体类中添加属性
在User类中添加City属性,以便在新的服务版本中获取更多的用户信息。服务接口不变,只需修改实体类和服务实现。
[DataContract]
public class User
{
[DataMember]
public string Id { get; set; } [DataMember]
public string Name { get; set; } [DataMember]
public int Age { get; set; } [DataMember]
public string City { get; set; } }
public void AddUser(User user)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", user.Id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", user.Name)); System.Diagnostics.Debug.WriteLine(string.Format("age = {0}", user.Age)); System.Diagnostics.Debug.WriteLine(string.Format("city = {0}", user.City));
}
在保证客户端不引用新的服务的前提下,测试客户端的服务调用情况。从结果可以看出,旧的客户端可以正常调用新的服务,只是新添加的字段没有显式赋值。
2.在实体类中删除属性
在User类中删除Age属性。服务接口不变,只需修改实体类和服务实现。
[DataContract]
public class User
{
[DataMember]
public string Id { get; set; } [DataMember]
public string Name { get; set; } }
public class TestingService : ITestingService
{
public void AddUser(User user)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", user.Id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", user.Name)); }
}
在保证客户端不引用新的服务的前提下,测试客户端的服务调用情况。从结果可以看出,旧的客户端可以正常调用新的服务。
3.在实体类中修改属性名
在User类中修改Name属性的名称为UserName。服务接口不变,只需修改实体类和服务实现。
[DataContract]
public class User
{
[DataMember]
public string Id { get; set; } [DataMember]
public string UserName { get; set; } [DataMember]
public int Age { get; set; } }
public class TestingService : ITestingService
{
public void AddUser(User user)
{
System.Diagnostics.Debug.WriteLine(string.Format("id = {0}", user.Id)); System.Diagnostics.Debug.WriteLine(string.Format("username = {0}", user.UserName)); }
}
在保证客户端不引用新的服务的前提下,测试客户端的服务调用情况。
从结果可以看到,如果修改了实体属性的名称则会影响到旧版本客户端的使用,可以在DataMemeber中设定Name属性的值,代码如下
[DataMember(Name = "Name")]
public string UserName { get; set; }
重新测试客户端,发现可以继续正常使用。
关于已部署的WCF服务升级的问题的更多相关文章
- WCF服务部署到IIS上,然后通过web服务引用方式出现错误的解决办法
本文转载:http://www.cnblogs.com/shenba/archive/2012/01/06/2313932.html 昨天在用IIS部署一个WCF服务时,碰到了如下错误: 理解了文档内 ...
- WCF服务端与客户端时间匹配问题
当服务端部署的WCF服务服务在被客户机调用时,如果显示: 错误,展开后,详细错误为:An error occurred when verifying security for the message ...
- 关于WCF服务 http://XXXXXX/XXX/xxx.svc不支持内容类型 application/sop+xml;charset=utf-8 错误解决方法
有时候用IIS部署一个WCF服务时,无论是在客户端还是在服务端通过地址都能正常访问. 但是当你在客户端添加服务引用时, 怎么也添加不上, 会碰到了如下错误: 好啦. 现在说说怎么解决吧. 其实很简单. ...
- WCF学习之旅—WCF服务部署到应用程序(十)
上接 WCF学习之旅—WCF寄宿前的准备(八) WCF学习之旅—WCF服务部署到IIS7.5(九) 五.控制台应用程序宿主 (1) 在解决方案下新建控制台输出项目 ConsoleHosting.如下 ...
- Wcf for wp8 使用iis Express 承载Wcf服务部署发布网站(三)
我们接下来要做的是 本地电脑当作服务器(模拟外网服务器)来承载Wcf服务程序,通过引用本地电脑ip地址访问wcf服务程序接口 http://192.168.1.123/Service1.svc 一.先 ...
- WCF系列教程之WCF服务宿主与WCF服务部署
本文参考自http://www.cnblogs.com/wangweimutou/p/4377062.html,纯属读书笔记,加深记忆. 一.简介 任何一个程序的运行都需要依赖一个确定的进程中,WCF ...
- .Net WCF服务部署IIS详细解析
官方解析:Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台.整合了原有的windows通 ...
- WCF学习之旅—WCF服务部署到IIS7.5(九)
上接 WCF学习之旅—WCF寄宿前的准备(八) 四.WCF服务部署到IIS7.5 我们把WCF寄宿在IIS之上,在IIS中宿主一个服务的主要优点是在发生客户端请求时宿主进程会被自动启动,并且你可以 ...
- WCF服务部署IIS
一.将WCF服务部署到IIS上 [转载自简单笑容——http://www.cnblogs.com/skdsxx/p/5072726.html ] 1.首先检测电脑上是否安装了IIS,一般来说Win7 ...
随机推荐
- Go搭建一个博客系统
go语言环境就不用多说了,版本肯定越高越好,这里用go1.10 先放着
- 用JavaScript动态实现单元格合并
不太想描述,大家自行理解吧,这样可能记忆会深一点儿- <script type="text/javascript"> function mergeCells(){ va ...
- linux redhat NFS网络共享搭建
nfs网络共享 测试环境: 服务端:redhat6.7 ip:192.168.1.100 客户端:redhat6.7 ip:192.168.1.110 一.服务端 1.创建共享文件夹 权限666即可 ...
- 北京Uber优步司机奖励政策(1月18日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- leetcode笔记10 Intersection of Two Arrays(求交集)
问题描述: Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, ...
- SpringBoot入门(四)——自动配置
本文来自网易云社区 SpringBoot之所以能够快速构建项目,得益于它的2个新特性,一个是起步依赖前面已经介绍过,另外一个则是自动配置.起步依赖用于降低项目依赖的复杂度,自动配置负责减少人工配置的工 ...
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 – 员工离职管理
C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 – 员工离职管理 当公司有几万人,上千家加盟网点,几个庞大的直属分公司后,系统账户的有效管理也是一个头疼的问题,把所有的帐户及时进行科学 ...
- 抓取Oracle数据快照
进入到oracle安装目录下的admin(找到这个目录)开启cmd键入sqlplus system/mima@实例名>@awrrpt.sql Would you like an HTML rep ...
- ansible基础配置使用(一)
test test test
- 第六模块:WEB框架开发 第1章·Django框架开发88~128
88-Ajax简介 89-Ajax的简单实现 90-基于Ajax的传递数据 91-基于Ajax的登录验证 92-基于Form表单的文件上传 93-请求头之contentType 94-Ajax传递js ...