Как отправить запрос PUT службе REST WCF 4.0, защищенной с помощью OAuth 2.0 и DotNetOpenAuth - PullRequest
2 голосов
/ 23 февраля 2012

Вопрос:

Существуют ли какие-либо средства (возможно, временное решение) для поддержки 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, но я не знаю, с чего начать.

У меня заканчиваются идеи, и я буду благодарен за любые предложения.

1 Ответ

0 голосов
/ 24 февраля 2012

Это отслеживается Issue # 62 . Вы можете взглянуть на исправление, если хотите перенести его на свою версию, не дожидаясь следующего выпуска.

...