WCF学习笔记(2)——独立WCF服务
本文将建立一个silverlight与wcf通讯的简单实例,wcf服务将被独立出来,而不再寄放在Web中。以下是详细步骤:
新建Silverlight应用程序,名称WCFtest,在解决方案上右键添加wcf服务应用程序,名称WcfServiceTest,WCF服务将不再寄宿在Web中。
WcfServiceTest创建完毕,将VS自动添加的IService1.cs和Service1.svc文件删除。
修改WcfServiceTest服务,固定端口12345。
添加一个wcf服务,名称ServiceTest,VS自动生成IServiceTest.cs和ServiceTest.svc文件。
打开IServiceTest.cs,新建一个实体类MyName,包含FirstName和LastName两个属性,[DataContract]标识实体类契约,[DataMember]标识属性,实体类MyName用以返回。
[ServiceContract]//接口标识,服务契约
public interface IServiceTest
{
[OperationContract]
void DoWork();
[OperationContract]//方法名标识
MyName GetName(string fullName);
}
[DataContract]//实体类契约
public class MyName
{
[DataMember]//属性
public string FirstName
{
get;
set;
}
[DataMember]
public string LastName
{
get;
set;
}
}
实现接口方法,传入参数fullName,将fullName拆解成FirstName和LastName赋值给新建MyName实体类的属性,返回MyName类型的结果。
public class ServiceTest : IServiceTest
{
public void DoWork()
{
}
#region IServiceTest 成员
public MyName GetName(string fullName)
{
MyName name = new MyName();
string[] names = fullName.Split(' ');
name.FirstName = names[0];
name.LastName = fullName.Substring(names[0].Length - 1);
return name;
}
#endregion
}
重新生成解决方案,否则可能会出现发现WCF服务有误的情况,在Silverlight项目中添加服务引用,点击发现可以查找到刚刚添加的svc服务。修改服务命名空间ServiceReferenceTest。
在Silverlight项目的MainPage.xaml上,为了便于演示,添加一个TextBox,一个Button,一个TextBlock。
<Grid x:Name="LayoutRoot" Background="White">
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="12,41,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="12,70,0,0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Width="120" />
</Grid>
添加button1点击Click事件。
private void button1_Click(object sender, RoutedEventArgs e)
{
Binding binding = new BasicHttpBinding();
EndpointAddress endPoint = new EndpointAddress("http://localhost:12345/ServiceTest.svc");
ServiceReferenceTest.ServiceTestClient client = new ServiceReferenceTest.ServiceTestClient(binding, endPoint);
client.GetNameCompleted += new EventHandler<ServiceReferenceTest.GetNameCompletedEventArgs>(client_GetNameCompleted);
client.GetNameAsync(this.textBox1.Text);
}
Binding binding =new BasicHttpBinding();绑定通讯方式,这里是BasicHttp方式;
EndpointAddress endPoint = new EndpointAddress("http://localhost:12345/ServiceTest.svc");指定svc服务路径;
定义调用GetName方法完成后的回调事件,客户端接收MyName类型的返回结果e.Result,将FirstName属性显示在textBlock1上;
void client_GetNameCompleted(object sender, ServiceReferenceTest.GetNameCompletedEventArgs e)
{
ServiceReferenceTest.MyName name = e.Result;
try
{
this.textBlock1.Text = string.Format("FirstName:{0}", name.FirstName);
}
catch
{
this.textBlock1.Text = "返回null!";
}
}
异步调用GetName方法,将textBox1的text内容作为参数调用服务端的GetName方法。
你可能会遇到跨域问题,解决方法是,在wcf服务应用程序中添加配置文件clientaccesspolicy.xml。
clientaccesspolicy.xml文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
F5运行,在TextBox1中输入全名fullName,点击button1,调用服务端的GetName方法参数fullName,GetName方法返回一个MyName类型的结果,客户端将结果中的FirstName属性显示在TextBlock1中。