web-dev-qa-db-ja.com

Windows Azure上のASP.NET Web APIおよびデータベースでPUTおよび削除が機能しない

基本的なCRUD操作でASP.NET WebAPIプロジェクトに取り組んでいます。プロジェクトはローカルで実行され、Windows Azure内にサンプルデータベースが存在します。

これまでのところ、HTTP GETとPOSTは正常に機能し、200と201を与えています。しかし、DELETEとPOSTに苦労しています。Web.configでハンドラーを変更し、WebDavを削除しました。 CORSや[AcceptVerbs]のようなあらゆる種類の属性を有効にすることもできませんでした。

私が間違っていることは何か考えていますか?

Fiddlerの未加工出力:

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>

コントローラ:

 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)
        {
            //..
        }

    }

ルーティングとフォーマッター:

 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();
    }
}
16
oldsport

最後に、私がめちゃくちゃにしたものを見つけました。両方のコントローラーメソッド(PostおよびPut)でのId(productId)の名前は、カスタマイズされたルーティング(id)と同じである必要があります。 productIdからidに変更したときPOSTとPUTはフィドラーで動作しました。その後、Web.config設定をデフォルトの設定に戻しました。これは私が変更したものです。

コントローラ:

    [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>
28
oldsport

「ASP.NET Web API 2の属性ルーティング」(2014年1月20日)の記事は次のように述べています。

ルーティングは、Web APIがURIとアクションを照合する方法です。 Web API 2は、属性ルーティングと呼ばれる新しいタイプのルーティングをサポートしています。

(参照: "ASP.NET Web API 2の属性ルーティング"

したがって、Web API 2以降では、ルート属性を[問題のメソッドに]追加し、プレースホルダーに希望の名前を付けることもできます。

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

同じ問題にぶつかったので、これを自分のコードでテストしました。

11
Scott Fraley

以下のコードをWeb Configファイルに追加してみてください。

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

私も同じ問題を抱えていましたが、これを行うことで解決しました!

0
Dark Matter