web-dev-qa-db-ja.com

HTTP PUTはASP.NET Web APIで許可されていません

Web APIプロジェクトで、HTTP PUT私のリソースへ。私は読みました somesimilarquestionsonthis問題 そして、私は推奨されるアドバイスに従った。

まず、マシン(Windows 7 64ビット)でWebDAVを完全にアンインストールし、その後マシンを再起動しました。

第二に、WebDAVハンドラーは、私のweb.config そしてその HTTP PUT動詞が、Extensionless URL Handlerで許可されていると指定されました。

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

ISAPIエクステンションレスURLハンドラー(32ビットおよび64ビット)を追加し、アプリケーションを統合パイプラインアプリプールから従来のアプリプールに変更することも試みました。

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

現在、Cross Origin Resource Sharing(CORS)サポートを有効にするために Thinktecture IdentityModel を使用しています。私の正気のために、私はすべてを有効にして、HTTP PUTは実際に許可されています。

config.RegisterGlobal(httpConfig);

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

属性ルーティング NuGetパッケージは、現在のアセンブリとApiControllerのサブタイプからすべてのルートを取得するように構成されています。

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

リソースにはPUT属性も適切に指定されています。

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

この問題を調べるすべてのリソースは、WebDAVをアンインストールし、WebDAVハンドラーを無効にし、Extensionless URLハンドラーが適切に構成されていることを確認することとまったく同じことを推奨します。私はそれをすべてやりましたが、stillは機能しません。

フィドラーでは、私は次を取得しています:

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

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

私は何を間違えていますか?

25
Mike Bailey

明らかに、AttributeRouting内には既知の問題があり、HttpPutメソッドは現在ASP.NET Web APIで機能していません。

現在受け入れられている回避策 は、適切な修正が行われるまで適切な動詞をルートに追加します。

Web API RCは、基盤となるフレームワークによるルート検出のための重要なインターフェイスを封印しました。インターフェイスは現在公開されていますが、変更はvNextまでリリースされません。そのため、次の回避策があります。

  • System.Web.HttpのHttpGet、HttpPost、HttpPut、またはHttpDelete属性と組み合わせてAR属性を使用します。
[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

[HttpPut] from System.Web.Httpを使用していることを再確認してください。

状況によっては、System.Web.Mvcの属性を使用することになります。

その結果、405秒になりました。

12
Nick Josevski

同じエラーが発生し、次のように定義したカスタムルートにトレースしました。

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

ここでの問題はaction = "Get"これにより、同じURIのPUTアクションが応答しなくなりました。デフォルトのアクションを削除すると、問題が修正されました。

4
Andrew

私のために働いたのは、次のようにオーバーロードされたGETリクエスト用にすでに定義されているルート属性を追加することでした:

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

だから私は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<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

私にとっては、httpクライアントリクエストのjsonコンテンツ文字列にメディアタイプを設定していなかったためです。

new StringContent(json、Encoding.UTF32、"application/json");

これが設定されていない場合、あらゆる種類の奇妙な動作。

0
ComeIn

私はこれはもはや事実ではないと思う、おそらくこの問題は現在修正されています。 ASP.NET MVC Web APIは$ http.putを許可するようになりました。テストするコードは次のとおりです。

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

Htmlコード

<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アクションメソッド

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

(リクエストを送信するURLを変更します)Submitボタンをクリックすると、PutDataResponseアクションメソッドが宣言されている '/ api/default'(DefaultController)にHttpPutリクエストが送信されます。このメソッドが呼び出され、ユーザーが応答を取得します。

このソリューションは元々書かれていました here

0
Sheo Narayan