Как отправить SOAP-запрос и получить ответ в C#

Как отправить SOAP-запрос и получить ответ в C#
Тестируя различные API с помощь SoapUI, мы решили, что хотим иметь гибкие и настраиваемые под нас тесты. Для этого мы решили тестировать API не через SoapUI, а писать автоматизированные тесты на C#. Теперь рассмотрим, как отправлять SOAP-запросы и получать ответы в C# и при этом используя минимальное количество строк кода и без подключений «WSDL» к проекту. Про REST API и C# я, возможно, напишу статью позже.

В данной статье будет указан несуществующий API, поэтому не стоит пытаться его проверять.

Допустим у нас есть сервис, у которого есть API, и он доступен по адресу:

https://victorz.ru/soapapi/Transport

У данного сервиса есть ряд методов и один из них «GetInfo», который позволяет запрашивать информацию по транспортному средству передавая идентификатор транспортного средства.

Создаём в C# новый проект. Я создал проект с типом Windows Form. В проект подключим:

using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Windows.Forms;

Создадим метод C#, который будет запрашивать информацию и возвращать ответ сервиса:

/// <summary> Метод отправки запроса к SOAP сервису и получения от него ответа </summary>
/// <param name="_url">URL SOAP API-сервиса</param>
/// <param name="_method">Метод, который вызывается на API сервисе</param>
/// <param name="_soapEnvelope">SOAP-конверт (запрос), который будет отправлен к API</param>
/// <returns>Метод возвращает ответ SOAP сервиса в виде XML</returns>
private string GetResponseSoap(string _url, string _method, string _soapEnvelope)
{
	_url = _url.Trim('/').Trim('\\'); // в конце адреса удалить слэш, если он имеется
	WebRequest _request = HttpWebRequest.Create(_url);
	//все эти настройки можно взять со страницы описания веб-сервиса
	_request.Method = "POST";
	_request.ContentType = "text/xml; charset=utf-8";
	_request.ContentLength = _soapEnvelope.Length;
	_request.Headers.Add("SOAPAction", _url + @"/" + _method);
	// пишем тело
	StreamWriter _streamWriter = new StreamWriter(_request.GetRequestStream());
	_streamWriter.Write(_soapEnvelope);
	_streamWriter.Close();
	// читаем тело
	WebResponse _response = _request.GetResponse();
	StreamReader _streamReader = new StreamReader(_response.GetResponseStream());
	string _result = _streamReader.ReadToEnd(); // переменная в которую пишется результат (ответ) сервиса
	return _result;
}

Описывать подробно метод не будем, так как в комментариях достаточно информации.

Далее нам надо вызвать с помощью данного методы сервис и получить от него ответ. К примеру, при нажатии на кнопку «button1» мы выведем ответ сервиса в текстовом поле «textBox1»:

private void button1_Click(object sender, EventArgs e)
{
	textBox1.Text = ""; // очищаем текстовое поле
	string _url = @"https://victorz.ru/api/Transport"; // URL SOAP API-сервиса
	string _method = @"GetInfo​"; // Метод, который вызывается на API сервисе
	string _soapEnvelope = File.ReadAllText(@"С:\GetInfo​.xml"); // SOAP-конверт (запрос), который будет отправлен к API
	string _response = GetResponseSoap(_url, _method, _soapEnvelope); // получаем ответ SOAP сервиса в виде XML
	textBox1.Text = _response; // выводим данные в текстовое поле
}

В строке 7 кода вызывается метод и результат пишется в переменную.

Некоторые отправляемый запрос предпочитают указывать в коде. Я делаю код максимально независимым, поэтому у меня в методе считываются данные из файла «GetInfo.xml» (строка 6 кода).
Что из себя представляет данный файл? Это SOAP-конверт, который надо отправить сервису, чтобы получить от него ответ. В нашем случае, если я бы открыл «GetInfo.xml», то в нём мы бы увидели следующее:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices.victorz.ru/">
   <soapenv:Header/>
   <soapenv:Body>
      <web:Transport>
         <NumID>975764</NumID>
      </web:Transport>
   </soapenv:Body>
</soapenv:Envelope>

Что надо отправить вам в адрес вашего сервиса вы должны знать и сохранить эти данные в аналогичном XML-файле.

Отправив запрос сервису, мы получим от него ответ и выведем в текстовое поле:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns2:TransportResponse xmlns:ns2="http://webservices.victorz.ru/" xmlns:ns3="data.shemas.victorz.ru">
        <TransportName>Газель</TransportName>
		<TransportNumber>р999вд</TransportNumber>
		<TransportRegion>77</TransportRegion>
      </ns2:TransportResponse>
   </S:Body>
</S:Envelope>

Далее нам остаётся только распарсить XML ответ и получить требуемые данные из XML.

Как видим всё достаточно просто. У нас SOAP API внутренний и не использует авторизацию, поэтому запрос отправляется без авторизации. Если у вас сервис с авторизацией, то в комментариях можете сообщить читателям, как отправлять данные с авторизацией.

5 комментариев

  1. хорошо я согласен

    У меня возникает ошибка в строке

    _request.Headers.Add("SOAPAction", _url + @"/" + _method);
    argumentException.

    Дальше выполнять не хочет.

    • Захаров Виктор

      Запускайте в дебаге и смотрите, что у вас происходит. Используйте контрольные точки остановки, чтобы на разных этапах понять что и где передаётся/присваивается.

  2. Магарам

    Привет! Использую данную идею для реализации в дипломной работе. Не могли бы мне помочь разобраться:

    • Захаров Виктор

      Дипломами не занимаюсь. Попросите ребят на спец. формумах.

  3. Магарам

    Тот же метод
    _request.Headers.Add("SOAPAction", _url + @"/" + _method);
    argumentException.

    Указанное значение содержит недопустимые знаки управления.
    Изначально это исключение было создано в этом стеке вызовов:
    [Внешний код]
    Diploma.Form1.GetResponseSoap(string, string, string) в Form1.cs
    Diploma.Form1.button1_Click(object, System.EventArgs) в Form1.cs
    [Внешний код]
    Diploma.Program.Main() в Program.cs

Добавить комментарий

Ваш адрес email не будет опубликован.