with enable cid attachments array wcf soap jax-ws mtom xop

enable - WCF:(MTOM) ¿hay alguna forma de cambiar el esquema utilizado en xop: uris de referencia de contenido generadas por WCF?



soapui mtom (3)

Ambos XOP incluyen muestras que usted indicó son correctas y aceptables de acuerdo con el W3C. Me refiero a ellos como el formato de URL y el formato de correo electrónico, respectivamente.

No soy desarrollador de JAVA, pero recuerdo un problema similar cuando interactúo con un servicio web de JAVA en particular. Recuerdo que había un error en un lanzamiento de JAVA en particular y después de que (los desarrolladores de JAVA) se actualizaron a la próxima versión de lanzamiento, este problema simplemente desapareció. Desearía poder brindarte más detalles, pero en ese momento, había suficientes problemas para abordar desde el final del cable y me alegré de tener un elemento menos en el registro de defectos.

//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>

WCF utiliza http://tempuri/1/number para las referencias uri Content-ID cuando se manejan las solicitudes MTOM transmitidas.

¿Hay alguna manera de forzar a WCF a usar referencias de Content-ID diferentes para el xop: Include?

Antecedentes del problema:

Estoy construyendo un cliente .NET para el servicio web jax ws java habilitado para MTOM que maneja cargas grandes de datos transmitidos. He creado a mano el servicio y los contactos de datos (los contratos generados por WSDL no eran correctos y no permitían la transmisión).

El problema es que el servicio web (jax ws) no recibe el cuerpo de la solicitud que contiene los datos.

Recibe los datos que se transfieren en los encabezados.

Hemos construido un cliente Java para el ws, este funciona.

He capturado y comparado el tráfico HTTP al emitir solicitudes desde java y wcf, y la única diferencia está en cómo se genera la referencia Content-ID cuando se publican los datos multiparte:

  • WCF utiliza http://tempuri/1/... referencias Content-ID que arrojan en valor codificado, como href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928"

  • El cliente de Java usa uris "de estilo de correo electrónico", como href="cid:[email protected]"

Estos rinden en las siguientes xop-includes (los datos son el único elemento en el cuerpo del jabón) ( XOP incluye la especificación )

//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>

más adelante, en los datos multiparte, el contenido se denomina Content-ID no codificado:

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

Supongo que puede haber un error en el marco del servicio web jax y no reconoce las referencias uri codificadas url-codificadas + WCF-generated.

¿Hay alguna manera de forzar a WCF a usar referencias de Content-ID diferentes para el xop: Include?

EDITAR: He encontrado el XmlMtomWriter que tiene el método GenerateUriForMimePart, esto se usa para generar Content-IDs.

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

No parece que la generación de ID sea de ninguna manera invalidable.

Aquí se describe un problema similar, la respuesta proporcionada no ayuda: http://social.msdn.microsoft.com/Forums/en/wcf/thread/f90affbd-f431-4602-a81d-cc66c049e351


Asnwering a mí mismo después de una larga investigación: No es posible sin volver a implementar todo el XmlMtomWriter y otras capas relacionadas y preocupaciones en WCF: casi todo lo que está involucrado en la implementación de mtom es interno.


Sé que es una vieja pregunta. Pero me enfrenté al mismo problema hace dos días.

Encontré una manera que funciona PERO es un truco MUY MUY sucio (lo sé. Pensé en no publicarlo aquí, pero tal vez ayudaría a alguien.) Espero que no me culpes por eso.

ContentId está formateado con el uso de CultureInfo.InvariantCulture. No encontré una forma oficial de reemplazarlo con un CultureInfo personalizado. Pero con la ayuda de la reflexión, lo puse en marcha. La siguiente implementación es solo para .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); } }

Hago posible mi propia "InvariantCulture" solo antes de una llamada a WCF.

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

CultureInfo.InvariantCulture es un objeto de estado global. La habilitación de mi propia InvariantCulture afecta a todos los demás hilos. Nuevamente, es un hack sucio. Pero funciona.