2010-02-17 7 views
10

WCF verwendet http://tempuri/1/number für Content-ID-uri-Verweise bei der Verarbeitung von MTOM-Streamanforderungen.WCF: (MTOM) gibt es eine Möglichkeit, das in xop verwendete Schema zu ändern: Inhaltsreferenz Uris von WCF generiert?

Gibt es eine Möglichkeit, WCF zu zwingen, eine andere Content-ID-Verweise für den xop zu verwenden: Include?

Hintergrund des Problems:

Ich baue ein .NET-Client für MTOM JAX ws Java Web Service aktiviert, die große Datenuploads gestreamt Griffe. Ich habe die Service- und Datenkontakte manuell erstellt (die von WSDL generierten Verträge waren nicht korrekt und erlaubten kein Streaming).

Das Problem ist, dass der Web-Service (Jax Ws) nicht den Anfragetext erhält, der die Daten enthält.

Es empfängt die Daten, die in Kopfzeilen übertragen werden.

Wir haben einen Java-Client für die ws gebaut - dieser funktioniert.

Ich habe gefangen genommen und den HTTP-Verkehr im Vergleich, wenn Anfragen von Java und wcf Ausgabe, und der einzige Unterschied besteht darin, wie Content-ID Referenz erzeugt wird, wenn die Multipart Daten veröffentlichen:

  • WCF verwendet http://tempuri/1/... Inhalt -ID Referenzen, die in codiertem Wert ergeben, wie href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928"

  • Java-Client verwendet "E-Mail-style" uris, wie href="cid:[email protected]"

Diese Ausbeute bei der folgenden XOP-includes (Data ist das einzige Element in dem Seifenkörper) (XOP includes specification)


//WCF: 
<Data> 
    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928" /> 
</Data> 

//JAVA: 
<Data> 
    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/> 
</Data> 

später, in den Multipart-Daten, wobei der Gehalt an von uncodierten bezeichnet wird Content-ID:

--uuid:7e166bb7-042f-4ba3-b6ef-98fbbc21244b+id=1 
Content-ID: <http://tempuri.org/1/634019957020047928> 
Content-Transfer-Encoding: binary 
Content-Type: application/octet-stream 

ich denke, es kann ein Fehler in dem JAX Web-Service-Framework und es ist nicht zu erkennen WCF-generated + urlencoded Content-ID uri Referenzen.

Gibt es eine Möglichkeit, WCF zu zwingen, eine andere Content-ID-Verweise für den xop zu verwenden: Include?


EDIT: Ich habe die XmlMtomWriter gefunden haben, die die GenerateUriForMimePart Methode hat, wird diese verwendet Inhalt-IDs zu generieren.

public static string GenerateUriForMimePart(int index) 
{ 
    return string.Format(CultureInfo.InvariantCulture, 
"http://tempuri.org/{0}/{1}", new object[] { index, DateTime.Now.Ticks }); 
} 

Es scheint nicht, dass die ID-Generation in irgendeiner Weise übersteuerbar ist.

Ein ähnliches Problem wird hier beschrieben, sofern die Antwort nicht hilft: http://social.msdn.microsoft.com/Forums/en/wcf/thread/f90affbd-f431-4602-a81d-cc66c049e351

Antwort

1

mir Asnwering nach langer Untersuchung: Nicht möglich, ohne dass der ganzen XmlMtomWriter und andere damit zusammenhängende Schichten und Anliegen in WCF Neuimplementierung - fast alles beteiligt Die Implementierung von mtom ist intern.

0

Beide XOP enthält Beispiele, die Sie laut W3C als korrekt und akzeptabel angegeben haben. Ich bezeichne sie als das URL-Format bzw. das E-Mail-Format.

Ich bin kein JAVA-Entwickler, aber erinnere mich an ein ähnliches Problem bei der Schnittstelle mit einem bestimmten JAVA-Webdienst. Ich erinnere mich, dass es in einer bestimmten JAVA-Version einen Bug gab und nachdem sie (die JAVA-Entwickler) auf die nächste Version aktualisiert hatten, ging dieses Problem einfach weg. Ich wünschte, ich könnte Ihnen mehr Details geben, aber zu der Zeit gab es genug Probleme für mich von meinem Ende der Leitung an zu adressieren und ich war nur froh, einen weniger Artikel auf dem Defektprotokoll zu haben.

//WCF: using URL format 
<Data> 
    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928" /> 
</Data> 

//JAVA: using EMAIL format 
<Data> 
    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/> 
</Data> 
1

Ich weiß, es eine alte Frage. Aber vor zwei Tagen habe ich das gleiche Problem.

Ich habe einen Weg gefunden, der funktioniert, ABER es ist ein SEHR SEHR dreckiger Hack (Ich weiß das. Ich dachte daran, es hier nicht zu veröffentlichen, aber vielleicht würde es jemandem helfen.) Hoffentlich wirst du mir dafür keine Vorwürfe machen.

Die ContentId wird mit CultureInfo.InvariantCulture formatiert. Ich habe keinen offiziellen Weg gefunden, um es durch eine benutzerdefinierte CultureInfo zu ersetzen. Aber mit Hilfe der Reflexion habe ich es in Gang gebracht. Die folgende Implementierung ist nur für .NET 4.0.

public class NoTempUriInvariantCultureInfo : CultureInfo, ICustomFormatter 
{ 
    private static CultureInfo originalCulture; 
    private static object originalCultureLock; 
    private static int enableCounter; 

    private NoTempUriInvariantCultureInfo(CultureInfo invariantCulture) 
     : base(invariantCulture.Name) 
    { 
     originalCulture = invariantCulture; 
    } 

    public static void Enable() 
    { 
     if(originalCultureLock == null) 
     originalCultureLock = new object(); 

     lock (originalCultureLock) 
     { 
     if (enableCounter == 0) 
     { 
      var mInvCultField = typeof (CultureInfo).GetField("s_InvariantCultureInfo", BindingFlags.NonPublic | BindingFlags.Static); 
      mInvCultField.SetValue(null, new NoTempUriInvariantCultureInfo(CultureInfo.InvariantCulture)); 
     } 
     enableCounter++; 
     } 
    } 

    public static void Disable() 
    { 
     lock (originalCulture) 
     { 
     if (enableCounter == 0) 
      return; 

     enableCounter--; 
     if (enableCounter == 0) 
     { 
      var mInvCultField = typeof (CultureInfo).GetField("s_InvariantCultureInfo", BindingFlags.NonPublic | BindingFlags.Static); 
      mInvCultField.SetValue(null, NoTempUriInvariantCultureInfo.originalCulture); 
     } 
     } 
    } 

    public override object GetFormat(Type formatType) 
    { 
     var result = originalCulture.GetFormat(formatType); 
     return result ?? this; 
    } 

    public string Format(string format, object arg, IFormatProvider formatProvider) 
    { 
     if (format == null) 
     return System.Text.RegularExpressions.Regex.Replace(arg.ToString().Replace("http%3A%2F%2Ftempuri.org%2F1%2F", ""), "http[:][/][/]tempuri[.]org[/][0-9]+[/]*", ""); 
     return String.Format("{0:" + format + "}", arg); 
    } 
} 

Ich aktivieren meine eigene "InvariantCulture" nur vor einem WCF-Anruf.

NoTempUriInvariantCultureInfo.Enable(); 
try 
{ 
    // make your call 
} 
finally 
{ 
    NoTempUriInvariantCultureInfo.Disable(); 
} 

CultureInfo.InvariantCulture ist ein globales Statusobjekt. Die Aktivierung meiner eigenen InvariantCulture wirkt sich auf jeden anderen Thread aus. Wieder ist es ein schmutziger Hack. Aber es funktioniert.

+0

ja, das ist dreckig, aber herzlichen Glückwunsch zum Finden einer Lösung, die funktioniert. Ich hätte nicht gedacht, InvariantCulture durch Reflexion zu ersetzen, aber es scheint, dass es wirklich die einzige Option ist. – Marek

Verwandte Themen