Обработка запроса веб-сервисом

Коллеги, добрый вечер!

Работаю с внешней системой, которая шлет запросы в указанном формате:

curl --location --request POST 'http://localhost/0/ServiceModel/BsoCaller.svc/DoWork' \
--header 'Content-Type: application/xml' \
--data-raw '<?xml version="1.0" encoding="UTF-8"?>
<Event>
</Event>'

Написал анонимный веб-сервис на подобие:

namespace Terrasoft.Configuration.MyNamespace
{
	using System;
	using System.IO;
	using System.Linq;
	using System.Runtime.Serialization;
	using System.Text;
	using System.ServiceModel;
	using System.ServiceModel.Activation;
	using System.ServiceModel.Web;
	using System.Web;
	using System.Xml.XPath;
	using System.Xml.Linq;
	using System.Reflection;
	using Terrasoft.Core;
	using Terrasoft.Common;
	using Terrasoft.Core.Entities;
	using Terrasoft.Web.Common;
 
	[ServiceContract]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	public class BsoCaller: BaseService 
	{
		[OperationContract]
		[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)]
		public void DoWork()
		{
			var xml = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
		}
	}
}

Пробую отправить запрос через postman в виде xml - получаю Bad Request.

Если выбираю Text - запрос отрабатывает.

Кто-нибудь сталкивался? Где допускаю ошибку?

Спасибо!

Нравится

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

Добрый день! 

Первое что бросается в глаза это запрос:

curl --location --request POST 'http://localhost/0/ServiceModel/BsoCaller.svc/DoWorkhttp://localhost/0/…'

Это опечатка в данном посте или на самом деле такая адресная строка?

Руслан Хасанов,

Руслан, добрый день.

Это опечатка в данном посте) Поправил.

Я думаю что адресная строка должна быть примерно такой

http://localhost/0/ServiceModel/MyService/Handler

К тому же метод Handler должен возвращать результат работы, чтобы было что то видно.

Руслан Хасанов,

Руслан, извиняюсь. Подправил названия в веб-сервисе, чтобы было понятнее. Писал просто в торопях в кач-ве примера.

Суть в том, что если я оборачиваю тело в постмане в Text - все отрабатывает. С Xml же какая-то беда.

Хорошо, теперь ближе к правде. Не понятно, конечно, почему такое поведение с Text. Ваш метод DoWork ни чего не возвращает (void).  Я думаю что он должен делать:

return "some text result, for example";

а если конкретно в вашем случае, то return xml; 

И сигнатуру метода надо изменить на public string DoWork.....

Руслан Хасанов,

Руслан, дело в том, что в методе на самом деле не одна строка. Просто сюда решил не скидывать весь код, т.к. уже на этапе инициализации переменной xml возникает проблема.

Дальнейшая логика в методе парсит содержимое переменной xml и создается запись в разделе. И все это работает если слать через Text.

Методу не обязательно что-то возвращать. Если переделать под ваш вариант - к сожалению ничего не поменяется. Все тот же Status: 400 Bad Request в постмане.

Подозреваю что проблема в параметрах, что над методом. Но уже по моему все перепробовал.

Александр, а что именно за Bad Request? Там же в ответе должна быть более подробная информация о причине. Если при этом самодельный веб-сервис упал с ошибкой, её стек должен быть в логах сайта.

Зверев Александр,

Александр, вот что пишет:

The server encountered an error processing the request. The exception message is 'Error in line 2 position 145. Expecting element 'base64Binary' from namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.. Encountered 'Element' with name 'Event', namespace 'http://schema.broadsoft.com/xsi'. '. See server logs for more details. The exception stack trace is:
 
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader) at System.ServiceModel.Channels.Message.GetBodyCore[T](XmlDictionaryReader reader, XmlObjectSerializer serializer) at Terrasoft.Configuration.BsoCesolutions.UsrNewCallHandler.WebhookHandler() at SyncInvokeWebhookHandler(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp; outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Подаю в постмане такое тело в xml:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsi:Event xsi1:type="xsi:SubscriptionEvent" xmlns:xsi="http://schema.broadsoft.com/xsi" xmlns:xsi1="http://www.w3.org/2001/XMLSchema-instance"&gt;
    &lt;xsi:eventData xsi1:type="xsi:CallReleasedEvent"&gt;
        &lt;xsi:call&gt;
            &lt;xsi:callId&gt;2222222222222222&lt;/xsi:callId&gt;
            &lt;xsi:extTrackingId&gt;222222222222&lt;/xsi:extTrackingId&gt;
            &lt;xsi:networkCallId&gt;2222222222222222&lt;/xsi:networkCallId&gt;
            &lt;xsi:startTime&gt;2222222222222&lt;/xsi:startTime&gt;
            &lt;xsi:answerTime&gt;22222222222222&lt;/xsi:answerTime&gt;
            &lt;xsi:releaseTime&gt;2222222222222&lt;/xsi:releaseTime&gt;
        &lt;/xsi:call&gt;
    &lt;/xsi:eventData&gt;
&lt;/xsi:Event&gt;

Решил переписать немного метод:

[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)]
public string DoWork()
{	
    using (var reader = OperationContext.Current.RequestContext.RequestMessage.GetReaderAtBodyContents())
    {
        return reader.ReadOuterXml();
    }
}

Теперь ошибки нету, но получаю такое тело в постмане:

&lt;string xmlns="http://schemas.microsoft.com/2003/10/Serialization/"/&gt;

А нужно получить по сути тоже самое, что подал. Просто в виде строки.

Вот аналогичный случай, но, смотрю, Вы совет оттуда уже попробовали. Там ещё советуют приводить сразу к нужному типу класса с такими полями.

 

И Вы уверены, что в ответе ReadOuterXml не требуемая строка? Может, теряется уже на обратном пути. Попробуйте для теста писать значение куда-то в базу.

Зверев Александр,

Боюсь привести к нужному типу сразу такой запрос затруднительно.

Еще как выяснилось если писать в базу - строка вообще пустая)

Не сильно теперь понимаю почему постман вообще что-то возвращает.

Пробовал так же пройтись по всем методам из XmlDictionaryReader, но ничего подходящего не нашел.

Александр Горчаков пишет:

Не сильно теперь понимаю почему постман вообще что-то возвращает.

Так это, наверное, пустую строку так сериализировало.

 

 

Зверев Александр,

Да, уже убедился.

Вообщем пока все еще не понятно как нормально отлавливать xml post-запросы в wcf..

Вообще, в системе куча примеров сервисов, но все на Json.

 

А с WebMessageBodyStyle.Bare точно всё правильно? Смотрю тут примеры, Ваш запрос больше на WebMessageBodyStyle.Wrapped похож.

Зверев Александр,

Wrapped пробовал для обоих методов. Результаты аналогичные.

Попробуйте ещё советы из этой темы, в частности, создать сервис для теста сначала не в 7.Х, а в отдельной своей программе и проверить, всё ли нормально в конфиге.

Показать все комментарии