webentwicklung-frage-antwort-db.com.de

HTTP-PUT ist in ASP.NET-Web-API nicht zulässig

In meinem Web-API-Projekt kann ich keinen HTTP PUT für meine Ressourcen ausführen. Ich habe einigeähnlicheFragenaufdiesesProblem gelesen und ich habe den empfohlenen Rat befolgt.

Zunächst habe ich WebDAV auf meinem Rechner (Windows 7 64-Bit) vollständig deinstalliert und anschließend den Rechner neu gestartet.

Zweitens wurden die WebDAV-Handler in meinem web.config als entfernt angegeben, und das HTTP PUT-Verb wurde als zulässig für den URL-Handler ohne Erweiterung angegeben.

<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>

Ich habe sogar versucht, den ISAPI Extensionless URL Handler (32-Bit und 64-Bit) hinzuzufügen und meine Anwendung vom integrierten Pipeline-App-Pool zum klassischen App-Pool zu ändern.

<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" />

Ich verwende derzeit Thinktecture IdentityModel , um die Unterstützung für die CORS-Unterstützung (Cross Origin Resource Sharing) zu aktivieren. Für meine Vernunft habe ich mich für die nukleare Option entschieden, alles zu aktivieren, um sicherzustellen, dass der HTTP PUT tatsächlich erlaubt ist.

config.RegisterGlobal(httpConfig);

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

Das Attribute Routing NuGet-Paket ist so konfiguriert, dass alle Routen von der aktuellen Assembly und allen Subtypen von ApiController abgerufen werden.

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

Meine Ressource hat auch das PUT-Attribut richtig angegeben.

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

Jede Ressource, die ich in dieser Angelegenheit nachgeschlagen habe, empfiehlt dasselbe: Deinstallieren von WebDAV, Deaktivieren der WebDAV-Handler und Sicherstellen, dass der Erweiterungslose URL-Handler ordnungsgemäß konfiguriert ist. Ich habe das alles gemacht und noch funktioniert nicht. 

In Fiedler bekomme ich Folgendes:

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

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

Was mache ich falsch?

25
Mike Bailey

Offensichtlich gibt es ein bekanntes Problem in AttributeRouting, bei dem die HttpPut-Methoden in ASP.NET-Web-API derzeit nicht funktionsfähig sind.

Die aktuell akzeptierte Problemumgehung fügt das entsprechende Verb der Route hinzu, bis eine korrekte Korrektur vorliegt:

Web API RC versiegelte eine wichtige Schnittstelle für die Routenerkennung durch die zugrunde liegender Rahmen. Die Schnittstelle ist zwar nun öffentlich, die Änderung wird nicht vor vNext freigegeben. Hier sind einige Problemumgehungen:

  • Verwenden Sie AR-Attribute in Kombination mit den Attributen HttpGet, HttpPost, HttpPut oder HttpDelete aus 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() {}
19
Mike Bailey

Vergewissern Sie sich, dass Sie [HttpPut] aus System.Web.Http verwenden.

Unter bestimmten Umständen können Sie das Attribut von System.Web.Mvc verwenden.

Dies führte zu 405s für uns.

12
Nick Josevski

Ich hatte den gleichen Fehler und verfolgte ihn auf eine benutzerdefinierte Route, die ich wie folgt definiert hatte:

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

Das Problem hier ist deraction = "Get", der die PUT-Aktion desselben URIs daran hinderte zu antworten. Durch das Entfernen der Standardaktion wurde das Problem behoben.

4
Andrew

Was für mich funktionierte, war das Hinzufügen eines Routenattributs, da bereits eines für eine GET-Anforderung definiert wurde, die wie folgt überladen war:

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

Also habe ich für den PUT hinzugefügt:

    // 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);
    }
3
Oladipo Olasemo

Für mich war es, weil ich den Medientyp nicht in der json-Inhaltszeichenfolge für meine http-Clientanforderung festgelegt hatte:

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

Alle Arten von seltsamen Verhalten, wenn dies nicht festgelegt ist.

0
ComeIn

Ich denke, das ist nicht mehr der Fall, vielleicht wurde dieses Problem jetzt behoben. Die ASP.NET MVC-Web-API ermöglicht jetzt $ http.put. Hier ist der Code zum Testen.

AngularJS-Skriptcode 

$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 Quelltext

<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>

ASP.NET MVC-Web-API-Controller-Aktionsmethode

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

(Ändern Sie die URL, an die die Anforderung gesendet werden soll.). Wenn Sie auf die Schaltfläche "Senden" klicken, wird die Anforderung "HttpPut" an "/ api/default" (DefaultController) gesendet, wo die Aktionsmethode PutDataResponse deklariert ist. Diese Methode wird aufgerufen und der Benutzer erhält seine Antwort.

Diese Lösung wurde ursprünglich geschrieben hier

0
Sheo Narayan