WCF的三个名称/命名空间,你是否傻傻分不清楚?

在定义和寄宿WCF服务的时候会面临三个名称/命名空间,它们分别是ServiceContractAttribute、ServiceBehaviorAttribute和Binding的Name和Namespace属性,很对人对此不能很好地区分。

一、ServiceContractAttribute的名称/命名空间

每个服务契约都有一个确定的名称,当在一个接口或类上应用了ServiceContractAttribute特性,默认的名称就是接口或类的名称。我们可以通过Name属性显式地指定需要的名称,这在某些场景中往往具有重要的作用。比如在客户端有一个通过接口的形式定义的服务契约,现有的很多客户端代码均依赖于这个接口,如果这个时候服务方的名称改变了,客户端仅须更新这个Name属性,从而避免修改接口的名称而造成对现有代码的影响。

   1: public sealed class ServiceContractAttribute : Attribute
   2: {   
   3:     //其他成员    
   4:     public string Name { get; set; }
   5:     public string Namespace { get; set; }
   6: }

至于服务契约的命名空间,其作用和我们托管语言(比如C#、VB.NET)的命名空间完全一样,旨在解决命名冲突问题。很多WCF的编程人员都不太注重在定义服务契约的时候指定命名空间,这是一个不太好的习惯。我们鼓励采用包含你所在的公司名称或项目名称作为命名空间。WCF默认采用的命名空间是http://tempuri.org/

作为服务的描述信息,服务契约作为WSDL的一部分以元数据的形式发布出来。WSDL通过<portType>元素定义相应的服务契约。ServiceContractAttribute的Name和Namespace属性对应着用于描述服务契约的<portType>元素的名称和命名空间。

   1: [ServiceContract(Name = "CaclService", Namespace = "http://www.artech.com/")]
   2: public interface ICalculator
   3: {
   4:     //省略成员
   5: }

如上面的代码所示,我们应用了ServiceContractAttribute特性将接口ICalculator接口定义成服务契约。ServiceContractAttribute的Name和Namespace分别被设置成CaclService和http://www.artech.com/"。服务契约将会对应着如下一段WSDL。

   1: <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
   2:                   xmlns: tns = "http://www.artech.com/"...>
   3:    <wsdl:portType name="tns:CaclService">
   4:      ...
   5:   </wsdl:portType>
   6: </wsdl:definitions>

二、ServiceBehaviorAttribute的名称和命名空间

关于通过ServiceContractAttribute特性定义的服务契约的名称和命名空间,很多人会和通过ServiceBehaviorAttribute定义的名称和命名空间混淆。

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //其他成员
   5:     public string Name { get; set; }
   6:     public string Namespace { get; set; }
   7: }

实际上服务行为特性ServiceBehaviorAttribute定义的是服务本身的名称和命名控件。这两个属性将作为整个WSDL根节点< definitions >的name和targetNamespace属性。如果没有对其进行显式设置,默认的命名空间为http://tempuri.org/。WCF将使用服务类型的名称作为作为服务名称。

   1: [ServiceBehavior(Name = "CaclService", 
   2:           Namespace ="http://www.artech.com")]
   3: public class CalculatorService : ICalculator
   4: {
   5:   //省略成员
   6: }

对于上面定义的服务类型来说,由于我们通过ServiceBehaviorAttribute特性对名称和命名空间进行了显式设置。用于描述服务的WSDL将具有如下一个根节点。

   1: <wsdl:definitions  name="CaclService" 
   2:                    targetNamespace="http://www.artech.com"
   3:                    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" ...>
   4: </wsdl:definitions>

三、Binding的名称和命名空间

既然已经将到了服务契约和服务的名称和命名空间,我们顺便来谈谈另一组命名和命名空间。其实作为终结点三要素之一的绑定也具有自己的名称和命名空间。如下面的代码所示,作为绑定基类的抽象类Binding同样具有一组Name和Namespace属性。

   1: public abstract class Binding
   2: {
   3:     //省略成员
   4:     public string Name { get; set; }
   5:     public string Namespace { get; set; }
   6: }

Binding的名称和命名空间通过服务终结点的bindingName和bindingNamespace属性进行设置。由于这两个属性属于服务描述范畴,所以客户端终结点无此设置。由于绑定在WSDL中对应的节点为<binding>,所以绑定的Name和Namespace属性值将作为对应的<binding>节点的名称和命名空间。在默认的情况下,<binding>元素的命名空间的值依然是http://tempuri.org/。至于名称,则通过绑定类型名称和契约名称合并而成。比如说契约名称为ICalculator,并采用BasicHttpBinding,那么对应的<binding>元数的名称为BasicHttpBinding_ICalculator。

   1: <configuration>
   2:   <system.serviceModel>    
   3:     <services>
   4:       <service ...>
   5:         <endpoint bindingName="myBasicHttpBinding"
   6:                   bindingNamespace="http://www.artech.com" .../>
   7:       </service>
   8:     </services>
   9:   </system.serviceModel>
  10: </configuration>

比如说在服务寄宿时采用如上的配置将终结点的绑定名称和命名空间进行了显式设置,并且采用如上的服务契约(名称被定义成CalcService)。该终结点绑定在WSDL中将对应于如下一个<binding>元素。

   1: <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   2:                   xmlns:tns = "http://www.artech.com/">
   3:   <wsdl:binding name="tns: myBasicHttpBinding_CalcService" ...>    
   4:   </wsdl:binding>
   5: </wsdl:definitions>

总结

要区分上述三个名称/命名空间其实不然,只要我们知道终结点三要素在WSDL具体对应什么。

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

缓冲区溢出攻击初学者手册(更新版)

说明 之前版本翻译质量不佳,本人赵阳在这里对本文的读者表示深深的歉意。由于本人的疏忽和大意导致您不能很好的读完这篇文章,同时也对原文内容进行了破坏,也对IDF和...

2809
来自专栏王金龙的专栏

分布式系统ID生成方案汇总

本文只整理MySQL的自增字段方案,Oracle和SQL Server的自增长方案就不介绍了。

2242
来自专栏前端达人

JavaScript基础——回调(callback)是什么

上篇文章《JavaScript基础——你真的了解JavaScript吗?》,我们明白了JavaScript是一个单线程、非阻塞、异步、解释性语言,清楚了什么是单...

2087
来自专栏鹅厂少年的奇妙之旅

Go内存模型

Go语言中内存分配大致有3种模式:Stack、Heap、Fixed Size Segment。

6805
来自专栏安恒网络空间安全讲武堂

从零基础到成功解题之0ctf-ezdoor

2144
来自专栏编程

JAVA面试常考系列八

题目一 JDBC是什么? JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为...

36511
来自专栏大内老A

WCF技术剖析之十七:消息(Message)详解(上篇)

消息交换是WCF进行通信的唯一手段,通过方法调用(Method Call)形式体现的服务访问需要转化成具体的消息,并通过相应的编码(Encoding)才能通过传...

4389
来自专栏编程

看我是如何把SQLMap里的功能移植到我的程序的

不知道各位有没有听过不要重复造轮子?因为有些开源的工具,它们经过时间和众人的捶打,其实会比我们自己一个人造出来的轮子考虑的更加周到和全面。可是有时候有些开源工具...

20510
来自专栏大内老A

ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则

对于Model验证,理想的设计应该是场景驱动的,而不是Model(类型)驱动的,也就是对于同一个Model对象,在不同的使用场景中可能具有不同的验证规则。举个简...

18010
来自专栏运维一切

ceph对象存储折腾记 原

###前言 一直想弄对象存储,以前弄过一次,不是很理解region是个什么东西,后来时间和工作上的原因没有再折腾,这两天闲了下来,再次折腾了一次。我是参考的ce...

1591

扫码关注云+社区

领取腾讯云代金券