WCF: (MTOM) есть ли способ изменить схему, используемую в xop: Ссылка на содержимое UIS, сгенерированная WCF? - PullRequest
10 голосов
/ 17 февраля 2010

WCF использует http://tempuri/1/number для ссылок URI Content-ID при обработке потоковых запросов MTOM.

Есть ли способ заставить WCF использовать другие ссылки Content-ID для xop: Include?

Предыстория проблемы:

Я создаю .NET-клиент для MTOM-совместимого веб-сервиса jax ws java, который обрабатывает потоковые загрузки больших объемов данных. Я вручную создал контакты службы и данных (сгенерированные 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-клиент использует uris "в стиле электронной почты", например href="cid:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"

Этот выход в следующем xop-include (данные является единственным элементом в теле мыла) ( 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, и она не распознает сгенерированные WCF + кодированные ссылки URI Content-ID.

Есть ли способ заставить 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

Ответы [ 3 ]

1 голос
/ 18 января 2013

Я знаю, что это старый вопрос. Но я столкнулся с той же проблемой два дня назад.

Я нашел способ, который работает, НО это ОЧЕНЬ ОЧЕНЬ грязный хак (я знаю это. Я думал о том, чтобы не публиковать его здесь, но, возможно, это кому-нибудь поможет.) Надеюсь, вы меня за это не обвините.

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 влияет на все остальные потоки. Опять же, это грязный хак. Но это работает.

1 голос
/ 22 февраля 2010

Ответ на вопрос после долгого исследования: невозможно без переопределения всего XmlMtomWriter и других связанных уровней и проблем в WCF - почти все, что связано с реализацией mtom, является внутренним.

0 голосов
/ 30 октября 2011

Оба 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>
...