[英]How can I expose a .Net 2.0 Webservice to a Silverlight client?
我有一个简单的.Net 2.0 SOAP Web服务。 我想从托管在同一服务器但不同端口上的Silverlight应用程序访问它。 我知道要使其正常工作,我需要提供一个clientaccesspolicy.xml
或crossdomain.xml
策略文件(该服务位于http://example:8085/RemoteObject.rem?wsdl
,因此该策略文件必须位于http://example:8085/crossdomain.xml
)。 与WCF示例一样,我应该在以下简单的Web服务中添加些什么以自助服务策略文件 ?
该Web服务正在Mono上运行,尽管这不应更改任何内容-仅涉及IIS。
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
namespace ConsoleApplication1
{
class RemoteObject : MarshalByRefObject
{
static void Main()
{
var channel = new HttpChannel(8085);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemoteObject), "RemoteObject.rem",
WellKnownObjectMode.Singleton);
Console.WriteLine("Press ENTER to exit the server.");
Console.ReadLine();
}
public DateTime Now()
{
return DateTime.Now;
}
}
}
编辑:由于所有无法使用的答案,让我重复一遍:我需要使用.Net 2.0(而不是3.0或3.5)来进行此操作。 WCF不可用 。
我对MONO中的deploymnets了解不多。 如果您没有找到更好的方法来解决这个问题,我建议您使用其他方法。
您可以从托管的Silverlight代码中使用以下方法来调用javascript方法:
string sJson = HtmlPage.Window.Invoke("JSMethod", new string[] { strInParam }) as string;
并将AJAX请求(来自JS方法)发送到您的服务器,并将在内部对MONO中部署的Web服务进行调用(来自服务器),并返回JSON格式的结果。
我已经在我的项目中实现了这种方法,并且效果很好。
只是一种选择。
好的,我可以说答案并非易事。 请查看Cassini开源Web服务器,您将必须在应用程序中实现小型Web服务器,然后在自定义Web服务器中运行自定义服务。
打开此Silverlight的最佳方法是创建一个IFrame,并使其从自定义端口本身的自定义Web服务器加载html / aspx。 因此,您将不需要任何跨域策略问题。
EDIT2 : 我的同事找到了一个可用的解决方案:Microsoft的Web服务增强 。 它确实需要IIS,并且已随着WCF的引入而弃用,但它与纯.Net Framework 2.0兼容,并且可以与Mono XSP一起部署。
编辑 : 下面的解决方案是没有意义的,因为.Net 2.0使用SOAP 1.1 rpc /编码模型公开了Web服务,而Silverlight需要SOAP 1.2文档/文字。 因此,尽管解决方法可以解决问题中指出的问题,但仍无法使用Web服务。
我设法做到了这一点而不求助于极端的技巧。 我的解决方案的关键是在请求处理队列中插入一个额外的IServerChannelSink
。 所以,我改变了
var channel = new HttpChannel(8085);
在普通管道之前注册我的自定义IServerChannelSink
:
var provider = ChainProviders(
new PolicyServerSinkProvider(),
new SdlChannelSinkProvider(),
new SoapServerFormatterSinkProvider(),
new BinaryServerFormatterSinkProvider());
var channel = new HttpChannel(new Hashtable(1) {{"port", 8085}}, null, provider);
我使用辅助方法将接收器提供程序链接在一起:
private static IServerChannelSinkProvider ChainProviders(
params IServerChannelSinkProvider[] providers)
{
for (int i = 1; i < providers.Length; i++)
providers[i-1].Next = providers[i];
return providers[0];
}
PolicyServerSinkProvider
只需创建一个PolicyServerSink
:
internal class PolicyServerSinkProvider : IServerChannelSinkProvider
{
public void GetChannelData(IChannelDataStore channelData){}
public IServerChannelSink CreateSink(IChannelReceiver channel)
{
IServerChannelSink nextSink = null;
if (Next != null)
nextSink = Next.CreateSink(channel);
return new PolicyServerSink(channel, nextSink);
}
public IServerChannelSinkProvider Next { get; set; }
}
PolicyServerSink
将所有消息委派到整个链中,除非它获得对crossdomain.xml
的请求-然后它将所需的xml写入响应流。
internal class PolicyServerSink : IServerChannelSink
{
public PolicyServerSink(
IChannelReceiver receiver, IServerChannelSink nextSink)
{
NextChannelSink = nextSink;
}
public IDictionary Properties { get; private set; }
public ServerProcessing ProcessMessage(
IServerChannelSinkStack sinkStack, IMessage requestMsg,
ITransportHeaders requestHeaders, Stream requestStream,
out IMessage responseMsg, out ITransportHeaders responseHeaders,
out Stream responseStream)
{
if (requestMsg != null || ! ShouldIntercept(requestHeaders))
return NextChannelSink.ProcessMessage(
sinkStack, requestMsg, requestHeaders, requestStream,
out responseMsg, out responseHeaders, out responseStream);
responseHeaders = new TransportHeaders();
responseHeaders["Content-Type"] = "text/xml";
responseStream = new MemoryStream(Encoding.UTF8.GetBytes(
@"<?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>")) {Position = 0};
responseMsg = null;
return ServerProcessing.Complete;
}
private static bool ShouldIntercept(ITransportHeaders headers)
{
return ((string) headers["__RequestUri"]).Equals(
"/crossdomain.xml", StringComparison.InvariantCultureIgnoreCase);
}
public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack,
object state, IMessage msg, ITransportHeaders headers, Stream stream)
{
}
public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack,
object state, IMessage msg, ITransportHeaders headers)
{
throw new NotSupportedException();
}
public IServerChannelSink NextChannelSink { get; private set; }
}
这也可以用于与Web服务一起提供其他文件。 我目前正在使用此方法来托管我的Silverlight应用程序(Web服务的使用者),而没有单独的http服务器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.