Laden...

[gelöst] Multiple File Upload via WCF SOAP Endpoint (MTOM) und SoapUI

Erstellt von Wax vor 5 Jahren Letzter Beitrag vor 5 Jahren 2.083 Views
Wax Themenstarter:in
731 Beiträge seit 2006
vor 5 Jahren
[gelöst] Multiple File Upload via WCF SOAP Endpoint (MTOM) und SoapUI

Hallo,

Ich habe einen WCF Service der es ermöglicht Dateien hochzuladen. Nun habe ich die Anforderung bekommen, dass die Dateien am besten mittels MTOM Encoding hochgeladen werden sollen und am besten 3 Dateien in einem Request. Der Endpunkt der sich um den Upload kümmert, hat als Binding Parameter das MessageEncoding mit MTOM eingerichtet. Jetzt frage ich mich ob ich im dazugehörigem ServiceContract einfach eine Collection von Streams verwenden kann oder ob es eine Collection von Byte Arrays sein muss, um mehrere MTOM Attachments gleichzeitig entgegennehmen zu können.

Kennt sich da jemand vielleicht mit aus?

Gruß
wax

T
2.219 Beiträge seit 2008
vor 5 Jahren

Zwar habe ich mit MTOM noch nicht gearbeitet, aber die Dateien würde ich als Byte Arrays übertragen.
Je nachdem was du zusätzlich zur Datei übertragen musst, also Daten wie Dateiname etc., würde ich dann eine entsprechende Struktur für die Dateien bauen.
Der Service würde dann einfach eine Liste der Strukturen bekommen und diese dann verarbeiten.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.807 Beiträge seit 2008
vor 5 Jahren

Prinzipiell ist es theoretisch möglich mehrere Streams anzugeben.
Da aber WCF auf einem Single Stream pro Verbindung basiert, macht das überhaupt kein Sinn.

3.003 Beiträge seit 2006
vor 5 Jahren

Normalerweise würde man für den Ansatz eine eigene Stream-Implementierung benutzen, die intern die Sammlung von Streams abgrast. Jedenfalls machen wir das so, ist übersichtlich und wird auch von MS empfohlen. Für den Fall, dass es sich um viele kleine Streams ohne semantischen Zusammenhang handelt, empfiehlt MS dagegen mehrere Requests in einer Session.

The most common scenario in which such large data content transfers occur are transfers of binary data objects that:

Cannot be easily broken up into a message sequence.

Must be delivered in a timely manner.

Are not available in their entirety when the transfer is initiated.

For data that does not have these constraints, it is typically better to send sequences of messages within the scope of a session than one large message. For more information, see the "Streaming Data" section later in this topic.

LaTino
EDIT: @T-Virus es geht, wenn ich das richtig verstanden habe, um Streamed Transfer. Die Frage, ob man Stream verwendet oder nicht, stellt sich also nicht.

WCF: Large data and streaming

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

Wax Themenstarter:in
731 Beiträge seit 2006
vor 5 Jahren

Hi zusammen,

danke erstmal für die bisherigen Antworten!

Es muss nicht unbedingt per Stream gemacht werden.

Ich habe jetzt eine Variante, in der mehrere Dateien gleichzeitig geschickt werden könnten.
Hier mal ein Beispiel Aufruf, wie ich ihn aus SoapUI heraus abschicken möchte:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="www.tempuri.org" xmlns:bgp="http://schemas.datacontract.org/2004/07/WSController.Models">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:UploadMultipartDocument>
         <!--Optional:-->
         <tem:multipartDocument>
            <bgp:Parts>
               <bgp:DocumentPart>
                  <bgp:Name>part1.xml</bgp:Name>
                  <bgp:PartData>cid:794981264365</bgp:PartData>
               </bgp:DocumentPart>
               <bgp:DocumentPart>
                  <bgp:Name>part2.xml</bgp:Name>
                  <bgp:PartData>cid:123481264365</bgp:PartData>
               </bgp:DocumentPart>
            </bgp:Parts>
         </tem:multipartDocument>
      </tem:UploadMultipartDocument>
   </soapenv:Body>
</soapenv:Envelope>

In SoapUI wird mir angezeigt, dass die beiden Attachments vom Typ "XOP" sind, also glaube ich erstmal in Ordnung.

Auf Service Seite wirft der XmlMtomReader jetzt die Exception "Ein MIME-Abschnitt mit der Content-ID "cid:794981264365" konnte nicht gefunden werden."

Also entweder schnürt SoapUI das Gesamtpaket nicht korrekt oder ich habe noch ein tieferliegendes Problem.

Gruß
wax

16.807 Beiträge seit 2008
vor 5 Jahren

Und wie sieht der OperationContract aus.. und TransferMode ist auf Streamed.....?

Wax Themenstarter:in
731 Beiträge seit 2006
vor 5 Jahren

Hier der ServiceContract:


    [ServiceContract(Namespace = "www.tempuri.org")]
    public interface IMultipartDocumentsService
    {
        [OperationContract(Name = "UploadMultipartDocument")]
        void UploadMultipartDocument(MultipartDocument multipartDocument);
    }

Die dazugehörigen Models:


[DataContract]
public class MultipartDocument
{

    [DataMember(IsRequired = true)]
    public string ID
    {
        get;
        set;
    }

    [DataMember(IsRequired = true)]
    public string CreationDate
    {
        get;
        set;
    }


    [DataMember(IsRequired = true)]
    public string Name
    {
        get;
        set;
    }

    [DataMember(IsRequired = true)]
    public Collection<DocumentPart> Parts
    {
        get;
        set;
    }

    public MultipartDocument()
    {
        Parts = new Collection<DocumentPart>();
    }

}



[DataContract]
public class DocumentPart
{

    [DataMember(IsRequired = true)]
    public string Name
    {
        get;
        set;
    }

    [DataMember(IsRequired = true)]
    public byte[] PartData
    {
        get;
        set;
    }

}

Hier das dazugehörige Binding:


<basicHttpBinding>
    <binding name="httpsWithMtom" messageEncoding="Mtom" textEncoding="utf-8">
        <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName"/>
        </security>
    </binding>
 </basicHttpBinding>

Gruß
wax

Wax Themenstarter:in
731 Beiträge seit 2006
vor 5 Jahren

Ich habe es hinbekommen und es lag tatsächlich an der Art und Weise wie das SOAP-XML in SoapUI definiert wird. Wenn man in SoapUI ein Attachment hinzufügt, dann wird eine ContentID vergeben.

Und genau diese ContentID musste einfach gleich sein zu dem dazugehörigen PART Eintrag:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="www.tempuri.org" xmlns:bgp="http://schemas.datacontract.org/2004/07/WSController.Models">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:UploadMultipartDocument>
         <!--Optional:-->
         <tem:multipartDocument>
            <bgp:Parts>
               <bgp:DocumentPart>
                  <bgp:Name>part1.xml</bgp:Name>
                  <bgp:PartData>cid:part1.xml</bgp:PartData>
               </bgp:DocumentPart>
               <bgp:DocumentPart>
                  <bgp:Name>part2.xml</bgp:Name>
                  <bgp:PartData>cid:part2.xml</bgp:PartData>
               </bgp:DocumentPart>
            </bgp:Parts>
         </tem:multipartDocument>
      </tem:UploadMultipartDocument>
   </soapenv:Body>
</soapenv:Envelope>

Attachments in SoapUI:
part1.xml mit PART="part1.xml" und ContentID="part1.xml"
part2.xml mit PART="part2.xml" und ContentID="part2.xml"

Für den Request sind außerdem natürlich noch EnableMTOM und ForceMTOM auf true zu setzen.

Gruß
wax