WCF入门(二)——终结点,契约(2)

简介: Contract 契约,用于提供消息的标准,消息交换的规则。它分四类: ·服务契约 定义操作 ·数据契约 定义数据 ·异常契约 定义异常 ·消息契约 定义消息格式 (一)服务契约 服务契约,可以用接口定义,也可以直接在类上定义。

Contract

契约,用于提供消息的标准,消息交换的规则。它分四类:

·服务契约 定义操作

·数据契约 定义数据

·异常契约 定义异常

·消息契约 定义消息格式

(一)服务契约

服务契约,可以用接口定义,也可以直接在类上定义。

例如:

[ServiceContract]

public interface ICaculateService

它有很多可选属性,例如:

NameNamespaceCallbackContractSessionMode等等。这里来从包中来演示一下:

契约:

[ServiceContract]

public interface ICaculateService

{

[OperationContract]

int Devide(int a, int b);

}

上边的契约没有显示使用其它的属性

现在的包的情况:

<a:Action s:mustUnderstand="1"

u:Id="_2">http://tempuri.org/ICaculateService/DevideResponse

</a:Action>

在应用namespace之后:

 

[ServiceContract(Namespace="http://www.selftest.com/test1")]

public interface ICaculateService

情况为:

<a:Action s:mustUnderstand="1" u:Id="_2">

http://www.selftest.com/test1/ICaculateService/DevideResponse

</a:Action>

 

这个namespace的定义为:获取或设置 Web 服务描述语言 (WSDL) 中的 <portType> 元素的命名空间,它默认的为 http://tempuri.org

 

OperationContractAttribute用于标注向远程调用公开的方法功能。只要公开了,即使访问性为私有,也可以被远程调用。

(接口中定义默认公开的,也无法添加访问修饰符),这个标签也有很多可选属性,而且这些属性非常重要。例如:

ActionIsInitiatingIsOneWayIsTerminatingName

例如Action

引用:

使用 Action 属性控制方法的输入消息的操作。由于 WCF 使用该操作将传入消息调度至相应方法,因此在协定操作中使用的消息必须具有唯一的操作。默认操作值由以下几项组成:协定命名空间(默认值为“http://tempuri.org/”)、协定名称(如果没有使用显式服务接口,则为接口名称或类名)、操作名称,并且如果该消息是一个相关的响应,则还有一个附加字符串(“Response”)。您可以使用 Action 属性重写该默认值:

<a:Action s:mustUnderstand="1"

u:Id="_2">http://tempuri.org/ICaculateService/DevideResponse

</a:Action>

(二)数据契约

DataContract

对于系统的简单类型,已经有默认的规则(所有 .NET Framework 基元类型(如整型和字符串型)以及某些被视为基元的类型(如 DateTime XmlElement)无需做其他任何准备工作就可序列化并被视为拥有默认数据协定)。而对于复杂类型来说,如类对象,如果不进行处理,是不可以传输的。而如果要让复杂类型传输或存储,则要对其进行序列化。(若要使其类型可序列化,类型作者必须为其类型定义数据协定。)

 

DataContract属性可用于类,结构,枚举,然后其中的所有成员都必须添加DataMember标签,来指示这些成员做为数据成员,而可以被序列化和反序列化

可以被序列化的类型包括:

·数据契约类型,就是添加DataContract标签的类型

·集合,数组与集合

·枚举,可以对枚举类型添加DataContract标签,然后,必须对枚举成员添加EnumMember标签,例如:

[DataContract]

public enum eErrorType

{

[EnumMember]

No1,

[EnumMember]

No2,

[EnumMember]

No3,

[EnumMember]

No4

}

·.NET Framework 基元类型 包括,字符,字串,字节,数值类型,object,时间,时间戳,guidUri

·Serializable修饰的类型

·原始的xmlado.net关系数据的类型

(三)异常契约

用于在服务操作在遇到处理错误时,返回的soap错误。这个通过FaultContractAttribute标签来实现。

WCF服务在两种错误系统下工作(一是托管的应用程序中的Exception异常,另一种是soap异常),所以,发送到客户端的异常要由托管的异常信息转化为Soap异常信息。

这里说一下FaultException<T> 泛型类,其中T表示可序列化错误详细信息类型。

例如:

·契约

[FaultContract(typeof(eErrorType))]

int Devide(int a, int b);

·服务

public int Devide(int a, int b)

{

    switch (b)

    {

case 0:

         throw new FaultException<eErrorType>(eErrorType.No1);

case 1:

         throw new FaultException<eErrorType>(eErrorType.No2);

    }

    return a /b;

}

其中eErrorType前文已经给出

 

客户端:

int result = client.Devide(10, 0);

 

catch (FaultException<FirstInstance.eErrorType> ex)

{

    Console.WriteLine(ex.Detail.ToString());

}

异常信息:No1

(四)消息契约

WCF的核心是消息交换。例如WSHttpBinding绑定,编码格式为文本的时候,那么消息就是一个完整的Soap,就是一个封套;如果是MTOM时,那就是另一种格式了。

为了验证消息的格式,现在在绑定中把安全选项加上,使用不加密:

<wsHttpBinding>

<binding name="BindingSelf"

messageEncoding="Text" textEncoding="utf-8">

<security mode="None"></security>

</binding>

</wsHttpBinding>

 

然后,看一看消息格式是怎么样的:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"

xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

     <a:Action s:mustUnderstand="1">

http://www.selftest.com/test1/

ICaculateService/GetCustomerByIdResponse

</a:Action>

<a:RelatesTo>

urn:uuid:944ad5e1-7c2a-4617-a7a1-64bdc5b25d47

</a:RelatesTo>

</s:Header>

<s:Body>

<GetCustomerByIdResponse

xmlns="http://www.selftest.com/test1">

<GetCustomerByIdResult

xmlns:b=" http://schemas.datacontract.org

/2004/07/FirstService "

xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

     <b:Address>Shandong</b:Address>

     <b:CustomerName>Songjiang</b:CustomerName>

<b:Unid>1</b:Unid>

</GetCustomerByIdResult>

</GetCustomerByIdResponse>

</s:Body>

</s:Envelope>

 

在服务端是这样契约的:

[DataContract]

public class Customer

{

[DataMember]

public int Unid { get; set; }

 

[DataMember]

public string CustomerName { get; set; }

 

[DataMember]

public string Address { get; set; }

}

 

方法GetCustomerById返回了一个Customer对象:

<b:Address>Shandong</b:Address>

     <b:CustomerName>Songjiang</b:CustomerName>

<b:Unid>1</b:Unid>

这些就是它的属性及值。

 

现在通过消息契约,来设置一下消息的格式。

[MessageContract]

public class Customer

{

[MessageHeader(Name="selfHeader001")]

public int Unid { get; set; }

 

[MessageHeader(Name = "selfHeader002")]

public string CustomerName { get; set; }

 

[MessageBodyMember(Name="selfBody001")]

public string Address { get; set; }

}

 

 

<s:Envelope

xmlns:s="http://www.w3.org/2003/05/soap-envelope"

xmlns:a="http://www.w3.org/2005/08/addressing">

<s:Header>

     <a:Action s:mustUnderstand="1">

http://www.selftest.com/test1/ICaculateService

/GetCustomerByIdResponse

</a:Action>

     <h:selfHeader001

xmlns:h="http://www.selftest.com/test1">

1

</h:selfHeader001>

     <h:selfHeader002

xmlns:h="http://www.selftest.com/test1">

Songjiang

</h:selfHeader002>  

<a:RelatesTo>

urn:uuid:6ea8a734-d01f-4cf4-85ce-5fae03e538d9

</a:RelatesTo>

  </s:Header>

<s:Body>

<Customer xmlns="http://www.selftest.com/test1">

     <selfBody001>Shandong</selfBody001>

  </Customer>

  </s:Body>

  </s:Envelope>

 

可以看出这种消息契约非常灵活。现在来为customer消息添加一个文本文件。

[MessageBodyMember(Name="text001")]

public Byte[] TextFile { get; set; }

 

包中的结果

<text001>MTIzNCBxd2VydA==</text001>

 

博客园大道至简

http://www.cnblogs.com/jams742003/

转载请注明:博客园

目录
相关文章
WCF基础教程(四)——数据契约实现传送自定义数据类型
WCF基础教程(四)——数据契约实现传送自定义数据类型
119 0
|
Web App开发 C#
WCF-找不到终结点
开发环境:Vs2010SP1 Rel 问题:开发WCF服务端新建Wcf服务的过程中,正常的新建了svc服务,在浏览器中打开总是提示找不到终结点 解决:添加svc文件时,应该选择WCF服务,而不是WCF数据服务, 如果你选择WCF数据服务,生成的svc头命令是 在浏览器中浏览这...
958 0