HTTP PUT no permitido en ASP.NET Web API

En mi proyecto de API web, no puedo realizar un HTTP PUT a mis recursos. He leído algunas preguntas similares sobre este problema y he seguido el consejo recomendado.

En primer lugar, desinstalé completamente WebDAV en mi máquina (Windows 7 de 64 bits) y posteriormente reinicié mi máquina.

En segundo lugar, los manejadores de WebDAV se especificaron como eliminados en mi web.config y el verbo HTTP PUT se especificó como permitido para el manejador de URL sin extensión.

            

Incluso traté de agregar el controlador de URL sin extensión de ISAPI (32 bits y 64 bits) y cambiar mi aplicación del grupo de aplicaciones de canalización integrado al grupo de aplicaciones clásico.

   

Actualmente estoy usando Thinktecture IdentityModel para permitir el soporte Cross Origin Resource Sharing (CORS). Por mi cordura, he optado por la opción nuclear de habilitar todo para asegurarme de que HTTP PUT esté realmente permitido.

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

El paquete Attribute Routing NuGet está configurado para recoger todas las rutas del ensamblaje actual y cualquier subtipo de ApiController .

 config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly()); config.AddRoutesFromControllersOfType(); 

Mi recurso tiene el atributo PUT correctamente especificado también.

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

Cada recurso que busco sobre este tema recomienda exactamente lo mismo: desinstalar WebDAV, deshabilitar los controladores WebDAV y asegurarse de que el controlador de URL sin extensión esté configurado correctamente. He hecho todo eso y todavía no funciona.

En el violinista, obtengo lo siguiente:

 PUT https://localhost/Test/API/Authenticate/Link/Foo/Bar {"Message":"The requested resource does not support http method 'PUT'."} 

¿Qué estoy haciendo mal?

Aparentemente, hay un problema conocido dentro de AttributeRouting en el que los métodos HttpPut actualmente no son funcionales en ASP.NET Web API.

La solución alternativa actualmente aceptada es agregar el verbo apropiado en la ruta hasta que aparezca una solución adecuada:

Web API RC selló una interfaz vital para la detección de rutas por el marco subyacente. Aunque la interfaz ahora es pública, el cambio no se lanzará hasta vNext. Así que aquí hay algunas soluciones:

  • Use los atributos AR en combinación con los atributos HttpGet, HttpPost, HttpPut o HttpDelete de 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() {} 

Verifique que esté usando [HttpPut] desde System.Web.Http .

En algunas circunstancias, puede terminar usando el atributo de System.Web.Mvc.

Esto resultó en 405 para nosotros.

Tuve el mismo error y lo remonté a una ruta personalizada que definí así:

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

El problema aquí es la action = "Get" que impidió que la acción PUT del mismo URI respondiera. La eliminación de la acción predeterminada solucionó el problema.

Lo que funcionó para mí fue agregar un atributo de ruta porque ya tenía uno definido para una solicitud GET que estaba sobrecargada de la siguiente manera:

  // 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; } 

Así que agregué para el 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(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(HttpStatusCode.InternalServerError, transaction); } 

Creo que esto ya no es el caso, tal vez este problema se ha solucionado ahora. ASP.NET MVC Web API ahora permite $ http.put y aquí está el código para probar.

Código de secuencia de comandos AngularJS

 $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); }); }; 

Código HTML

 

AngularJS Put request

First Name:

Last Name:

Age :


{{ ServerResponse }}

Método de acción del controlador ASP.NET MVC Web API

  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); } } 

(Cambie la url para enviar la solicitud) Cuando hacemos clic en el botón Enviar, envía la solicitud HttpPut a ‘/ api / default’ (DefaultController) donde se declara el método de acción PutDataResponse. Se llamará a este método y el usuario obtendrá su respuesta.

Esta solución fue escrita originalmente aquí

Para mí fue porque no había establecido el tipo de medio en la cadena de contenido json para mi solicitud de cliente http:

nuevo StringContent (json, Encoding.UTF32, “application / json” );

Todo tipo de comportamiento raro si esto no está configurado.