Есть ли лучший способ настройки заголовков SOAP в C # - PullRequest
1 голос
/ 01 декабря 2008

Раньше мне приходилось создавать пользовательские заголовки SOAP в проекте C #, в котором использовалась импортированная веб-ссылка WSDL. Я нашел способ сделать это, но я никогда не был доволен этим, и у меня возникло сомнение, есть ли лучший способ. Что я сделал, так это создал заголовок, производный от SoapHeader:

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://model.test.net")]
[System.Xml.Serialization.XmlRootAttribute("securitytoken", Namespace = "http://model.test.net", IsNullable = false)]
public class SpecialHeader : SoapHeader
{ 
  [System.Xml.Serialization.XmlTextAttribute()]
  public string aheadervalue;
}

Затем мне пришлось изменить код, сгенерированный из WSDL, и добавить ссылку до экземпляра нового заголовка и следующего перед каждым веб-вызовом, который Я хотел содержать пользовательский заголовок:

[System.Web.Services.Protocols.SoapHeaderAttribute("instancename", Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut)]

Где "instancename" - это имя переменной экземпляра пользовательского заголовка в сгенерированном классе.

Это прекрасно работает, за исключением того, что любое изменение в WSDL требует, чтобы все это было сделано заново, поскольку оно восстанавливает класс. В других языках заголовки могут быть добавлены за пределы сгенерированного кода, поэтому, возможно, мне не хватает способа, который делается в C #. Есть ли лучшие способы сделать это?

Ответы [ 4 ]

3 голосов
/ 17 декабря 2008

Похоже, вы используете .Net 2.0 и asmx webservices. Знаете ли вы, что в .Net 3.0 есть фреймворк под названием WCF (Windows Communication Framework). Я знаю, что нелегко перейти на новый фреймворк, но с WCF вы получаете так много. Кроме того, WCf может использоваться гораздо больше, чем веб-сервисы (удаленное взаимодействие, msmq и многое другое). Это основа, на которую Microsoft делает ставку на будущее. То есть. манипулирование мыльным заголовком выполняется с помощью MessageContracts.

Итак, ответ таков: в WCF вы можете сделать это с помощью MessageContracts.

2 голосов
/ 30 июня 2011

Поскольку сгенерированный класс является частичным классом. Вы можете определить его в другом файле с тем же пространством имен и именем класса (опять же частичный класс). Затем вы можете переопределить его виртуальные методы и определить его один раз.

Это предотвращает дальнейшие изменения в восстановленном классе и не влияет на тот, который вы написали.

В новом файле класса вы можете использовать «GetWriterForMessage» для переопределения и добавления в него новых заголовков SOAP.

public partial class SampleService
{
    public string MessageID { get; set; }

    protected override System.Xml.XmlWriter GetWriterForMessage(System.Web.Services.Protocols.SoapClientMessage message, int bufferSize)
    {
        message.Headers.Add(new UsernameSoapHeader("Username"));
        message.Headers.Add(new PasswordSoapHeader("Password"));
        message.Headers.Add(new MessageIDSoapHeader(MessageID));
        return base.GetWriterForMessage(message, bufferSize);
    }
}
0 голосов
/ 13 апреля 2010

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

0 голосов
/ 02 декабря 2008

Есть способ сделать это, вроде; это не обязательно красиво, и на очень простом веб-сервисе это может не стоить усилий, но, по крайней мере, избавляет вас от необходимости повторно добавлять атрибуты при регенерации кода.

Поскольку генератор генерирует частичные классы, вы можете:

  1. Добавьте в свой проект файл, который расширяет класс веб-службы (тот, который получен из SoapHttpClientProtocol) с другим «частичным» разделом (т. Е. Используйте то же пространство имен и имя, что и сгенерированный класс, и отметьте его как «частичный» «).

  2. Скопируйте методы, к которым вы хотите добавить заголовки (т. Е. Те же методы, к которым вы уже добавляли атрибуты), из сгенерированного кода и вставьте их в раздел расширения.

  3. Переименуйте методы слегка, чтобы они не конфликтовали с методами в сгенерированном коде, и измените имена, которые передаются Invoke, для соответствия. (Возможно, вам также придется настроить другие атрибуты в методах, чтобы убедиться, что они по-прежнему отображаются на соответствующие вызовы в WSDL.)

  4. Добавьте пользовательский атрибут заголовка в переименованные методы, а также поле экземпляра заголовка в раздел расширения.

  5. Вызывайте переименованные версии из своего кода вместо исходных версий.

Пока сигнатуры методов не меняются в WSDL, вам не придется ничего менять в коде, даже если вы перегенерируете. (Поскольку вы копируете только относительно короткие реализации методов, любые другие структуры из WSDL по-прежнему будут выходить из сгенерированного кода, поэтому, если они изменятся, вы автоматически получите обновленные версии при регенерации. Конечно, если WSDL этого не делает есть какие-то другие структуры, полезность этого, вероятно, несколько ограничена.)

Это все еще не идеально, но если не пытаться перехватить необработанное сообщение XML и вставить заголовок напрямую (что вы, вероятно, могли бы сделать, но это было бы неприятно), на самом деле я не знаю других вариантов, о которых я знаю (не переходя в WCF в любом случае).

...