Коллеги, добрый вечер!
Работаю с внешней системой, которая шлет запросы в указанном формате:
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 - запрос отрабатывает.
Кто-нибудь сталкивался? Где допускаю ошибку?
Спасибо!
Нравится
Добрый день!
Первое что бросается в глаза это запрос:
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[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
Подаю в постмане такое тело в xml:
<?xml version="1.0" encoding="UTF-8"?> <xsi:Event xsi1:type="xsi:SubscriptionEvent" xmlns:xsi="http://schema.broadsoft.com/xsi" xmlns:xsi1="http://www.w3.org/2001/XMLSchema-instance"> <xsi:eventData xsi1:type="xsi:CallReleasedEvent"> <xsi:call> <xsi:callId>2222222222222222</xsi:callId> <xsi:extTrackingId>222222222222</xsi:extTrackingId> <xsi:networkCallId>2222222222222222</xsi:networkCallId> <xsi:startTime>2222222222222</xsi:startTime> <xsi:answerTime>22222222222222</xsi:answerTime> <xsi:releaseTime>2222222222222</xsi:releaseTime> </xsi:call> </xsi:eventData> </xsi:Event>
Решил переписать немного метод:
[OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)] public string DoWork() { using (var reader = OperationContext.Current.RequestContext.RequestMessage.GetReaderAtBodyContents()) { return reader.ReadOuterXml(); } }
Теперь ошибки нету, но получаю такое тело в постмане:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/"/>
А нужно получить по сути тоже самое, что подал. Просто в виде строки.
Вот аналогичный случай, но, смотрю, Вы совет оттуда уже попробовали. Там ещё советуют приводить сразу к нужному типу класса с такими полями.
И Вы уверены, что в ответе ReadOuterXml не требуемая строка? Может, теряется уже на обратном пути. Попробуйте для теста писать значение куда-то в базу.
Зверев Александр,
Боюсь привести к нужному типу сразу такой запрос затруднительно.
Еще как выяснилось если писать в базу - строка вообще пустая)
Не сильно теперь понимаю почему постман вообще что-то возвращает.
Пробовал так же пройтись по всем методам из XmlDictionaryReader, но ничего подходящего не нашел.
Александр Горчаков пишет:
Не сильно теперь понимаю почему постман вообще что-то возвращает.
Так это, наверное, пустую строку так сериализировало.
Зверев Александр,
Да, уже убедился.
Вообщем пока все еще не понятно как нормально отлавливать xml post-запросы в wcf..
Вообще, в системе куча примеров сервисов, но все на Json.
А с WebMessageBodyStyle.Bare точно всё правильно? Смотрю тут примеры, Ваш запрос больше на WebMessageBodyStyle.Wrapped похож.
Зверев Александр,
Wrapped пробовал для обоих методов. Результаты аналогичные.
Попробуйте ещё советы из этой темы, в частности, создать сервис для теста сначала не в 7.Х, а в отдельной своей программе и проверить, всё ли нормально в конфиге.