HTTP PUT non consentito nell’API Web ASP.NET

Nel mio progetto API Web, non riesco a eseguire un HTTP PUT sulle mie risorse. Ho letto alcune domande simili su questo problema e ho seguito il consiglio consigliato.

Prima di tutto, ho disinstallato completamente WebDAV sulla mia macchina (Windows 7 64-bit) e successivamente ho riavviato la mia macchina.

In secondo luogo, i gestori WebDAV sono stati specificati come rimossi nel mio web.config e il verbo HTTP PUT stato specificato come consentito per il gestore URL senza estensioni.

            

Ho persino provato ad aggiungere il gestore URL senza estensioni ISAPI (a 32 e 64 bit) e a modificare la mia applicazione dal pool di app della pipeline integrata al classico pool di app.

   

Attualmente sto utilizzando Thinktecture IdentityModel per abilitare il supporto CORS (Cross Origin Resource Sharing). Per la mia sanità mentale, sono andato con l’opzione nucleare di abilitare tutto per assicurarmi che l’ HTTP PUT sia effettivamente permesso.

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

Il pacchetto Attribute Routing NuGet è configurato per raccogliere tutti i percorsi dall’assembly corrente e qualsiasi sottotipo di ApiController .

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

La mia risorsa ha anche l’attributo PUT correttamente specificato.

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

Ogni risorsa che cerco su questo argomento consiglia la stessa identica cosa: disinstallare WebDAV, disabilitare i gestori WebDAV e assicurarsi che il gestore URL Extensionless sia configurato correttamente. Ho fatto tutto ciò e ancora non funziona.

Nel violinista, sto ottenendo il seguente:

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

Che cosa sto facendo di sbagliato?

Apparentemente, esiste un problema noto all’interno di AttributeRouting cui i metodi HttpPut non sono attualmente funzionanti nell’API Web ASP.NET.

La soluzione attualmente accettata è aggiungere il verbo appropriato sulla route fino a quando non viene trovata una correzione appropriata:

Web API RC ha sigillato un’interfaccia vitale per il rilevamento del percorso da parte del framework sottostante. Sebbene l’interfaccia sia ora pubblica, la modifica non verrà rilasciata fino a vNext. Quindi ecco alcuni accorgimenti:

  • Usa gli attributi AR in combinazione con gli attributi HttpGet, HttpPost, HttpPut o HttpDelete di 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() {} 

Verifica che stai usando [HttpPut] da System.Web.Http .

In alcune circostanze è ansible utilizzare l’attributo di System.Web.Mvc.

Questo risultò in 405 per noi.

Ho avuto lo stesso errore e l’ho tracciato su un percorso personalizzato che avevo definito così:

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

Il problema qui è action = "Get" che ha impedito all’azione PUT dello stesso URI di rispondere. La rimozione dell’azione predefinita ha risolto il problema.

Ciò che ha funzionato per me è stato aggiungere un attributo di instradamento come ne avevo già definito uno per una richiesta GET che era sovraccaricata come di seguito:

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

Quindi ho aggiunto per il 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); } 

Penso che questo non sia più il caso, forse questo problema è stato risolto ora. L’API Web MVC di ASP.NET ora consente $ http.put e qui è il codice da testare.

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

Codice html

 

AngularJS Put request

First Name:

Last Name:

Age :


{{ ServerResponse }}

Metodo di azione del controller API Web 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); } } 

(Cambia l’url per inviare la richiesta a) Quando clicchiamo sul pulsante Invia, invia la richiesta HttpPut a ‘/ api / default’ (DefaultController) dove viene dichiarato il metodo di azione PutDataResponse. Questo metodo verrà chiamato e l’utente riceverà la sua risposta.

Questa soluzione è stata originariamente scritta qui

Per me è stato perché non avevo impostato il tipo di supporto nella stringa di contenuto json per la mia richiesta del client http:

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

Tutti i tipi di comportamento strano se questo non è impostato.