Вопрос:
Существуют ли какие-либо средства (возможно, временное решение) для поддержки HTTP-команд PUT и DELETE с помощью службы REST WCF 4.0, защищенной с помощью OAuth 2.0 и DotNetOpenAuth 4? Я не использую веб-API WCF или начальный комплект WCF.
Что я сделал до сих пор:
Рассмотрим следующую службу REST WCF 4.0:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService
{
[WebGet(UriTemplate = "")]
public List<Resource> GetCollection()
{
/* some implementation */
}
[WebInvoke(UriTemplate = "", Method = "POST")]
public Resource Create(Resource instance)
{
/* some implementation */
}
[WebGet(UriTemplate = "{id}")]
public Resource Get(string id)
{
/* some implementation */
}
[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
public Resource Update(string id, Resource instance)
{
/* some implementation */
}
[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
public void Delete(string id)
{
/* some implementation */
}
}
OAuth 2.0 используется для управления доступом к услуге. Это достигается с помощью пользовательской реализации ServiceAuthorizationManager, использующей DotNetOpenAuth для выполнения всей работы. Реализация практически идентична реализации, предоставленной образцами DotNetOpenAuth 4.0.
Для запросов POST и GET это прекрасно работает. Однако запросы не выполняются для запросов PUT и DELETE с сообщением об ошибке:
'AccessProtectedResourceRequest' messages cannot be received with HTTP verb 'PutRequest'
Код клиента выглядит примерно так:
public class ResourceClient
{
public Resource UpdateResource(Resource resource)
{
var uri = new Uri(new Uri("http://api.example.com/"), Resource.Format("resources/{0}", resource.Id));
var serializer = new DataContractSerializer(typeof(Resource));
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "PUT";
request.ContentType = "application/xml";
ClientBase.AuthorizeRequest(request, Authorization.AccessToken);
using (var requestStream = request.GetRequestStream())
{
serializer.WriteObject(requestStream, resource);
}
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
Debug.Assert(responseStream != null, "responseStream != null");
return (Resource)serializer.ReadObject(responseStream);
}
}
}
}
Из ответа на другой вопрос кажется, что это может быть недостатком DotNetOpenAuth. Глядя на спецификацию OAuth 2.0, я не вижу ничего, запрещающего использование глаголов PUT или DELETE http при доступе к ресурсам. Тем не менее, я не эксперт в OAuth 2.0, и я не знаю его наизусть.
Поэтому я подумал, что буду «умным» и использую «X-HTTP-Method-Override», чтобы указать PUT, а затем отправить запрос на сервер ресурсов. Я реализовал поведение, как описано в этом примере . Интересно, что пользовательское поведение было вызвано до моей реализации ServiceAuthorizationManager, что привело к точно такой же ошибке.
Альтернативой может быть решение проблемы внутри самого DotNetOpenAuth, но я не знаю, с чего начать.
У меня заканчиваются идеи, и я буду благодарен за любые предложения.