上一篇文章中,我们抛出了N个问题:WCF到底难不难学?复杂吗?如果复杂,可以化繁为简吗?

其实,这些问题的答案全取决于你的心态,都说“态度决定一切”,这句话,不知道各位信不信,反正我是信了。首先,敢于挑战自我,乐于接受新事物的 人,就不会觉得有啥难学的,“世上有难事,只怕有心人”;再者,WCF当然复杂了,整个.NET框架都复杂,但不难学,因为.NET有一个先天性优点—— 集成性和统一性严重地好,这也是我乐于研究.NET的主要原因之一,复杂但不混乱。一个统一的国家总比一个四分五裂的国家要强大;第三,任何东西都可以化 繁为简,关键是你持什么样的心态。编程最高境界就是将程序和自然哲学等多种学术融为一体。

今天聊聊服务协定,这个概念,如果你只停留在字面上去理解,你会发现灰常抽象。有两家公司经过七天七夜的谈判,终于达成基本一致的意见,于是,就签 下了合作协议。根据合作协议要求,两家公司在ABCD项目上互相公开一定程度的资料,以便更好地合作。各位想一想,这个合作协议,像不像我们这里说的服务 协定?是啊,服务协定其实没啥了不起的,刚才签下合作协议的两家公司分别叫“服务器端”和“客户端”。

服务协定告诉客户端,哪些方法你可以调用,哪些数据类型你可使用,至于公不公开接口让你调用,就完全取决于服务器端如何定义服务协定了。

比如下面这个协定:

 
    [ServiceContract]
public interface IServiceA
{
[OperationContract]
int AddInt(int a, int b); [OperationContract]
double AddDouble(double a, double b); float AddFloat(float a, float b);
}

实现该协定:

    {
public int AddInt(int a, int b)
{
return a + b;
} public double AddDouble(double a, double b)
{
return a + b;
} public float AddFloat(float a, float b)
{
return a + b;
}
}

大家可以猜一下,在客户端中生成的代码中,哪你能看到哪些方法,哪些方法将看不到?上面的服务协定中,我们定义了三个方法,其中前两个是带了操作协定 OperationContractAttribute的,而AddFloat方法是没有用标注为协定的。那么,生成的客户端代码会如何呢?

是不是少了一个方法呢?对啊,就是少了AddFloat,还记得吗?我们上面的代码中,AddFloat方法是没有标注为操作协定的。

好的,现在我们为AddFloat加上操作协定,如下所示。

 [ServiceContract]
public interface IServiceA
{
[OperationContract]
int AddInt(int a, int b); [OperationContract]
double AddDouble(double a, double b); [OperationContract]
float AddFloat(float a, float b);
}
 

这时候,看看在客户端能看到多少个方法。

这回全到齐了,对吧。

下面来看看服务的命名空间。

ServiceContractAttribute有个属性Namespace,用于设置服务的命名空间,由于避免放到互联网中与其它服务冲突,命名空间必须是唯一的(其实就是XML命名空间),多数情况下,我们会使用公司主页的地址或个人网站地址,因为这些地址是唯一的。

在不设置命名空间的时候,我们看看客户端代码默认生成的命名空间是什么。

在“解决方案资源管理器”窗口上,点击“显示所有文件”,如下图所示。

打开.wsdl文件。

 
  <wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/Imports">
<xsd:import schemaLocation="http://localhost:9000/service?xsd=xsd0" namespace="http://tempuri.org/" />
<xsd:import schemaLocation="http://localhost:9000/service?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
</xsd:schema>
</wsdl:types>

我们看到,默认的命名空间是http://tempuri.org/,然后,回到服务器端的代码,我们显式设置一个命名空间,看看生成的客户端代码又将如何。

    [ServiceContract(Namespace = "http://MyApp.net")]
public interface IServiceA
{
[OperationContract]
int AddInt(int a, int b); [OperationContract]
double AddDouble(double a, double b); [OperationContract]
float AddFloat(float a, float b);
}
 

好了,现在再看看WSDL文件会变成啥样。

我们发现,现在的WSDL文件和刚才不一样了,上面出现了我们自定义的命名空间。

我们也许还会问,命名空间一定要用http://的方式吗?我用其它字符串行吗?不必问,试一下就知道了。

    [ServiceContract(Namespace = "FuckingDog")]
public interface IServiceA
{
.............

再看看这次生成的客户端代码中,WSDL中是如何描述。

好了,结论出来了。

ServiceContractAttribute类还有一个属性Name,那么设置了该属性会发生什么?不急,我们先来看看不设置Name的情况下是如何。

我们看到,默认情况下,生成的WSDL直接使用服务协定的名字,即IServiceA。那么,如果我们在定义服务协定时修改了Name属性,那会如何?

    [ServiceContract(Namespace = "FuckingDog", Name = "HaHaHa")]
public interface IServiceA
{
.......

看对比一下生成的WSDL文件。

现在,就变成“HaHaHa”了,呵呵,这有啥用呢?哈,问你一句,如果你上网聊天的时候,不希望对方知道你的真实姓名时,你会咋办?嘿,弄个网名呗,就是了,为服务协定弄一下Name属性,就相当于为它取一个网名呗。

还有哦,这个网名不仅仅服务协定可以取,操作协定也可以,来,看看。

[ServiceContract(Namespace = "FuckingDog", Name = "HaHaHa")]
public interface IServiceA
{
[OperationContract(Name = "OperatFirst")]
int AddInt(int a, int b); [OperationContract(Name = "OperatSecond")]
double AddDouble(double a, double b); [OperationContract(Name = "OperatThird")]
float AddFloat(float a, float b);
}
 

你猜猜,这样改了以后,生成的客户端代码会啥样子?

猜对了吗?这样一来啊,调用服务的人就不知道你姓甚名谁了。

怎么样?WCF有趣不?本文的服务器端示例完整代码清单如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description; namespace Server
{
[ServiceContract(Namespace = "FuckingDog", Name = "HaHaHa")]
public interface IServiceA
{
[OperationContract(Name = "OperatFirst")]
int AddInt(int a, int b); [OperationContract(Name = "OperatSecond")]
double AddDouble(double a, double b); [OperationContract(Name = "OperatThird")]
float AddFloat(float a, float b);
} public class MyService : IServiceA
{
public int AddInt(int a, int b)
{
return a + b;
} public double AddDouble(double a, double b)
{
return a + b;
} public float AddFloat(float a, float b)
{
return a + b;
}
} class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(MyService),new Uri("http://localhost:9000/service")))
{
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.None;
host.AddServiceEndpoint(typeof(IServiceA), binding, "contract1");
host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
host.Opened += (sd, arg) => Console.WriteLine("服务已启动。");
try
{
host.Open();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
host.Close();
}
}
}
}

最后,说说WSDL的事儿,这个家伙我们了解一下就够了,为啥,我们不必自己动手写WSDL文档,甚至说,你看不懂也不影响编程,因为强大的Visual Studio在我们引用服务时,会为我们生成所需的代码,我们就像使用一般类一个使用就可以了。

若想了解WSDL,看看这个,不错,挺简洁明了的。http://www.w3school.com.cn/wsdl/index.asp

传说中的WCF(2):服务协定的那些事儿的更多相关文章

  1. [转] 传说中的WCF(2):服务协定的那些事儿

    上一篇文章中,我们抛出了N个问题:WCF到底难不难学?复杂吗?如果复杂,可以化繁为简吗? 其实,这些问题的答案全取决于你的心态,都说“态度决定一切”,这句话,不知道各位信不信,反正我是信了.首先,敢于 ...

  2. WCF入门教程(三)定义服务协定--属性标签

    WCF入门教程(三)定义服务协定--属性标签 属性标签,成为定义协议的主要方式.先将最简单的标签进行简单介绍,以了解他们的功能以及使用规则. 服务协定标识,标识哪些接口是服务协定,哪些操作时服务协定的 ...

  3. 【WCF全析(一)】--服务协定及消息模式

    上周微软开发布会说.NET支持完全跨平台和并开放Core源码的新闻,让我们顿时感到.NET要迎来它的春天.虽然早在几年前.NET就能开发Android和IOS,但是这次的跨平台把Linux都放到了微软 ...

  4. WCF初探-14:WCF服务协定

    前言: 在前面的文章中,我们定义的服务协定上都会有一个ServiceContract的特性来修饰,这是因为服务契约的实现要靠ServiceContractAttribute 属性定义,然后使用一个或多 ...

  5. WCF学习心得------(二)设计和实现服务协定

    设计和实现服务协定 创建服务协定—WCF术语 消息 消息是一个独立的数据单元,它可能由几个部分组成,包括消息正文和消息头. 服务 服务是一个构造,它公开一个或多个终结点,其中每个终结点都公开一个或多个 ...

  6. 传说中的WCF(8):玩转消息协定

    Message翻译成中文,相信各位不陌生,是啊,就是消息,在WCF中也有消息这玩意儿,不知道你怎么去理解它.反正俺的理解,就像我们互发短信一个道理,通讯的双方就是服务器与客户端,说白了吧,就是二者之间 ...

  7. 传说中的WCF(5):数据协定(a)

    在第4篇中,咱们了解了发送/接收SOAP头,从本篇开头,我们不妨更深入地去探求一下有关WCF中的消息到底是啥玩意儿.WCF庞大而复杂,而从 MSDN文档中,你会看到许多很专业很抽象的东西,你不禁会问, ...

  8. 传说中的WCF(3):多个协定

    我们知道,WCF服务端是先定义服务协定,其实就是一个接口,然后通过实现接口来定义服务类.那么,有一个问题,如果一个服务类同时实现N个接口(也就是有N个协定)呢?结果会如何? 不必猜,我们还是通过实验来 ...

  9. 【架构之路之WCF全析(一)】--服务协定及消息模式

    上周微软开公布会说.NET支持全然跨平台和并开放Core源代码的新闻,让我们顿时感到.NET要迎来它的春天.尽管早在几年前.NET就能开发Android和IOS,可是这次的跨平台把Linux都放到了微 ...

随机推荐

  1. TextSwitcher,译为文字转换器控件

    ViewSwitcher仅仅包含子类型TextView.TextSwitcher被用来使屏幕上的label产生动画效果.每当setText(CharSequence)被调用时,TextSwitcher ...

  2. .net 面试问题 汇总

    用.net做B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为什么要这样分层? 答: 从下至上分别为:数据访问层.业务逻辑层(又或成为领域层).表示层 数据访问层:有时候也称为是持久层,其 ...

  3. JVM学习总结五(番外)——VisualVM

    距离上次介绍Jconsole已经时隔两周了,这期间由于工作中要用go来做一个新项目,所以精力都用在入门go上了,不过发现go语言用起来真的挺不错的,比python感觉还好点,大家没事可以了解下.   ...

  4. 配置 apt-get cloudera 离线source(Cloudera Manager的源)

    配置 apt-get cloudera 离线source(Cloudera Manager的源) 创建/etc/apt/source.list.d/cloudera-manager.list文件,并在 ...

  5. libmemcached upcoming ISO C++ standard, C++0x

    在编译我的小程序的时候,触发了一个编译错误,程序中使用了libmemcached,错误如下: 1 2 3 4 5 6 7 8 9 In file included from /usr/lib/gcc/ ...

  6. [译]rabbitmq 2.4 Multiple tenants: virtual hosts and separation

    我对rabbitmq学习还不深入,这些翻译仅仅做资料保存,希望不要误导大家. With exchanges, bindings, and queues under your belt, you mig ...

  7. 使用 RestEasy 和 Apache Tomcat 构建 RESTful Web 服务

    第一次,用这个RestEasy框架,用的时候,总是提示,404的错误,郁闷,呵呵,不过经过努力,终于解决问题,特别留个标记. 关于404的错误,上网找了一大堆,也还不行. 我感觉应该是lib下面架包的 ...

  8. 使用Ajax.BeginForm 中需要 上传文件 但 Request.files获取不到

    使用Mvc里的插件jquery.unobtrusive-ajax.min.js 之前一直困在这里,一开始以为添加属性enctype="multipart/form-data"就可以 ...

  9. C++异常机制知识点

     在这里总结一下,C++中的异常机制,以及如何使用异常的知识点 C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决 ...

  10. 基于.net mvc的校友录(六、codefirst的使用以及班级模块的关键部分实现)

    通过EF将新用户存入数据库 这里,探讨一下如何使用EF的code first将数据存入数据库,以及如何对用户的密码进行md5加密与验证.下面是用户登陆的前台代码. @using (Html.Begin ...