我是学自考出身的,一般喜欢先看下实例效果。所以我就根据我对WCF的概念性的理解,创建了我的第一个WCF程序。
第一:当然是要建立WCF服务程序了。
。
程序创建后发现生成了三个文件:App.config,IService1.cs,Service1.cs
App.config代码如下:
Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- 部署服务库项目时,必须将配置文件的内容添加到
主机的 app.config 文件中。System.Configuration 不支持库的配置文件。-->
<system.serviceModel>
<services>
<service name="WcfServiceLibrary1.Service1" behaviorConfiguration="WcfServiceLibrary1.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- 除非完全限定,否则地址将与上面提供的基址相关 -->
<endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary1.IService1">
<!--
部署时,应删除或替换下列标识元素,以反映
在其下运行部署服务的标识。删除之后,WCF 将
自动推导相应标识。
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- 元数据交换终结点由服务用于向客户端做自我描述。-->
<!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfServiceLibrary1.Service1Behavior">
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 要接收故障异常详细信息以进行调试,
请将下值设置为 true。在部署前
设置为 false 以避免泄漏异常信息-->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- 部署服务库项目时,必须将配置文件的内容添加到
主机的 app.config 文件中。System.Configuration 不支持库的配置文件。-->
<system.serviceModel>
<services>
<service name="WcfServiceLibrary1.Service1" behaviorConfiguration="WcfServiceLibrary1.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- 除非完全限定,否则地址将与上面提供的基址相关 -->
<endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary1.IService1">
<!--
部署时,应删除或替换下列标识元素,以反映
在其下运行部署服务的标识。删除之后,WCF 将
自动推导相应标识。
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- 元数据交换终结点由服务用于向客户端做自我描述。-->
<!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfServiceLibrary1.Service1Behavior">
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
<serviceMetadata httpGetEnabled="True"/>
<!-- 要接收故障异常详细信息以进行调试,
请将下值设置为 true。在部署前
设置为 false 以避免泄漏异常信息-->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
这是个配置文件,类似于asp.net程序中的web.config。
IService1.cs :
我删除了点其它的方法,保留了一个方法.
Code
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
这里定义了一个接口,和普通程序中的接口是一样的,唯一不同的是在接口上面有一个特性[ServiceContract],这是契约中的一种:服务契约。有了这个标记,它就可能面向客户端了。在下面申明的方法中和普通方法也有点不同,同样是多了一个标记[OperationContract],这个标记将方法向客户端公开。
Service1.cs :它继承了上面的接口.
Code
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
第二:有了服务端当然少不了客户端了。这我就用ASP.NET来充当了。
客户端要想应用服务端程序,一定要添加服务引用了,这里我的服务端与客户端在一个项目里面就可以直接添加服务引用了。
由于我的服务端是本地的,所在点击“发现”,程序就会发现项目中我上面创建的WCF程序。点确定就成功的添加了服务端的引用了。
第三:写客户端的调用程序。
页面代码:
Code
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
后台代码:
Code
private void transferWCF()
{
ServiceReference1 .Service1Client prox=new WebApplication1.ServiceReference1.Service1Client ();
int i = 0;
int.TryParse(this.TextBox1.Text.Trim(), out i);
string s = prox.GetData(i);
Response.Write(s);
}
protected void Button1_Click(object sender, EventArgs e)
{
this.transferWCF();
}
private void transferWCF()
{
ServiceReference1 .Service1Client prox=new WebApplication1.ServiceReference1.Service1Client ();
int i = 0;
int.TryParse(this.TextBox1.Text.Trim(), out i);
string s = prox.GetData(i);
Response.Write(s);
}
protected void Button1_Click(object sender, EventArgs e)
{
this.transferWCF();
}
上面的就是我的第一个基于HELLO WORLD 的程序了。
客户端调用时要先创建代理类
ServiceReference1 .Service1Client prox=new WebApplication1.ServiceReference1.Service1Client ();
通过这个代理类就可以调用服务端的方法了。由于只在接口是对外公开的,所有只能调用到接口的方法,你并不能直接调用Service1.cs的方法。这样和我们现在一直提倡的“面向接口编程”非常相似。
我在应用这个程序的时候,证明了WCF默认情况下是不运行操作符重载的。在C#中的利用重载是相当普遍的做法,但在WCF程序中如果你不做具体设置它会出现异常(InvalidOperationException)。
下面是错误的代码,并不能编译成功。
Code
[OperationContract
string GetData(int value);
[OperationContract
string GetData(string value);
[OperationContract
string GetData(int value);
[OperationContract
string GetData(string value);
WCF并不是不支持这种操作重载,而要手动指定。这里要用到OperationContract特性的Name属性。下面是正确的代码.
Code
[OperationContract(Name="int")]
string GetData(int value);
[OperationContract(Name="string")]
string GetData(string value);
[OperationContract(Name="int")]
string GetData(int value);
[OperationContract(Name="string")]
string GetData(string value);
这样在生成代理的时候,程序就会自动在GetData后面加上相应的标记来区分了,这样就达到了操作重载的效果了。