ВКФ:(MTOM) есть ли способ изменить схему, используемую в xop: Content Reference Uris, созданном WCF?
Вопрос
WCF использует http://tempuri/1/number
для ссылок Content-ID uri при обработке потоковых запросов MTOM.
Есть ли способ заставить WCF использовать разные ссылки Content-ID для xop:Include?
Предыстория проблемы:
Я создаю клиент .NET для веб-службы java с поддержкой MTOM jax ws, которая обрабатывает потоковую загрузку больших данных.Я вручную создал контакты службы и данных (сгенерированные WSDL контракты были неправильными и не позволяли осуществлять потоковую передачу).
Проблема в том, что веб-сервис (jax ws) не получает тело запроса, содержащее данные.
Он получает данные, которые передаются в заголовках.
Мы создали Java-клиент для ws — он работает.
Я захватил и сравнил HTTP-трафик при отправке запросов из Java и WCF, и единственная разница заключается в том, как генерируется ссылка Content-ID при публикации составных данных:
WCF использует
http://tempuri/1/...
Ссылки Content-ID, которые возвращают закодированное значение, напримерhref="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928"
Клиент Java использует URI в стиле электронной почты, например
href="cid:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"
Они дают следующие xop-includes (Данные — единственный элемент в теле мыла) (XOP включает спецификацию)
//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:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"/>
</Data>
позже, в составных данных, на контент ссылается незакодированный 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
Я думаю, там может Это ошибка в структуре веб-службы jax, и она не распознает ссылки Content-ID, сгенерированные + urlencoded.
Есть ли способ заставить WCF использовать разные ссылки Content-ID для xop:Include?
РЕДАКТИРОВАТЬ:Я нашел XmlMtomWriter, у которого есть метод GenerateUriForMimePart, который используется для генерации идентификаторов контента.
public static string GenerateUriForMimePart(int index)
{
return string.Format(CultureInfo.InvariantCulture,
"http://tempuri.org/{0}/{1}", new object[] { index, DateTime.Now.Ticks });
}
Не похоже, что генерацию идентификатора можно каким-либо образом переопределить.
Аналогичная проблема описана здесь, предоставленный ответ не помогает: http://social.msdn.microsoft.com/Forums/en/wcf/thread/f90affbd-f431-4602-a81d-cc66c049e351
Решение
Отвечаю себе после долгого расследования:Невозможно без переопределить весь XmlMtomWriter и другие связанные уровни и проблемы в WCF — почти все, что связано с реализацией mtom, является внутренним.
Другие советы
Я знаю, что это старый вопрос.Но я столкнулся с той же проблемой два дня назад.
Я нашел способ, который работает, НО это ОЧЕНЬ ОЧЕНЬ грязный хак (я это знаю.Я думал не публиковать это здесь, но, возможно, это кому-то поможет.) Надеюсь, вы не будете меня за это винить.
ContentId форматируется с использованием CultureInfo.InvariantCulture.Я не нашел официального способа заменить его пользовательской CultureInfo.Но с помощью размышлений мне это удалось.Следующая реализация предназначена только для .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);
}
}
Я включаю свою собственную «InvariantCulture» только перед вызовом WCF.
NoTempUriInvariantCultureInfo.Enable();
try
{
// make your call
}
finally
{
NoTempUriInvariantCultureInfo.Disable();
}
CultureInfo.InvariantCulture — это глобальный объект состояния.Включение моего собственного InvariantCulture влияет на все остальные потоки.Опять же, это грязный хак.Но это работает.
Оба XOP включают образцы, которые вы указали как правильные и приемлемые в соответствии с W3C.Я называю их форматом URL-адреса и форматом электронной почты соответственно.
Я не JAVA-разработчик, но помню аналогичную проблему при взаимодействии с определенным веб-сервисом JAVA.Я помню, что в определенном выпуске JAVA была ошибка, и после того, как они (разработчики JAVA) обновились до следующей версии, эта проблема просто исчезла.Мне бы хотелось предоставить вам более подробную информацию, но в то время у меня было достаточно проблем, которые мне приходилось решать с моего конца провода, и я был просто рад, что в журнале дефектов на одну позицию меньше.
//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:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"/>
</Data>