WCF 服务, 该服务将内容推送到 Silverlight 应用程序 [推送通知]






3.40/5 (7投票s)
本文描述了一个WCF服务,该服务可以将内容推送到Silverlight应用程序。
引言
“推送通知”这个词已经存在很久了。几乎所有制造的智能手机都有启用推送通知的选项。“PUSH”与“PULL”相反。这意味着服务器不是从服务器拉取内容或向服务器请求内容,而是只要有更新可用,服务器就会推送内容或发送响应。在手机上,这项技术非常省电。在Web技术中,它大大节省了服务器请求流量。互联网上有大量关于实现此技术的文章,但我发现MSDN是最好的。因此,我继续努力,让MSDN教程对初学者来说更容易。请记住,这是一篇初学者文章,但实现真实应用程序的想法围绕着这个。你可以尽力重新编码。
在这里,我们将看到一个Silverlight应用程序请求雅虎!的股票价格。服务器将开始推送最新的股票价格。股票价格是随机数字。该应用程序基于一些假设。
背景
作为新手,您必须了解WCF、基本Silverlight以及推送通知等术语。请参考维基百科了解定义。
使用代码
我使用.NET Framework 4.0来开发示例。如果您使用的是早期版本,则可能需要更改一些代码。
- 转到新项目并创建一个WCF服务应用程序。首先要添加的是对Polling Duplex DLL的引用。您需要在“添加引用”窗口中浏览到%Program Files%\Microsoft SDKs\Silverlight\v3.0\Libraries\Server\System.ServiceModel.PollingDuplex.dll。请仔细看,我们正在从libraries\server文件夹引用轮询双工DLL。
- 右键单击项目并添加一个新项“接口”。您可以将其命名为IService1.cs。
- 您必须在标题区域包含这些:
using System.ServiceModel;
和using System.ServiceModel.Web;
。 - 复制并粘贴以下代码。基本上,我们在该接口中定义了两个接口。
IsOneWay=true
是一种消息传递模式,意思是“调用并忘记”,与“请求-响应”相反。 - 转到service1.svc.cs。如果不存在,请在标题中包含这些:
using System.ServiceModel;
和using System.ServiceModel.Web;
。您还必须包含:using System.Threading;
。 - 将以下代码复制并粘贴到您的service1.svc.cs中。
RequestPrice(string stocksyb)
方法将从Silverlight调用,并带有stockname
参数。此时,列表中有三只股票将被搜索并返回一个随机价格。搜索是通过LINQ完成的,因此您需要将System.Linq
作为引用。PushData
由timercallback
委托每秒调用一次。client.PushPrices(_i);
是将在客户端推送内容的方法。 - 下一步是创建一个类文件。因此,添加一个新类并将其命名为PollingDuplexServiceHostFactory.cs。添加以下内容
- 转到您的Service.svc文件的标记代码。右键单击文件->查看标记。用以下代码替换它
- 构建服务并查看它是否正确显示。如果您正在使用开发服务器,请确保在完成客户端应用程序之前,动态端口保持不变。就是这样;WCF端编码已完成。现在让我们创建客户端应用程序。
- 我们将使用Silverlight开发客户端应用程序。您必须已安装SDL。向同一解决方案添加新项目。选择Silverlight应用程序。
- 第一步是为客户端添加轮询双工DLL的引用。添加引用并从中浏览%Program Files%Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.ServiceModel.PollingDuplex.dll。
- 现在您需要添加服务引用。右键单击服务引用->添加服务引用。单击“发现”。您应该看到Service.svc。将命名空间输入为StockService,然后按OK。
- 转到您的默认XAML页面“MainPage.xaml”。添加两个
TextBlock
。将它们命名为“info
”和“reply
”。 - 在您的MainPage.xaml.cs的标题中添加引用:
using System.ServiceModel;
,using System.ServiceModel.Channels;
,using SilverlightApplication2.StockService;
。 - 复制并粘贴以下代码
EndpointAddress
应包含您的服务的URI。在开发服务器上工作时,不要忘记检查当前端口。- 代理对象是我们服务引用命名空间“
StockService
”的对象。 - 事件处理程序将处理来自服务的值。该处理程序处理
proxy_PushPricesReceived
方法。 e
对象是从服务返回的(_i
)值。- 生成项目并导航到Silverlight应用程序文件夹\SilverlightApplication2\Bin\Debug。复制SilverlightApplication2.xap文件并将其粘贴到您的WcfService1\ClientBin文件夹中。您需要创建ClientBin文件夹。每次在.xaml和xaml.cs文件中进行更改时,都需要执行此操作。
- 在WCF项目中,添加一个新HTML文件。将以下代码复制并粘贴到body标签中
- 生成所有内容。将HTML页面设置为启动文件并运行项目。该应用程序将请求雅虎的价格,服务器将每秒推送一次内容。
- 使用Fiddler查看服务器的响应。
namespace DuplexService
{
[ServiceContract(Namespace="Silverlight",
CallbackContract = typeof(IDuplexClient))]
public interface IDuplexService
{
[OperationContract(IsOneWay = true)]
void RequestPrice(string stocksyb);
}
[ServiceContract]
public interface IDuplexClient
{
[OperationContract(IsOneWay = true)]
void PushPrices(string p);
}
}
namespace DuplexService
{
public class StockService: IDuplexService
{
IDuplexClient client;
Random num = new Random();
public void RequestPrice(string stocksyb)
{
// Grab client callback channel.
client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
List<string> stocklist = new List<string>();
stocklist.Add("Yahoo");
stocklist.Add("Microsoft");
stocklist.Add("Google");
var query = from s in stocklist where s == stocksyb select s;
var result = query.SingleOrDefault();
if (result != null)
{
//Pretend service is pulling latest stock prices.
using (Timer timer =
new Timer(new TimerCallback(PushData), stocksyb, 1000, 1000))
{
Thread.Sleep(System.Threading.Timeout.Infinite);
}
}
else
{
client.PushPrices("Invalid Stock Request");
}
}
private void PushData(object o)
{
//Random stock prices between 200 and 205.
//This is where you can bring in your content from a datasource
string _i = num.Next(201,205).ToString();
// Send price to client
client.PushPrices(_i);
}
}
}
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using DuplexService;
namespace DuplexService
{
public class PollingDuplexServiceHostFactory : ServiceHostFactoryBase
{
public override ServiceHostBase CreateServiceHost(string constructorString,
Uri[] baseAddresses)
{
return new PollingDuplexSimplexServiceHost(baseAddresses);
}
}
class PollingDuplexSimplexServiceHost : ServiceHost
{
public PollingDuplexSimplexServiceHost(params System.Uri[] addresses)
{
base.InitializeDescription(typeof(StockService),
new UriSchemeKeyedCollection(addresses));
// base.Description.Behaviors.Add(new ServiceMetadataBehavior());
}
protected override void InitializeRuntime()
{
// Add an endpoint for the given service contract.
this.AddServiceEndpoint(
typeof(IDuplexService),
new CustomBinding(
new PollingDuplexBindingElement(),
new BinaryMessageEncodingBindingElement(),
new HttpTransportBindingElement()),
"");
// Add a metadata endpoint.
this.AddServiceEndpoint(
typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex");
base.InitializeRuntime();
}
}
}
<%@ServiceHost language="c#" Debug="true"
Factory="DuplexService.PollingDuplexServiceHostFactory"%>
请仔细看,这与之前的不同。此DLL是从Libraries\Client文件夹引用的。
您可以看到我们正在请求雅虎的价格,因为它存在于我们的列表中。如果我们输入其他内容,服务器将响应“无效的股票请求”。
namespace SilverlightApplication2
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
EndpointAddress address =
new EndpointAddress("https://:1582/Service1.svc");
PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding();
DuplexServiceClient proxy = new DuplexServiceClient(binding, address);
proxy.PushPricesReceived +=
new EventHandler<PushPricesReceivedEventArgs>(
proxy_PushPricesReceived);
//the only allowed stocks are Yahoo,Microsoft,Google.
//else the service will return 'Invalid Stock Request'
string stocksymb = "Yahoo";
proxy.RequestPriceAsync(stocksymb);
info.Text = "Fetch price for " + stocksymb +
Environment.NewLine + Environment.NewLine;
}
void proxy_PushPricesReceived(object sender, PushPricesReceivedEventArgs e)
{
reply.Text = "Current Market Price : ";
reply.Text += e.p;
}
}
}
<div id="silverlightControlHost">
<object data="data:application/x-silverlight-2,"
type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/SilverlightApplication2.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40818.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0"
style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376"
alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object><iframe id="_sl_historyFrame"
style="visibility:hidden;height:0px;width:0px;border:0px">
</iframe>
</div>