API Web không được phép 405


88

Lỗi này rất phổ biến và tôi đã thử tất cả các giải pháp nhưng không có giải pháp nào hoạt động. Tôi đã tắt xuất bản WebDAV trong bảng điều khiển và thêm tệp này vào tệp cấu hình web của mình:

  <handlers>
  <remove name="WebDAV"/>
  </handlers>
  <modules runAllManagedModulesForAllRequests="true">
  <remove name="WebDAVModule"/>
  </modules>

Lỗi vẫn còn. Đây là bộ điều khiển:

   static readonly IProductRepository repository = new ProductRepository();

    public Product Put(Product p)
    {
        return repository.Add(p);
    }

Phương pháp thực hiện:

 public Product Add(Product item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        item.Id = _nextId++;
        products.Add(item);
        return item;
    }

Và đây là nơi ngoại lệ được ném ra:

client.BaseAddress = new Uri("http://localhost:5106/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));      
var response = await client.PostAsJsonAsync("api/products", product);//405 exception

Bất kỳ đề xuất?

Câu trả lời:


61

Bạn đang ĐĂNG từ máy khách:

await client.PostAsJsonAsync("api/products", product);

không PUTing.

Phương thức API Web của bạn chỉ chấp nhận các yêu cầu PUT.

Vì thế:

await client.PutAsJsonAsync("api/products", product);

Lỗi 'HttpClient' không chứa định nghĩa cho 'PostAsJsonAsync' được đưa ra khi thử mã của bạn.
agileDev

61

Tôi đã có cùng một ngoại lệ. Vấn đề của tôi là tôi đã sử dụng:

using System.Web.Mvc; // Wrong namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

NÊN LÀ

using System.Web.Http; // Correct namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

18

Tôi đã thử nhiều cách để phương thức DELETE hoạt động (tôi nhận được phương thức 405 không được phép api web) và cuối cùng tôi đã thêm [Route ("api / scan / {id}")] vào bộ điều khiển của mình và hoạt động tốt. hy vọng bài viết này giúp một số người.

     // DELETE api/Scan/5
    [Route("api/scan/{id}")]
    [ResponseType(typeof(Scan))]
    public IHttpActionResult DeleteScan(int id)
    {
        Scan scan = db.Scans.Find(id);
        if (scan == null)
        {
            return NotFound();
        }

        db.Scans.Remove(scan);
        db.SaveChanges();

        return Ok(scan);
    }

Vì một số lý do của tôi, nó chỉ không hoạt động cho việc xóa, cho việc tạo và cập nhật nó hoạt động tốt. Chà, tôi vừa thêm [HttpPost] và nó đã hoạt động. Nhưng cảm ơn, bạn đã cho tôi đi đúng hướng và chỉ chi phí cho tôi 5 phút bây giờ :)
Rubenisme

1
Tại sao bạn không chỉ thêm thuộc tính [HttpDelete]?
johnny 5

14

Vấn đề của tôi hóa ra là Định tuyến thuộc tính trong WebAPI. Tôi đã tạo một tuyến tùy chỉnh và nó coi nó như một GET thay vì WebAPI phát hiện ra nó là một BÀI ĐĂNG

    [Route("")]
    [HttpPost] //I added this attribute explicitly, and it worked
    public void Post(ProductModel data)
    {
        ...
    }

Tôi biết nó phải là một cái gì đó ngớ ngẩn (tiêu tốn cả ngày của bạn)


Điều này đã cứu ngày của tôi!
Phate01

6

Chrome thường cố gắng thực hiện OPTIONScuộc gọi trước khi thực hiện một bài đăng. Nó làm điều này để đảm bảo các tiêu đề CORS theo thứ tự. Có thể có vấn đề nếu bạn không xử lý lệnh OPTIONSgọi trong bộ điều khiển API của mình.

public void Options() { }

6

Lỗi này cũng có thể xảy ra khi bạn cố gắng kết nối với http trong khi máy chủ đang sử dụng https.

Nó hơi khó hiểu vì các yêu cầu nhận được của tôi đều ổn, vấn đề chỉ xuất hiện với các yêu cầu sau.


4

Tôi nhận được 405 trong cuộc gọi GET của mình và sự cố hóa ra là tôi đã đặt tên cho tham số trong phương thức GET phía máy chủ Get(int formId)và tôi cần thay đổi tuyến hoặc đổi tên nó Get(int id).


4

Bạn cũng có thể gặp lỗi 405 nếu nói rằng phương thức của bạn đang mong đợi một tham số và bạn không truyền nó.

Điều này KHÔNG hoạt động (lỗi 405)

Chế độ xem HTML / Javascript

$.ajax({
         url: '/api/News',
         //.....

Web Api:

public HttpResponseMessage GetNews(int id)

Vì vậy, nếu chữ ký phương thức giống như trên thì bạn phải làm:

Chế độ xem HTML / Javascript

$.ajax({
         url: '/api/News/5',
         //.....

Dường như tôi đang gặp phải lỗi 405 vì nhiều lý do khác nhau, tất cả đều bắt nguồn từ việc nó cố gắng HIT chữ ký phương thức và vấn đề tham số hoặc vấn đề đặt tên theo quy ước hoặc vấn đề thuộc tính, v.v.
Tom Stickel

4

Tôi đến muộn với bữa tiệc này nhưng vì không có gì ở trên là khả thi hoặc hoạt động trong hầu hết các trường hợp, đây là cách điều này cuối cùng đã được giải quyết cho tôi.

Trên máy chủ mà trang web / dịch vụ được lưu trữ trên đó, cần có một tính năng! HOẠT ĐỘNG HTTP !!!

Trình quản lý máy chủ> Quản lý> Thêm vai trò và tính năng> tiếp theo tiếp theo cho đến khi bạn vào Tính năng> Trong .NET (từng phiên bản) đánh dấu vào Kích hoạt HTTP. Cũng lưu ý rằng có một ẩn trong> net> Dịch vụ WCF.

Điều này sau đó đã hoạt động ngay lập tức! Điều đó đã làm tan chảy bộ não của tôi


4

Nếu bạn có một lộ trình như

[Route("nuclearreactors/{reactorId}")]

Bạn cần sử dụng cùng tên tham số chính xác trong phương thức, ví dụ:

public ReactorModel GetReactor(reactorId)
{
 ...
}

Nếu bạn không chuyển cùng một tham số chính xác, bạn có thể gặp lỗi "Phương thức 405 không được phép" vì tuyến đường sẽ không khớp với yêu cầu và WebApi sẽ đánh một phương thức bộ điều khiển khác với phương thức HTTP được phép khác.


Đây cũng không phải là một câu trả lời!
Divyang Desai

@Div "Phương thức 405 không được phép" có thể được hiển thị trong trường hợp tôi đã chia sẻ vì phương thức sẽ không bắt lệnh gọi api do thiết lập tuyến không hợp lệ. Sau đó, lệnh gọi api có thể gặp một phương thức không mong muốn khác có thể cho phép một hành động HTTP khác. Có Tôi đồng ý rằng câu trả lời này có thể không phù hợp 100% với câu hỏi thực tế, tuy nhiên tiêu đề câu hỏi của Xardas không cụ thể lắm và tôi tin rằng nhiều người đến đây để tìm kiếm câu trả lời cho câu hỏi như đã nêu trong tiêu đề có thể thấy câu trả lời này hữu ích.
roylac


3

Điều này không trả lời câu hỏi cụ thể của bạn, nhưng khi tôi gặp vấn đề tương tự, tôi đã kết thúc ở đây và tôi nhận ra rằng nhiều người có thể làm như vậy.

Vấn đề tôi gặp phải là tôi đã cố ý khai báo phương thức Get của mình là tĩnh . Tôi đã bỏ lỡ điều này cả một buổi chiều và nó không gây ra cảnh báo từ các thuộc tính hoặc tương tự.

Sai:

public class EchoController : ApiController
{
    public static string Get()
    {
        return string.Empty;
    }
}

Chính xác:

public class EchoController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }
}

2

[HttpPost] là không cần thiết!

[Route("")]
public void Post(ProductModel data)
{
    ...
}

1
Có, cách bạn đang làm là đúng ở chỗ bạn không cần [HttpPost] rõ ràng, tuy nhiên có một số người không tuân theo quy ước (yikes) và do đó, một cái gì đó giống như [Route ("MyMethodSaver"] chuỗi công khai MyMethodtoSave (int? id) -> đó sẽ cần một [HttpPost] và nó sẽ sau đó làm việc
Tom Stickel

2

Tôi KHÔNG thể giải quyết điều này. Tôi đã bật CORS và hoạt động miễn là POST trả về giá trị vô hiệu (ASP.NET 4.0 - WEBAPI 1). Khi tôi cố gắng trả lại HttpResponseMessage, tôi bắt đầu nhận được phản hồi HTTP 405.

Dựa trên phản hồi của Llad ở trên, tôi đã xem xét các tài liệu tham khảo của riêng mình.

Tôi có thuộc tính [System.Web.Mvc.HttpPost] được liệt kê phía trên phương thức POST của mình.

Tôi đã thay đổi điều này để sử dụng:

[System.Web.Http.HttpPostAttribute]
[HttpOptions]
public HttpResponseMessage Post(object json)        
{
    ...
    return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}

Điều này đã sửa chữa tai ương của tôi. Tôi mong điều này giúp được người nào khác.

Để đầy đủ, tôi đã có những điều sau trong web.config của mình:

<httpProtocol>
    <customHeaders>
        <clear />
        <add name="Access-Control-Expose-Headers " value="WWW-Authenticate"/>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, PATCH, DELETE" />
        <add name="Access-Control-Allow-Headers" value="accept, authorization, Content-Type" />
        <remove name="X-Powered-By" />
    </customHeaders>
</httpProtocol>

Điều này sẽ có phương thức được gọi trên yêu cầu trước chuyến bay OPTIONS (cũng như trên BÀI ĐĂNG), tại thời điểm jsonnày có khả năng xảy ra nullvì các yêu cầu trước chuyến bay thường không có tải trọng hoặc bạn sẽ chạy hành động đăng hai lần.
glennsl

1

Chúng tôi đã có một vấn đề tương tự. Chúng tôi đã cố gắng NHẬN khỏi:

[RoutePrefix("api/car")]
public class CarController: ApiController{

    [HTTPGet]
    [Route("")]
    public virtual async Task<ActionResult> GetAll(){

    }

}

Vì vậy, chúng tôi sẽ .GET("/api/car")và điều này sẽ ném một 405 error.


Cách khắc phục:

Các CarController.cstập tin được trong thư mục /api/carnhư vậy khi chúng tôi đã yêu cầu endpoint api này, IIS sẽ gửi lại một lỗi bởi vì nó trông giống như chúng tôi đang cố gắng truy cập vào một thư mục ảo mà chúng ta không được phép.

Tùy chọn 1: thay đổi / đổi tên thư mục bộ điều khiển trong
Tùy chọn 2: thay đổi tiền tố tuyến đường thành một cái gì đó không khớp với thư mục ảo.


1

Trong trường hợp của tôi, tôi có một thư mục vật lý trong dự án có cùng tên với tuyến WebAPI (ví dụ: hộp cát) và chỉ yêu cầu POST bị chặn bởi trình xử lý tệp tĩnh trong IIS (hiển nhiên).

Gặp lỗi 405 gây hiểu lầm thay vì 404 được mong đợi hơn, là lý do khiến tôi mất nhiều thời gian để khắc phục sự cố.

Không dễ rơi vào điều này, nhưng có thể. Hy vọng nó sẽ giúp một ai đó.


1

Về phần mình, trình xử lý POST của tôi có dạng sau:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromRoute] int routeParam, [FromBody] PostData data)

Tôi đã phát hiện ra rằng tôi phải hoán đổi các đối số , tức là trước tiên nói dữ liệu body sau đó là tham số tuyến đường, như sau:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromBody] PostData data, [FromRoute] int routeParam)

0

kiểm tra tệp .csproj dự án của bạn và thay đổi

<IISUrl>http://localhost:PORT/</IISUrl>

đến url trang web của bạn như thế này

<IISUrl>http://example.com:applicationName/</IISUrl>

0

Một vấn đề khác có thể gây ra hành vi tương tự là các tham số mặc định trong định tuyến. Trong trường hợp của tôi, bộ điều khiển đã được định vị và khởi tạo chính xác, nhưng ĐĂNG bị chặn do Gethành động mặc định được chỉ định:

config.Routes.MapHttpRoute(
    name: "GetAllRoute",
    routeTemplate: "api/{controller}.{ext}"/*,
    defaults: new { action = "Get" }*/ // this was causing the issue
);

0

Tôi đã gặp chính xác cùng một vấn đề. Tôi đã tìm kiếm điều gì không ổn trong hai giờ đồng hồ cho đến khi tôi nhận ra POSTphương pháp của mình là privatethay vì public.

Thật buồn cười khi thấy thông báo lỗi đó là loại chung chung. Hy vọng nó giúp!


0

Đảm bảo rằng bộ điều khiển của bạn kế thừa từ Controllerlớp.

Thậm chí có thể còn điên rồ hơn khi mọi thứ sẽ hoạt động cục bộ ngay cả khi không có điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.