25

Web API プロジェクトで、HTTP PUT自分のリソースに対して実行できません。この問題に関するいくつかの 同様の 質問 を読み、推奨されるアドバイスに従いました。

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

次に、WebDAV ハンドラーは myweb.configで削除済みとして指定され、HTTP PUT動詞は拡張なし URL ハンドラーで許可されるように指定されました。

<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 Extensionless URL Handler (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" />

現在、クロス オリジン リソース共有 (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 ハンドラーが適切に構成されていることを確認します。私はそれをすべてやりましたが、まだうまくいきません。

フィドラーでは、次のようになっています。

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

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

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

4

7 に答える 7

20

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() {}
于 2013-01-14T16:50:49.480 に答える
4

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

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

ここでの問題は、応答する同じ URIaction = "Get"のアクションを妨げていたことです。PUTデフォルトのアクションを削除すると、問題が修正されました。

于 2013-01-29T16:35:26.483 に答える
3

私にとってうまくいったのは、以下のようにオーバーロードされた 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);
    }
于 2014-01-13T22:13:07.747 に答える
0

これはもはや当てはまらないと思います。おそらく、この問題は現在修正されています。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 コントローラー アクション メソッド

 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リクエストが送信されます。このメソッドが呼び出され、ユーザーはその応答を取得します。

このソリューションはもともとここに書かれていました

于 2015-07-07T10:16:23.790 に答える
0

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

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

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

于 2016-06-28T09:33:49.630 に答える