契约服务说白了就是对WCF服务的对外接口作定义和声明。下面是一些关键字,只有加了关键字的方法才能被服务调用者访问。
ServiceContract]:定义服务操作,对于某个Interface加上这个属性标签就会就定义了一个服务,客户端才可以看到这个服务。这个属性标签可以应用于接口或者类,建议应用于接口,第一,可以消除服务实现的耦合性,因为接口中不存在任何的业务逻辑相关的东西,第二,服务可能会实现多于一个契约,也就是说一个类同时实现多个服务,如果把标签定义在类上,就无法同时实现多个服务了。
两个属性:
Name:指定暴露给客户端的服务名称。
Namespace:提供有意义的命名空间。
[OperationContract]:使得方法作为公共服务契约的一部分暴露出来,也就说说客户端可以看到服务中暴露出来的方法。服务契约中的所有方法都应该拥有这个属性标签。
一些属性:
Namespace:提供有意义的命名空间。
Name:指定暴露给客户端的方法名称。
Action:Web调用地址,获取或设置请求消息的 WS-Addressing 操作,定义具体的动作,他表示的是一个层次上的关系,下面的代码中可以看出,Action=namespace+servername+methodname。当客户端导入一个服务终结点的元数据时,如果该终结点的契约属于接口层级的一部分,则生成的客户端契约将不再维持原来的层级关系。相反,它会取消层级,组成一个单独的契约,名称为终结点的契约名。这个单独的契约包含了层级中从上至下所有接口定义的操作。然而,如果使用OperationContract特性中的Action与ResponseAction属性,那么导入的接口定义仍然可以保留原来定义每个操作的契约名,比如:服务接口之间如果有继承关系的存在,那么他就可以派上用场了。
ReplyAction:调用后回传的地址,获取或设置用于该操作答复消息的 SOAP 操作的值,定义具体的相应动作。它主要完成的是SOAP数据到具体代码的映射关系。
对于这后两个属性是不是不太理解,没关系后面的sample会给你答案, 继续读完吧,坚持就是胜利!!!
[MessageParameter]:用来控制参数或者返回名称,下面的一段代码可以很好的帮我们理解他的作用,很简单,其实就是映射作用。具体如下:有一个Java的客户端,发送一个SOAP给WCF服务,WCF会检查SOAP中有没有的对应定义的MessageParameter Name,如果有就会对应到WCF函数中的相应位置,通过这种映射关系,然后通过反序列化把数据传到WCF的对应方法中,实现对象的传递。说简单点他就是用来控制在soap中参数节点的名称的。
概念SOAP:Simple Object Access Protocol,简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议( HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。
WCF服务和Client之间其实就是用的SOAP这种协议。下面的代码展示了这些关键字的使用方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF.Demo
{
public class HelloWorldService : IService
{
public string HelloWorld(string message)
{
return string.Format("At {0}, I will say {1}", DateTime.Now, message);
}
public void SaveLink(string item)
{
}
public string GetLink(string id)
{
return "Thanks!";
}
}
[ServiceContract(Name = "ContentManagerContract", Namespace = "http://www.cnblogs.com/CharlesLiu")]
public interface IService
{
[OperationContract(Name = "SaveLinkString", Action = "http://www.cnblogs.com/CharlesLiu/ContentManagerContract/SaveLink",ReplyAction="http://www.cnblogs.com/CharlesLiu/ContentManagerContract/ResponseSaveLink")]
void SaveLink([MessageParameter(Name = "StringItem")]string item);
[OperationContract]
[return: MessageParameter(Name = "StringItem")]
string GetLink(string id);
[OperationContract]
string HelloWorld(string message);
}
}
下面的例子主要介绍Action属性,创建WCF程序项目,更加方便,不用编写host部分了,F5会自动把Service给host起来,如下图:
![WCF开发之服务契约](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
![WCF开发之服务契约](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
![WCF开发之服务契约](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
![WCF开发之服务契约](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
Demo1.IService代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
namespace
WcfServiceLibraryDemo
{
//
NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in App.config.
[ServiceContract(Name
=
"
ServiceAContract
"
, Namespace
=
"
http://www.cnblogs.com/Charlesliu
"
)]
public
interface
IServiceA
{
[OperationContract(Name
=
"
Name_Operation1
"
, Action
=
"
http://www.cnblogs.com/Charlesliu/ServiceAContract/Operation1
"
, ReplyAction
=
"
http://www.cnblogs.com/Charlesliu/ServiceAContract/Operation1Response
"
)]
string
Operation1();
[OperationContract(Name
=
"
Name_Operation2
"
, Action
=
"
http://www.cnblogs.com/Charlesliu/ServiceAContract/Operation2
"
, ReplyAction
=
"
http://www.cnblogs.com/Charlesliu/ServiceAContract/Operation2Response
"
)]
string
Operation2();
}
}
Demo1.Service.Class代码
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Runtime.Serialization;
using
System.ServiceModel;
using
System.Text;
namespace
WcfServiceLibraryDemo
{
public
class
ServiceA : IServiceA
{
public
string
Operation1()
{
return
"
IServiceA.Operation1() invoked.
"
;
}
public
string
Operation2()
{
return
"
IServiceA.Operation2() invoked.
"
;
}
}
}
Demo1.WinClient代码
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
namespace
WinTest
{
public
partial
class
Form1 : Form
{
public
Form1()
{
InitializeComponent();
}
private
void
button1_Click(
object
sender, EventArgs e)
{
MyServiceReference.ServiceAContractClient so1
=
new
WinTest.MyServiceReference.ServiceAContractClient();
MessageBox.Show(so1.Name_Operation1());
}
private
void
button2_Click(
object
sender, EventArgs e)
{
MyServiceReference.ServiceAContractClient so1
=
new
WinTest.MyServiceReference.ServiceAContractClient();
MessageBox.Show(so1.Name_Operation2());
}
}
}