Silverlight中WCF的百分百完美简单实现!

在我刚开始接触Silverlight的时候,要建一个网站是多么容易的事情。但是如果用到了WCF,经常会出现跨域错误,而且Silverlight-enabled WCF也不好用,因为发布不方便,头痛无比。网上的攻略很多,但是大都都是只能针对他们自己的机器能用,或者断断续续的讲一些原理,看了还是不是很懂。

这里我贴出代码,让你直接复制粘贴代码就能使,保证能用。

我的构建方法很简单:WCF就是一个C#的Console Window Application,简而言之:“控制台程序”,注意我用的是.Net Framework 3.5,别的版本不知道能不能使,尤其是中间有个WebGet属性,需要调用System.ServiceModel.Web,有些System.ServiceModel.Web可能没有WebGet,所以这个保证能用啦!

第一步:新建一个控制台程序,拷贝下面一段代码复制到你的Program.cs,覆盖原来的,改一下那个namespace和类名成为你自己需要的,添加一些没有添加的引用,注释里面写的很清楚(亲测可用)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
using System.Net;
using System.ServiceModel.Description;

namespace Test
{
//using System.ServiceModel;
[ServiceContract]
public interface IPolicyRetriever
{
//WebGet: using System.ServiceModel.Web;
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream GetSilverlightPolicy();
[OperationContract, WebGet(UriTemplate = "/crossdomain.xml")]
Stream GetFlashPolicy();
}

//using System.Runtime.Serialization;
[DataContract]
public class People
{
[DataMember]
public string Name { get; set; }

[DataMember]
public int Age { get; set; }
}

[DataContract]
public enum Sex
{
[EnumMember]
Male,

[EnumMember]
Female
}

[ServiceContract]
public interface IPeople
{
[OperationContract]
List<People> GetAllPeople();
}

public class PeopleService : IPolicyRetriever, IPeople
{
public List<People> GetAllPeople()
{
//Add your own code
return null;
}

public Stream GetSilverlightPolicy()
{
string result = @"<?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>
";
return StringToStream(result);
}
public Stream GetFlashPolicy()
{
string result = @"<?xml version=""1.0""?>
<!DOCTYPE cross-domain-policy SYSTEM ""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"">
<cross-domain-policy>
<allow-access-from domain=""*"" />
</cross-domain-policy>
";
return StringToStream(result);
}
Stream StringToStream(string result)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
}


class Program
{
static void Main(string[] args)
{


// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
//using System.Net;
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
string ipAddr = localIPs[3].ToString();
Console.WriteLine(ipAddr);
Uri baseAddress = new Uri("http://" + ipAddr + ":8681");

// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(PeopleService), baseAddress);

try
{
// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(
typeof(IPeople),
new BasicHttpBinding(),
"PeopleService");

selfHost.AddServiceEndpoint(
typeof(IPolicyRetriever),
new WebHttpBinding(),
"").Behaviors.Add(new WebHttpBehavior()); //using System.ServiceModel.Description;

// Step 4 of the hosting procedure: Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);

// Step 5 of the hosting procedure: Start (and then stop) the service.
selfHost.Open();
Console.WriteLine("Service:" + baseAddress.AbsoluteUri);
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();

// Close the ServiceHostBase to shutdown the service.
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
}


第二步:在工程的根目录里建立两个文件:

clientaccesspolicy.xml

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="SOAPAction">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

 

crossdomain.xml

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

 

如图:

image_thumb[15]

然后再把这两个文件添加到Visual Studio的Solution Explorer的相应工程的引用中去,如图:

image_thumb[16]

这里的工程名字是我的另外一个工程的名字,与本文无关,希望不会影响你的理解。

反正就是把文件拖到这里面就行了,或者右键单击工程,选择add->exist items,然后选这两个添进来就行了

第三步:重新Build工程,找到工程的bin/debug文件夹,里面的exe打开,如图:

image_thumb[17]

这个时候WCF就建好了,建在显示的那个地址上的,包含了两个Service,一个是你自定义的Service,一个是跨域的Service

拷贝一下那个http://XXX.XX.XXX.XXX:8681

然后右键单击你的Silverlight工程,添加Service Reference, 如图:

image_thumb[19]

就看到啦,就可以在Silverlight里用啦。

第四步:发布网站

当你的网站建好了之后,你想发布,你想让别人也看到这个网站,就这么做:

先安装好IIS,我图中的显示的是IIS6.0还是7.0忘记了,版本低的盆友自己赶紧升级哦。

image_thumb[21]

然后在IIS中新建一个网站,注意程序池一定要选.net 4.0哦,端口号自己随便设一个,比如8624

image_thumb[22]

物理路径就是建Silverlight时自带的.Web工程

然后图中的默认文档(Default Document)添加.Web工程中的那个主页,名字复制好点添加就行了

image_thumb[9]

image_thumb[11]

这个时候你就可以直接通过右击网站,选择Manage Web Site->Browse进行浏览了,你会发现网址中是一个很纯粹的localhost:8624的形式,没有什么多余的文件名。

image_thumb[14]

如果想通过外部访问这个网站,只需要把localhost改成你的主机名就行了,主机名的查询方法就是右击“我的电脑”,选择属性,就有主机名显示了。当然,如果你用了路由器就比较麻烦,要做端口映射,自己查别的文献去吧,这个不在本文的讨论范围之内了。

综上所述,这个方法不受电脑的限制,也就是说两台联网的机器上,一台建WCF,一台建Silverlight工程也行,反正就是很简答,百试不爽!

如果讲的这么清楚你还搞不好,发邮件给我 ustcwhc@gmail.com

Good luck!

posted @ 2011-10-30 21:51  伍浩铖  阅读(3079)  评论(0编辑  收藏  举报