webentwicklung-frage-antwort-db.com.de

PUT und Delete funktionieren nicht mit ASP.NET WebAPI und Database unter Windows Azure

Ich arbeite an einem ASP.NET-WebAPI-Projekt mit grundlegenden CRUD-Vorgängen. Das Projekt wird lokal ausgeführt und verfügt über eine Beispieldatenbank in Windows Azure. 

Bisher funktionieren das Http GET und POST gut, was mir 200 und 201 ergibt. Aber ich habe Schwierigkeiten mit DELETE und POST. Ich habe die Handler in der Web.config geändert, WebDav entfernt, aber nichts davon hat funktioniert. Auch das Aktivieren von CORS und allen möglichen Attributen wie [AcceptVerbs] funktionierte nicht. 

Irgendeine Idee, was ich falsch mache?

Fiddler Raw Output:

HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: GET
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcTWFyY1xPbmVEcml2ZVxEb2t1bWVudGVcRmlcVnNQcm9qZWt0ZVxONTIwMTQwODI1XE41XE41XGFwaVxwcm9kdWN0XDEwODM=?=
X-Powered-By: ASP.NET
Date: Sun, 14 Sep 2014 15:00:43 GMT
Content-Length: 75

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

Web.config:

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
 </system.webServer>

Regler:

 public class ProductController : BaseApiController
    {
        public ProductController(IRepository<Product> repo)
            : base(repo)
        {

        }

        [HttpGet]
        public IEnumerable<Product> Get()
        {
            //...
        }

        [HttpGet]
        public Product Get(int id)
        {
            //...
        }

        [HttpPost]
        public HttpResponseMessage Post([FromBody] Product product)
        {
           //...
        }

        [HttpPut]
        public HttpResponseMessage Put(int productId, [FromBody] Product product)
        {
            //..
        }

        [HttpDelete]
        public HttpResponseMessage Delete(int productId)
        {
            //..
        }

    }

Routing & Formatters:

 public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));


        config.Routes.MapHttpRoute(
            name: "Product",
            routeTemplate: "api/product/{id}",
            defaults: new {controller = "product",  id = RouteParameter.Optional }
        );

        // Custom Formatters:
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(
            config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml"));

        var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
        jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }
}
15
oldsport

Endlich habe ich gefunden, was ich vermasselt habe. Die Benennung der Id (productId) in beiden Controller-Methoden (Post und Put) muss dieselbe sein wie im benutzerdefinierten Routing (id). Als ich ihn von productId in id änderte, funktionierten sowohl POST als auch PUT im Fiddler. Danach habe ich meine Web.config-Einstellungen auf die Standardeinstellungen zurückgesetzt. Das habe ich geändert:

Regler:

    [HttpPut]
    public HttpResponseMessage Put(int id, [FromBody] Product product)
    {
        //..
    }

    [HttpDelete]
    public HttpResponseMessage Delete(int id)
    {
        //..
    }

Web.config:

<system.webServer>
<modules>
  <remove name="FormsAuthentication" />
</modules>
<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

26
oldsport

Im Artikel "Attribut-Routing in ASP.NET-Web-API 2" (20.01.2014) erfahren Sie Folgendes:

Beim Routing wird das Web-API einen URI mit einer Aktion abgleichen. Web API 2 unterstützt ein neuer Routing-Typ, der als Attribut-Routing bezeichnet wird.

(Siehe: "Attributrouting in ASP.NET Web API 2" )

Ab Web-API 2 können Sie das Problem auch beheben, indem Sie das Routenattribut [zu der fraglichen Methode] mit dem gewünschten Platzhalter hinzufügen.

[HttpDelete]
[Route("api/product/{productId}")]
public HttpResponseMessage Delete(int productId)
{
    if (values.Count > productId) {
        values.RemoveAt(productId);
    }
}

Ich habe das in meinem eigenen Code getestet, weil ich mit dem gleichen Problem getroffen wurde und es wie ein Zauber wirkt!

10
Scott Fraley

Fügen Sie den folgenden Code in Ihre Web Config-Datei ein:

<system.webServer>
<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <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" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>

Ich habe auch das gleiche Problem, dadurch wurde es gelöst!

0
Dark Matter