Подтвердить что ты не робот

HTTP PUT не разрешен в веб-интерфейсе ASP.NET

В моем проекте веб-API я не могу выполнить HTTP PUT для своих ресурсов. Я прочитал несколько похожих questions on проблема, и я следил за рекомендациями.

Во-первых, я полностью удалил WebDAV на своей машине (Windows 7 64-bit) и впоследствии перезагрузил свою машину.

Во-вторых, обработчики WebDAV были указаны как удаленные в моем web.config, а глагол HTTP PUT был указан как разрешенный для обработчика URL без расширения.

<modules runAllManagedModulesForAllRequests="false">
  <remove name="WebDAVModule"/>
</modules>

<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="WebDAV"/>
  <add name="ExtensionlessUrlHandler-Integrated-4.0"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       type="System.Web.Handlers.TransferRequestHandler"
       resourceType="Unspecified"
       requireAccess="Script"
       preCondition="integratedMode,runtimeVersionv4.0" />
  <add name="AttributeRouting" path="routes.axd" verb="*" type="AttributeRouting.Web.Logging.LogRoutesHandler, AttributeRouting.Web" />
</handlers>

Я даже попробовал добавить обработчик URL-адресов без привязки ISAPI (32-разрядный и 64-разрядный) и сменить приложение из интегрированного пула приложений в классический пул приложений.

<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit"
      path="*."
      verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
      modules="IsapiModule"
      scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
      preCondition="classicMode,runtimeVersionv4.0,bitness32"
      responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
      path="*."
      verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
      modules="IsapiModule"
      scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
      preCondition="classicMode,runtimeVersionv4.0,bitness64"
      responseBufferLimit="0" />

В настоящее время я использую Thinktecture IdentityModel, чтобы включить поддержку Cross Origin Resource Sharing (CORS). Для моего здравомыслия я пошел с ядерным вариантом, позволяющим всем, чтобы убедиться, что HTTP PUT действительно разрешено.

config.RegisterGlobal(httpConfig);

config.ForAllResources()
      .ForAllOrigins()
      .AllowAllMethods()
      .AllowAllRequestHeaders();

Маршрутизация атрибутов Пакет NuGet настроен на выбор всех маршрутов из текущей сборки и любых подтипов ApiController.

config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
config.AddRoutesFromControllersOfType<ApiController>();

В моем ресурсе также правильно указан атрибут PUT.

[PUT("/API/Authenticate/Link/{key}/{identifier}")]
public Boolean LinkUser(Guid key, String identifier) { ... }

Каждый ресурс, который я ищу по этому вопросу, рекомендует то же самое: удалить WebDAV, отключить обработчики WebDAV и убедиться, что обработчик URL без расширения настроен правильно. Я сделал все это, и он еще не работает.

В fiddler я получаю следующее:

PUT https://localhost/Test/API/Authenticate/Link/Foo/Bar

{"Message":"The requested resource does not support http method 'PUT'."}

Что я делаю неправильно?

4b9b3361

Ответ 1

По-видимому, в AttributeRouting существует известная проблема, в которой методы HttpPut в настоящее время не работают в ASP.NET Web API.

принятый в настоящее время обходной путь добавляет соответствующий глагол на маршрут до тех пор, пока не произойдет правильное исправление:

Web API RC закрепил жизненно важный интерфейс для обнаружения маршрута лежащей в основе. Хотя интерфейс теперь открыт, изменение не будет выпущен до vNext. Итак, вот некоторые обходные пути:

  • Используйте атрибуты AR в сочетании с атрибутами HttpGet, HttpPost, HttpPut или HttpDelete из System.Web.Http:
[GET("some/url"), HttpGet]
public string Method1() {}

[PUT("some/url"), HttpPut]
public string Method2() {}

[POST("some/url"), HttpPost]
public string Method3() {}

[DELETE("some/url"), HttpDelete]
public string Method4() {}

Ответ 2

Дважды проверьте, что вы используете [HttpPut] из System.Web.Http.

В некоторых случаях вы можете использовать атрибут из System.Web.Mvc.

Это привело к 405 году для нас.

Ответ 3

У меня была такая же ошибка, и я проследил ее до настраиваемого маршрута, который я определил так:

config.Routes.MapHttpRoute(
    name: "SomeCall",
    routeTemplate: "api/somecall/{id}",
    defaults: new { controller = "SomeCall", action = "Get" }
);

Проблема здесь в action = "Get", которая мешала действию PUT того же самого URI. Удаление действия по умолчанию устранило проблему.

Ответ 4

Что для меня работало, так это добавить атрибут маршрута, поскольку я уже определил его для запроса GET, который был перегружен, как показано ниже:

    // GET api/Transactions/5
    [Route("api/Transactions/{id:int}")]
    public Transaction Get(int id)
    {
        return _transactionRepository.GetById(id);
    }

    [Route("api/Transactions/{code}")]
    public Transaction Get(string code)
    {
        try
        {
            return _transactionRepository.Search(p => p.Code == code).Single();
        }
        catch (Exception Ex)
        {
            System.IO.File.WriteAllText(@"C:\Users\Public\ErrorLog\Log.txt",
                Ex.Message + Ex.StackTrace + Ex.Source + Ex.InnerException.InnerException.Message);
        }

        return null;
    }

Итак, я добавил для PUT:

    // PUT api/Transactions/5
    [Route("api/Transactions/{id:int}")]
    public HttpResponseMessage Put(int id, Transaction transaction)
    {
        try
        {
            if (_transactionRepository.Save(transaction))
            {
                return Request.CreateResponse<Transaction>(HttpStatusCode.Created, transaction);
            }
        }
        catch (Exception Ex)
        {
            System.IO.File.WriteAllText(@"C:\Users\Public\ErrorLog\Log.txt",
                Ex.Message + Ex.StackTrace + Ex.Source + Ex.InnerException.InnerException.Message);
        }

        return Request.CreateResponse<Transaction>(HttpStatusCode.InternalServerError, transaction);
    }

Ответ 5

Я думаю, что это уже не так, возможно, этот вопрос уже исправлен. ASP.NET MVC Web API теперь позволяет $http.put, и вот код для тестирования.

AngularJS Script code

$scope.UpdateData = function () {
        var data = $.param({
            firstName: $scope.firstName,
            lastName: $scope.lastName,
            age: $scope.age
        });

        $http.put('/api/Default?'+ data)
        .success(function (data, status, headers) {
            $scope.ServerResponse = data;
        })
        .error(function (data, status, header, config) {
            $scope.ServerResponse =  htmlDecode("Data: " + data +
                "\n\n\n\nstatus: " + status +
                "\n\n\n\nheaders: " + header +
                "\n\n\n\nconfig: " + config);
        });
    };

HTML-код

<div ng-app="myApp" ng-controller="HttpPutController">
<h2>AngularJS Put request </h2>
<form ng-submit="UpdateData()">
    <p>First Name: <input type="text" name="firstName" ng-model="firstName" required /></p>
    <p>Last Name: <input type="text" name="lastName" ng-model="lastName" required /></p>
    <p>Age : <input type="number" name="age" ng-model="age" required /></p>
    <input type="submit" value="Submit" />
    <hr />
    {{ ServerResponse }}
</form></div>

Метод действия контроллера веб-API ASP.NET MVC

 public class DefaultController : ApiController
{

    public HttpResponseMessage PutDataResponse(string firstName, string lastName, int age)
    {
        string msg =  "Updated: First name: " + firstName +
            " | Last name: " + lastName +
            " | Age: " + age;

        return Request.CreateResponse(HttpStatusCode.OK, msg);
    }
}

(Изменить URL-адрес для отправки запроса) Когда мы нажимаем кнопку "Отправить", он отправляет запрос HttpPut на "/api/default" (DefaultController), где объявлен метод действия PutDataResponse. Этот метод будет вызван, и пользователь получит ответ.

Это решение изначально было написано здесь

Ответ 6

Для меня это было потому, что я не задал тип медиа в строке содержимого json для моего запроса http-клиента:

new StringContent (json, Encoding.UTF32, "application/json" );

Все виды странного поведения, если это не задано.