none
WebService-Programmierung mit HTTP-Post und XML RRS feed

  • Frage

  • Hallo an die Experten,

    ich muss Daten bei einem WebService abfragen. Das habe ich mit diesem Code-Schnipsel gelöst (xd enthält ein XmlDocument).

    WebRequest req = WebRequest.Create("http://Internet.html");
    byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xd.InnerXml);
    req.Method = "POST";
    req.ContentType = "text/xml";
    req.ContentLength = requestBytes.Length;
    Stream requestStream = req.GetRequestStream();
    requestStream.Write(requestBytes, 0, requestBytes.Length);
    requestStream.Close();
    WebResponse res = req.GetResponse();
    StreamReader sr = new StreamReader(res.GetResponseStream(), System.Text.Encoding.Default);
    MessageBox.Show(sr.ReadToEnd(), "Erfolg");
    sr.Close();
    res.Close();
    

    Funktioniert soweit.

    Nun muss ich das Gegenstück programmieren, also einen WebService.

    Probiert habe ich es so:

    [WebMethod(Description = "Test WebService")]
    public getBookingAvailabilityResponse GetAvailability(XmlDocument xd)
    {
        // Xml-Daten verarbeiten und zurückgeben
        getBookingAvailability GetBookingAvailability = new getBookingAvailability(xd);
        getBookingAvailabilityResponse resp = new getBookingAvailabilityResponse();
        return resp;
    }
    

    Problem ist nur: Der Client bekommt immer Fehler 500 und meldet "GetAvailability ist kein gültiger WebDienst-Methodenname.

    Ich bekomme einfach den Parameter nicht korrekt übergeben.

    Kann jemand helfen?

    Mfg

    Micha

    Sonntag, 2. September 2012 16:55

Antworten

  • Hallo Micha,

    im Endeffekt ist das nicht anderes als ein String, der zufälligerweise XML enthält. Damit das über einen Webservice (der das ganze auch in einer XML Struktur empfängt) funktioniert, sollte der XML Teil, den Du senden willst, codiert werden. Ich persönlich wähle hier meist Base64, dann muss ich mich nicht um die ganzen XML Eigenheiten kümmern.

    Im Endeffekt müsstest Du also deinem Client lediglich sagen, dass er vor dem dem Aufruf der Webservicemethode den Inhalt deines XMLDocument als String lesen und per Base64 codieren soll. Auf der Serverseite nimmst Du den String und decodierst ihn wieder.

    Falls es evtl. Verständnisprobleme gibt, hab ich mal ein "Oldstyle" Beispiel in VBScript, daran siehst Du, wie man einen Webservice auch komplett manuell aufrufen kann und wie der Aufruf aufgebaut werden muss. Für deine Anforderungen musst Du das natürlich ein wenig anders machen, das Beispiel sollte aber zeigen, wie es gehen kann.

    <%
    Const Address    = "http://dein.server.tld/Webservices/DeinWebservice.asmx"
    Dim   Parameters
          Parameters = "<?xml version=""1.0"" encoding=""utf-8""?>" & _
                       "<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">" & _
                       "  <soap:Body>" & _
                       "      <AddComplexType xmlns=""http://tempuri.org/"">" & _
                       "        <NewItem>" & _
                       "          <ID>4711</ID>" & _
                       "          <Name>Neuer Eintrag</Name>" & _
                       "          <Email>neue@emailadresse.tld</Email>" & _
                       "        </NewItem>" & _
                       "      </AddComplexType>" & _
                       "  </soap:Body>" & _
                       "</soap:Envelope>"
    
    Dim objHTTP
    Set objHTTP = Server.CreateObject("WinHttp.WinHttpRequest.5.1")
    
        objHTTP.SetTimeouts 5000, 5000, 5000, 5000
        objHTTP.open "POST", Address, false
        objHTTP.setRequestHeader "Content-Type",   "text/xml; charset=utf-8"
        objHTTP.setRequestHeader "Content-Length", "application/x-www-form-urlencoded"
        objHTTP.send Parameters
    
        strResult  = objHTTP.ResponseText
        If strResult <> "" Then
            Response.ContentType = "text/xml"
            Response.Write strResult
        Else
            Response.Write "No response from webservice"
        End if
    
    Set objHTTP = Nothing
    %>
    


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort markiert MichaMoll Dienstag, 4. September 2012 15:14
    Montag, 3. September 2012 23:20
    Moderator

Alle Antworten

  • Hi,

    in solchen Fällen ist es sinnvoll, sich mal mit irgendeinem Tool (Firebug, Fiddler, ...) anzuschauen, was normalerweise durch die Leitung geschickt wird.

    Die Webservices haben bei lokalem Aufruf und nicht komplexen Übergabetypen auch Testmethoden. Daran kann man sehen, dass der Aufbau einem Schema entspricht. Alternativ einfach mal an der Visual Studio Eingabeaufforderung wcftestclient eingeben, den Dienst dort abonnieren und dann schauen, was übergeben wird.

    Ich frage mich allerdings, warum Du den ganzen Kram überhaupt manuell machen willst? Füg in deinem Projekt doch einfach einen Webverweis auf den Webservice hinzu und lass Visual Studio den Rest machen. VS generiert Proxyklassen, alle Methoden zum Aufrufen der Methoden inkl. Rückgabe, usw.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Montag, 3. September 2012 08:05
    Moderator
  • Hallo Stefan,

    das ist ja mein Problem: Die Übergabetypen sind XML-Dateien und somit "komplex". Da hilft mir keine Testmethode und auch wcftestclient muss leider passen.

    Ich muss das insofern manuell machen, da ich ja den Web-Service erstellen muss. Die Vorgabe dabei lautet: Die Daten werden über http-POST (und nicht SOAP) übergeben. Das scheint (?) durch VS nicht automatisch unterstützt zu werden...

    Ich hatte gestern Nacht noch ein andere Idee: Möglicherweise ist ein Web-Service in diesem Fall der völlig falsche Ansatz. Wenn die Daten per http-POST übergeben werden sollen, so müsste es eigentlich auch ein httpListener tun. Ich werde das mal in diese Richtung weiter verfolgen...

    Gruß

    Micha


    • Bearbeitet MichaMoll Montag, 3. September 2012 17:45
    Montag, 3. September 2012 17:23
  • Hallo Micha,

    im Endeffekt ist das nicht anderes als ein String, der zufälligerweise XML enthält. Damit das über einen Webservice (der das ganze auch in einer XML Struktur empfängt) funktioniert, sollte der XML Teil, den Du senden willst, codiert werden. Ich persönlich wähle hier meist Base64, dann muss ich mich nicht um die ganzen XML Eigenheiten kümmern.

    Im Endeffekt müsstest Du also deinem Client lediglich sagen, dass er vor dem dem Aufruf der Webservicemethode den Inhalt deines XMLDocument als String lesen und per Base64 codieren soll. Auf der Serverseite nimmst Du den String und decodierst ihn wieder.

    Falls es evtl. Verständnisprobleme gibt, hab ich mal ein "Oldstyle" Beispiel in VBScript, daran siehst Du, wie man einen Webservice auch komplett manuell aufrufen kann und wie der Aufruf aufgebaut werden muss. Für deine Anforderungen musst Du das natürlich ein wenig anders machen, das Beispiel sollte aber zeigen, wie es gehen kann.

    <%
    Const Address    = "http://dein.server.tld/Webservices/DeinWebservice.asmx"
    Dim   Parameters
          Parameters = "<?xml version=""1.0"" encoding=""utf-8""?>" & _
                       "<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">" & _
                       "  <soap:Body>" & _
                       "      <AddComplexType xmlns=""http://tempuri.org/"">" & _
                       "        <NewItem>" & _
                       "          <ID>4711</ID>" & _
                       "          <Name>Neuer Eintrag</Name>" & _
                       "          <Email>neue@emailadresse.tld</Email>" & _
                       "        </NewItem>" & _
                       "      </AddComplexType>" & _
                       "  </soap:Body>" & _
                       "</soap:Envelope>"
    
    Dim objHTTP
    Set objHTTP = Server.CreateObject("WinHttp.WinHttpRequest.5.1")
    
        objHTTP.SetTimeouts 5000, 5000, 5000, 5000
        objHTTP.open "POST", Address, false
        objHTTP.setRequestHeader "Content-Type",   "text/xml; charset=utf-8"
        objHTTP.setRequestHeader "Content-Length", "application/x-www-form-urlencoded"
        objHTTP.send Parameters
    
        strResult  = objHTTP.ResponseText
        If strResult <> "" Then
            Response.ContentType = "text/xml"
            Response.Write strResult
        Else
            Response.Write "No response from webservice"
        End if
    
    Set objHTTP = Nothing
    %>
    


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    • Als Antwort markiert MichaMoll Dienstag, 4. September 2012 15:14
    Montag, 3. September 2012 23:20
    Moderator