Я ударял по голове стены в течение двух дней с этим так, надо надеяться, кто-то может дать мне руку. То, что я имею, является УСПОКОИТЕЛЬНЫМ веб-сервисом, что я записал использованию WCF; ничто к нему действительно всего два метода, которые принимают отдельный строковый параметр и также возвращают строку. И значение параметра и возвращаемое значение являются прямым XML.
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(UriTemplate = "/method1/{data}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
string Method1(string data);
[OperationContract]
[WebGet(UriTemplate = "/method2/{data}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
string Method2(string data);
}
Ради аргумента позволяет, говорят, что реализация обоих из этих методов похожа на это:
public string Method1(string data)
{
return string.Format("You entered: {0}", data);
}
Если я goto http://myuri.com/service.svc/method1/foo следующее, записал в браузер:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">You
entered: foo</string>
Это работает отлично, но если я изменяю URL на: http://myuri.com/service.svc/method1 / <нечто> я получаю 400 (Плохой Запрос). Таким образом, я позволил некоторым трассировщикам видеть то, что шло с помощью следующего кода:
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\Traces.svclog" />
</listeners>
</source>
</sources>
Поскольку Вы видите, что я использую значение переключателя 'Все' для получения каждого события, которое происходит во время казни этого сервиса. Я отбежал посредством несколько раз использования Формата ссылки, который работает, чтобы проверить, что трассировщики работали, и они были. Я затем перешел к URL, который содержал нечто XML-тэга и получил 400 ошибок как ожидалось, но когда я вернулся к файлу журнала не было никакой дополнительной информации appened в конец его. Это приводит меня полагать, что 400 ошибок отображаются, прежде чем сервис WCF когда-либо вызывается.
Наконец, я переключился, методы от 'ПОЛУЧАЮТ' методы к методам 'POST', записал небольшому количеству использования кода WebRequest / WebResponse с тем же результатом. Теперь я прочитал некоторые сообщения, говорящие об использовании XmlSerializer на стороне клиента, чтобы отправить данные службе, но это побеждает цель этого сервиса. В то время как я использую.NET для записи сервиса, вероятно, что PHP или классические сценарии ASP будут соединяться с этим сервисом, и у них, очевидно, нет доступа к XmlSerializer.
Таким образом, мой самый трудный вопрос - это: действительно ли возможно отправить 'необработанный' запрос XML к УСПОКОИТЕЛЬНОМУ веб-сервису, разработанному в WCF и, если так, как?
P.S. вход XML и выход из сервиса не основаны ни на каком материальном объекте, это - просто структура, которую я создал для использования с этим сервисом. Входящий XML анализируется через XPath, значения помещаются в большую строку XML и передаются внешнему API. Результаты, что API обрабатывается и затем возвращается моим УСПОКОИТЕЛЬНЫМ сервисом.
Любая справка значительно ценилась бы!!
Бретт, спасибо за код. К сожалению, я нашел его в этом потоке: WCF Rest parameters including complex types и пытался это сделать до этого постинга.
В любом случае, я решил эту проблему. Сейчас я хотел бы сказать, что у меня был полный момент "Эврики" и все просто сложилось, но дело в том, что я только начал бросать акронимы в Google и одна из SERP-ов привела меня по этой ссылке: http://blogs.msdn.com/pedram/archive/2008/04/21/how-to-consume-rest-services-with-wcf.aspx
Ссылка сама по себе не является непосредственным ответом на рассматриваемый вопрос, но она заставила меня по-другому подумать о том, как я собирал свои шаблоны URI. Я прочитал эту MSDN статью http://msdn.microsoft.com/en-us/library/dd203052.aspx о том, как составлять RESTful сервис. В примере автор предоставляет несколько различных шаблоновL некоторые из которых используют типичный шаблон Querystring parameter-esque, а некоторые нет. По какой-то причине я выбираю шаблон, который не имеет типичного параметра querystring, как видно из моей первоначальной заметки. Поэтому я немного изменил свой код и придумал следующее:
[OperationContract]
[WebGet(UriTemplate = "/method1/?xml={data}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
string Method2(string data);
Обратите внимание, что шаблон URI - единственное, что изменилось; изменение с "/method1/{data}" на "/method1/?xml={data}. Затем я перешел на http://myuri.com/service.svc/method1/?xml= и альт, все сработало прекрасно!
Это тоже было проблемой с POST. По какой бы то ни было причине передача XML в тело контента, даже в виде пары ключ/значение, приводила к ошибке 400. Используя точно такой же шаблон URI, показанный выше, я открыл Fiddler, выполнил POST, и результат был 200 OK.
Спасибо всем за помощь.
Я не верю, что вы сможете передать сырой XML в URL, но вы можете сделать это в коде. Я написал клиентов для RESTful веб-сервисов, которые работают на Compact Framework и не имеют проблем с десериализацией объектов на сырой XML и отправкой его в службу через HttpWebRequest и HttpWebResponse.
Если вы делаете GET, вы просто создаете URL в коде. Если вы делаете POST, вы можете прикрепить XML в виде массива байтов (код ниже .Net, но, конечно, вы можете сделать что-нибудь подобное в PHP).
private HttpWebRequest DoInvokeRequest<T>(string uri, string method, T requestBody)
{
string destinationUrl = _baseUrl + uri;
var invokeRequest = WebRequest.Create(destinationUrl) as HttpWebRequest;
if (invokeRequest == null)
return null;
invokeRequest.Method = method;
invokeRequest.ContentType = "text/xml";
byte[] requestBodyBytes = ToByteArray(requestBody);
invokeRequest.ContentLength = requestBodyBytes.Length;
AddRequestHeaders(invokeRequest);
using (Stream postStream = invokeRequest.GetRequestStream())
postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
invokeRequest.Timeout = 60000;
return invokeRequest;
}
private static byte[] ToByteArray<T>(T requestBody)
{
byte[] bytes;
using (var s = new MemoryStream())
{
var serializer = new XmlSerializer(typeof (T));
serializer.Serialize(s, requestBody);
bytes = s.ToArray();
}
return bytes;
}
Как вы их высмеиваете пользователей?
Инициализируют django.contrib.auth.models.user
объект. user.Objects.create_user
делает это легко.
Как вы запрашиваете запросы?
Инициализируют django.http.httprequest
объект.
Конечно, есть ярлыки в зависимости от того, что вы хотите сделать. Если вам просто нужен объект с атрибутом
, который указывает на пользователя, просто создайте что-нибудь (что-нибудь) и дайте ему этот атрибут.
Одной из основных причин, по которым исходный код не работал, был, потому что какие-либо строковые данные XML должны быть закодированы URL, если их передан в пути URL или строка запроса.
Однако, однако, если вы хотите, чтобы клиент отправил вам данные как XML в вашем методе обслуживания, то он должен быть выполнен . URL имеет неопределенную максимальную длину, в зависимости от браузера, версии IIS, а также любых веб-прокси, которые сидят между клиентом на сервере.
Это означает отправку данных в тело запроса, что означает глагол, отличный от получения. Так что давайте будем использовать пост.
Объявите параметр «Данные» как до подписи метода, но возьмите параметр из мочи и сделайте его WebInvoke (Verb по умолчанию - это сообщение, как вы знаете).
[WebInvoke(UriTemplate = "/method1", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Xml)]
string Method2(string data);
Тогда ваш почтовый корпус должен быть отформатирован следующим образом:
<data><![CDATA[data xml goes in here]]></data>
Почему раздел CDATA? Подумайте о типе целевого параметра - String. Вы хотите пройти XML в этой строке. Следовательно, вам необходимо убедиться, что сериализатор WCF не думает о данных как сложных данных, которые следует читать напрямую. То же самое было бы правдой, если ваш формат запроса был JSON, и вы хотите отправить json String на службу.
По моему мнению, услуги WCF, предоставляющие RESTful API, не допускают большой полезной нагрузки. На самом деле, по умолчанию службы WCF предназначены для отправки небольших сообщений туда и обратно.
На машине, которую я тестировал, я не смог получить обратно полезную нагрузку в формате XML (XML-файл) от службы WCF, открытую через веб-конечную точку REST-ful, которая была больше, чем 2,7 МБ .
Из раскопок и охоты через LOTS документации WCF я пришел к окончательному выводу, что WCF предназначен для небольших сообщений, когда в режиме буферизации . При переключении в режим потокового большие сообщения могут передаваться туда и обратно.
Однако, если вы подвергаете службы WCF через IIS в режиме RESTful, то вы не сможете получить потоковый ответ, так как это не поддерживается. Или, по крайней мере, я никогда не смогу это выяснить.
Хотел бы я иметь для вас отличный образец кода, но из того, что я смог обнаружить в результате собственных экспериментов, было то, что не существует способа вернуть большую полезную нагрузку в формате XML из службы WCF, открытую через конечную точку IIS .
Мой вывод заключается в том, что WCF - это действительно сетевое решение, которое переоснащается (плохо) в IIS, чтобы попытаться предоставить веб-сервисы. Я бы рекомендовал использовать ASP .NET MVC вместо этого для создания RESTful webservices без использования WCF вообще.