2009-08-20 5 views
2

Ich habe einen trivialen .Net 2.0 SOAP Web Service. Ich möchte auf die Silverlight-Anwendung zugreifen, die auf demselben Server, aber auf einem anderen Port gehostet wird. Ich weiß, dass, damit dies funktioniert, ich eine clientaccesspolicy.xml oder crossdomain.xml Richtliniendatei bereitstellen muss (der Dienst ist verfügbar unter http://example:8085/RemoteObject.rem?wsdl, so dass die Richtliniendatei bei http://example:8085/crossdomain.xml vorhanden sein muss). Was sollte ich dem folgenden einfachen Web-Service zu self-serve the policy file like the WCF example does hinzufügen?Wie kann ich einem Silverlight-Client einen .Net 2.0-Webdienst bereitstellen?

Der Webservice wird auf Mono ausgeführt, obwohl das nichts ändern sollte - es gibt einfach keinen 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; 
     } 
    } 
} 

EDIT: wegen all der unbrauchbaren Antworten, möchte ich mich wiederhole: Ich brauche das 2.0 mit .NET zu tun, nicht 3.0 oder 3.5. WCF ist nicht verfügbar.

+0

haben Sie jemals versucht, Ihren Webservice in Windows-Maschine zu betreiben ..? funktioniert das .. ?? – RameshVel

+0

Ja, das sind nur die Sicherheitseinschränkungen von Silverlight, die das Szenario verhindern, das ich mir vorgenommen habe. – skolima

Antwort

1

EDIT2: mein Kollege hat eine brauchbare Lösung gefunden: Web Service Enhancements von Microsoft. Es benötigt IIS und es wurde mit der Einführung von WCF veraltet, aber funktioniert gut mit einfachem .Net Framework 2.0 und sollte mit Mono XSP deployable sein.

EDIT: Lösung unten ist sinnlos, weil .NET 2.0 Web-Services setzt unter Verwendung von SOAP 1.1 rpc/encoded Modell und Silverlight erfordert SOAP 1.2 Dokument/Literal. Während die Problemumgehung für das in der Frage angegebene Problem funktioniert, kann der Web-Service dennoch nicht verwendet werden.

Ich schaffte es, diese Arbeit ohne den Rückgriff auf extreme Hacks zu machen. Der Schlüssel zu meiner Lösung war das Einfügen einer zusätzlichen IServerChannelSink in die Anforderungsverarbeitungswarteschlange.Also änderte ich

var channel = new HttpChannel(8085); 

zu meinen benutzerdefinierten registrieren IServerChannelSink vor der normalen Pipeline:

var provider = ChainProviders(
    new PolicyServerSinkProvider(), 
    new SdlChannelSinkProvider(), 
    new SoapServerFormatterSinkProvider(), 
    new BinaryServerFormatterSinkProvider()); 
var channel = new HttpChannel(new Hashtable(1) {{"port", 8085}}, null, provider); 

Ich benutze eine Hilfsmethode zur Kette der Spüle Anbieter zusammen:

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 einfach erstellt 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 delegiert alle Nachrichten in der Kette, außer wenn sie eine Anforderung für crossdomain.xml erhält - dann schreibt sie das benötigte XML in den Antwortstream.

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; } 
} 

Dies kann auch verwendet werden, um andere Dateien zusammen mit dem Webdienst zu bedienen. Ich verwende diese Methode derzeit, um meine Silverlight-Anwendung (den Consumer des Webdienstes) ohne einen separaten HTTP-Server zu hosten.

+0

.NET 2.0 kann auch Dokument/Literal. –

2

ich über die deploymnets in MONO wissen viel nicht. Ich würde einen anderen Ansatz vorschlagen, wenn Sie keine besseren Ansätze für Ihre Frage finden würden.

Anstatt die Webservice von Silverlight-Anwendung aufrufen .. können Sie eine Javascript-Methode von Ihrem verwalteten Silver Code

string sJson = HtmlPage.Window.Invoke("JSMethod", new string[] { strInParam }) as string; 

und Feuer eine AJAX-Anforderung (von JS-Methode) auf dem Server aufrufen und wird intern Rufen Sie den in MONO bereitgestellten Webserver (vom Server) an und geben Sie ein JSON-formatiertes Ergebnis zurück.

ich diesen Ansatz in meinen Projekten umgesetzt haben und ihre Arbeit fein ..

nur eine Alternative ..

+0

Dies sieht aus wie eine ausgezeichnete Antwort – JustLoren

+0

Dank Loren ... – RameshVel

1

Ok, kann ich sagen, dass Antwort kein einfacher Schritt ist. Bitte schauen Sie sich den Open-Source-Webserver von Cassini an, und Sie müssen einen kleinen Webserver in Ihrer Anwendung implementieren und Ihren benutzerdefinierten Dienst auf Ihrem benutzerdefinierten Webserver ausführen.

Und der beste Weg, um diese Silverlight zu öffnen wäre, erstellen Sie ein IFrame und lassen Sie es die HTML/aspx von Ihrem benutzerdefinierten Webserver von Ihrem benutzerdefinierten Port selbst laden. Sie benötigen also keine Cross-Domain-Richtlinienprobleme.

Verwandte Themen