我有一个简单的.Net 2.0 SOAP Web服务。我想从Silverlight应用程序访问它,该应用程序托管在同一台服务器上,但不同的端口。我知道要实现此目的,我需要提供clientaccesspolicy.xml
或crossdomain.xml
政策文件(该服务位于http://example:8085/RemoteObject.rem?wsdl
,因此政策文件必须出现在http://example:8085/crossdomain.xml
})。我应该将以下简单的Web服务添加到self-serve the policy file like the WCF example does?
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无法使用。
答案 0 :(得分:2)
我对MONO中的deploymnets了解不多。如果你没有为你的问题找到更好的方法,我建议采用不同的方法。
您可以使用
从您管理的Silverlight代码中调用javascript方法,而不是直接从silverlight应用程序调用web服务。string sJson = HtmlPage.Window.Invoke("JSMethod", new string[] { strInParam }) as string;
并将AJAX请求(来自JS方法)发送到您的服务器,并在内部调用部署在MONO中的Web服务(来自服务器)并返回JSON格式的结果。
我已经在我的项目中实现了这种方法,并且工作正常......
只是另一种选择..
答案 1 :(得分:1)
好的,我可以说答案不是一个简单的步骤。请查看Cassini开源Web服务器,您必须在应用程序中实现一个小型Web服务器,并在自定义Web服务器中运行自定义服务。
打开这个Silverlight的最好方法是,创建一个IFrame,然后从自定义端口本身加载自定义Web服务器的html / aspx。因此,您不需要任何跨域策略问题。
答案 2 :(得分:1)
EDIT2 :我的同事找到了一个可用的解决方案:来自Microsoft的Web Service Enhancements。它确实需要IIS,并且随着WCF的引入而被弃用,但与普通.Net Framework 2.0一起运行良好,并且可以与Mono XSP一起部署。
编辑:下面的解决方案毫无意义,因为.Net 2.0使用SOAP 1.1 rpc / encoded模型公开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服务器。
答案 3 :(得分:0)