EDIT2:我的同事发现了一个可用的解决方案:来自微软的Web Service Enhancements。它确实需要IIS,并且在引入WCF时已被弃用,但在纯净的.Net Framework 2.0中运行良好,并且应该可部署到Mono XSP。
EDIT:下面溶液是没有意义的,因为净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
简单的创建a 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; }
}
这也可以用来与网络服务一起提供其他文件。我目前正在使用这种方法来托管我的Silverlight应用程序(Web服务的使用者),而无需单独的http服务器。
你曾经尝试在Windows机器上运行你的web服务..?是那个作品.. ?? – RameshVel 2009-08-25 10:59:08
是的,它的确如此,这只是Silverlight的安全限制,可以防止我想到的情况。 – skolima 2009-08-25 12:35:08