簡體   English   中英

ASP.NET Web API中不允許HTTP PUT

[英]HTTP PUT not allowed in ASP.NET Web API

在我的Web API項目中,我無法對我的資源執行HTTP PUT 我已經閱讀了一些 關於 這個 問題的 類似 問題 並且我遵循了建議的建議。

首先,我在我的機器上完全卸載了WebDAV(Windows 7 64位),然后重新啟動了我的機器。

其次,WebDAV處理程序在我的web.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無擴展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" />

我目前正在使用Thinktecture IdentityModel來啟用跨源資源共享(CORS)支持。 為了我的理智,我已經選擇了啟用所有內容的核選項,以確保實際允許HTTP PUT

config.RegisterGlobal(httpConfig);

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

Attribute Routing NuGet包配置為從當前程序集和ApiController任何子類型中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'."}

我究竟做錯了什么?

顯然, AttributeRouting存在一個已知問題,其中HttpPut方法目前在ASP.NET Web API中不起作用。

當前接受的解決方法是在路由上添加適當的動詞,直到出現正確的修復:

Web API RC密封了底層框架進行路由檢測的重要接口。 雖然界面現已公開,但直到vNext才會發布更改。 所以這里有一些解決方法:

  • 將AR屬性與System.Web.Http中的HttpGet,HttpPost,HttpPut或HttpDelete屬性結合使用:
[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() {}

仔細檢查您是否正在使用System.Web.Http中的 [HttpPut]

在某些情況下,您最終可以使用System.Web.Mvc中的屬性。

這對我們來說是405s。

我有同樣的錯誤,並將其追溯到我定義的自定義路由,如下所示:

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

這里的問題是action = "Get"阻止相同URI的PUT操作響應。 刪除默認操作可解決問題。

對我有用的是添加一個Route屬性,因為我已經為一個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);
    }

我認為情況已經不是這樣了,也許這個問題現在已經解決了。 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按鈕時,它會將HttpPut請求發送到'/ api / default'(DefaultController),其中聲明了PutDataResponse操作方法。 將調用此方法,用戶將獲得其響應。

這個解決方案最初寫在這里

對我來說,這是因為我沒有在我的http客戶端請求的json內容字符串中設置媒體類型:

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

如果沒有設置,會出現各種奇怪的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM