Metoda 405 niedozwolona Web API

89

Ten błąd jest bardzo powszechny, wypróbowałem wszystkie rozwiązania i żadne z nich nie zadziałało. Wyłączyłem publikowanie WebDAV w panelu sterowania i dodałem to do mojego internetowego pliku konfiguracyjnego:

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

Błąd nadal występuje. To jest kontroler:

   static readonly IProductRepository repository = new ProductRepository();

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

Wdrożenie metody:

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

I tu jest zgłaszany wyjątek:

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

Jakieś sugestie?

Xardas
źródło

Odpowiedzi:

61

PUBLUJESZ od klienta:

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

nie PUT.

Twoja metoda interfejsu API sieci Web akceptuje tylko żądania PUT.

Więc:

await client.PutAsJsonAsync("api/products", product);
Darin Dimitrov
źródło
Błąd „HttpClient” nie zawiera definicji dla „PostAsJsonAsync” jest generowany podczas próby kodu.
agileDev
61

Miałem ten sam wyjątek. Mój problem polegał na tym, że użyłem:

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

POWINIEN BYĆ

using System.Web.Http; // Correct namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}
Llad
źródło
18

Próbowałem wielu rzeczy, aby metoda DELETE działała (otrzymywałem metodę 405 niedozwoloną w interfejsie internetowym), a na koniec dodałem [Route ("api / scan / {id}")] do mojego kontrolera i działało dobrze. mam nadzieję, że ten post komuś pomoże.

     // 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);
    }
user2662006
źródło
Z jakiegoś powodu mój nie działał tylko w przypadku usuwania, do tworzenia i aktualizowania działał dobrze. Cóż, właśnie dodałem [HttpPost] i zadziałało. Ale dzięki,
trafiłeś
1
Dlaczego po prostu nie dodajesz atrybutu [HttpDelete]?
johnny 5
14

Moim problemem okazał się routing atrybutów w WebAPI. Utworzyłem niestandardową trasę i potraktowałem ją jak GET zamiast WebAPI, odkrywając, że to POST

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

Wiedziałem, że to musiało być coś głupiego (co pochłania cały dzień)

Nexxas
źródło
To uratowało mi dzień!
Phate01
6

Chrome często próbuje OPTIONSzadzwonić przed wysłaniem posta. Robi to, aby upewnić się, że nagłówki CORS są w porządku. Może to być problematyczne, jeśli nie obsługujesz OPTIONSwywołania w kontrolerze API.

public void Options() { }
Nate Zaugg
źródło
6

Ten błąd może również wystąpić podczas próby połączenia się z protokołem http, gdy serwer jest w trybie https.

Było to trochę zagmatwane, ponieważ moje żądania pobierania były OK, problem występował tylko w przypadku żądań końcowych.

FrankyHollywood
źródło
4

Otrzymałem 405 podczas mojego wywołania GET, a problem okazał się, że nazwałem parametr w metodzie GET po stronie serwera Get(int formId)i musiałem zmienić trasę lub zmienić jej nazwę Get(int id).

Sako73
źródło
4

Możesz również otrzymać błąd 405, jeśli powiedz, że twoja metoda oczekuje parametru, a ty go nie przekazujesz.

To NIE działa (błąd 405)

Widok HTML / JavaScript

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

Internetowy interfejs API:

public HttpResponseMessage GetNews(int id)

Jeśli więc podpis metody jest taki jak powyżej, musisz zrobić:

Widok HTML / JavaScript

$.ajax({
         url: '/api/News/5',
         //.....
Tom Stickel
źródło
Wydaje mi się, że z różnych powodów napotykam błędy 405, wszystkie one sprowadzają się do tego, że próbowałem trafić w sygnaturę metody i problem z parametrami, problem z nazewnictwem konwencji lub problem z
atrybutem
4

Spóźniłem się na tę imprezę, ale ponieważ nic powyżej nie było opłacalne ani działające w większości przypadków, oto jak to zostało ostatecznie rozwiązane dla mnie.

Na serwerze, na którym hostowana była witryna / usługa, wymagana była funkcja! AKTYWACJA HTTP !!!

Menedżer serwera> Zarządzaj> Dodaj role i funkcje> następny następny następny, aż dojdziesz do funkcji> W obszarze .NET (każda wersja) zaznacz opcję Aktywacja HTTP. Należy również zauważyć, że jest ukryty pod> net> Usługi WCF.

To zadziałało natychmiast! To topiło mój mózg

Monolithcode
źródło
4

Jeśli masz trasę taką jak

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

Musisz użyć dokładnie tej samej nazwy parametru w metodzie np

public ReactorModel GetReactor(reactorId)
{
 ...
}

Jeśli nie przekażesz dokładnie tego samego parametru, może pojawić się błąd „405 metoda niedozwolona”, ponieważ trasa nie będzie zgodna z żądaniem, a WebApi uderzy w inną metodę kontrolera z inną dozwoloną metodą HTTP.

roylac
źródło
To też nie jest odpowiedź!
Divyang Desai
@Div „405 metoda niedozwolona” może zostać wyświetlona w przypadku, gdy udostępniłem, ponieważ metoda nie złapie wywołania api, ponieważ konfiguracja trasy jest nieprawidłowa. Wywołanie api może następnie trafić w inną niezamierzoną metodę, która może mieć inne dozwolone działanie HTTP. Tak, zgadzam się, że ta odpowiedź może nie być w 100% adekwatna do rzeczywistego pytania, jednak tytuł pytania Xardasa nie jest zbyt konkretny i uważam, że wiele osób lądujących tutaj w poszukiwaniu odpowiedzi na pytanie zawarte w tytule może uznasz tę odpowiedź za przydatną.
roylac
3

To nie jest odpowiedzią na twoje konkretne pytanie, ale kiedy miałem ten sam problem, wylądowałem tutaj i pomyślałem, że więcej osób może zrobić to samo.

Problem polegał na tym, że nieumyślnie zadeklarowałem moją metodę Get jako statyczną . Tęskniłem za tym przez całe przedpołudnie i nie spowodowało to żadnych ostrzeżeń ze strony atrybutów lub podobnych.

Błędny:

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

Poprawny:

public class EchoController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }
}
Per Stolpe
źródło
2

[HttpPost] jest niepotrzebne!

[Route("")]
public void Post(ProductModel data)
{
    ...
}
user3963793
źródło
1
Tak, sposób, w jaki to robisz, jest prawidłowy, ponieważ nie potrzebujesz jawnego [HttpPost], jednak niektórzy ludzie nie przestrzegają konwencji (yikes), a zatem coś w rodzaju [Route ("MyMethodSaver"]) publicznego ciągu MyMethodtoSave (int? id) -> który wymagałby [HttpPost] i wtedy działałby
Tom Stickel
2

NIE mogłem tego rozwiązać. Miałem włączony CORS i działał tak długo, jak długo POST zwrócił void (ASP.NET 4.0 - WEBAPI 1). Kiedy próbowałem zwrócić HttpResponseMessage, zacząłem otrzymywać odpowiedź HTTP 405.

Opierając się na powyższej odpowiedzi Llada, przyjrzałem się własnym referencjom.

Miałem atrybut [System.Web.Mvc.HttpPost] wymieniony powyżej mojej metody POST.

Zmieniłem to, aby użyć:

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

To naprawiło moje nieszczęścia. Mam nadzieję, że to pomoże komuś innemu.

Ze względu na kompletność w moim pliku web.config miałem następujące informacje:

<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>
Spencer Sullivan
źródło
Będzie to mieć metodę wywoływaną w żądaniu OPTIONS przed lotem (a także w POST), w którym jsonto momencie jest prawdopodobne, nullponieważ żądania przed lotem zwykle nie zawierają ładunków lub uruchomisz akcję post dwukrotnie.
glennsl
1

Mieliśmy podobny problem. Próbowaliśmy uzyskać z:

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

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

    }

}

Więc zrobilibyśmy .GET("/api/car")i to rzuciłoby 405 error.


Poprawka:

CarController.csPlik był w katalogu /api/carwięc kiedy byliśmy prośbą ten końcowy API IIS byłoby odesłać błąd, ponieważ wyglądało na to, staraliśmy się uzyskać dostęp do katalogu wirtualnego, że nie wolno było.

Opcja 1: zmień / zmień nazwę katalogu, w którym znajduje się kontroler.
Opcja 2: zmień prefiks trasy na coś, co nie pasuje do katalogu wirtualnego.

Zze
źródło
1

W moim przypadku miałem fizyczny folder w projekcie o tej samej nazwie co trasa WebAPI (np. Sandbox) i tylko żądanie POST zostało przechwycone przez moduł obsługi plików statycznych w IIS (oczywiście).

Pojawienie się mylącego błędu 405 zamiast bardziej oczekiwanego błędu 404 było powodem, dla którego rozwiązanie problemu zajęło mi dużo czasu.

Niełatwo się w to wpaść, ale możliwe. Mam nadzieję, że to komuś pomoże.

Panos Roditakis
źródło
1

Z mojej strony mój program obsługi POST miał następującą postać:

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

Doszedłem do wniosku, że muszę zamienić argumenty , to znaczy najpierw dane ciała, a potem parametr trasy, tak jak to:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromBody] PostData data, [FromRoute] int routeParam)
Alexandre Daubricourt
źródło
0

wpisz plik .csproj projektu i zmień go

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

do adresu URL Twojej witryny w ten sposób

<IISUrl>http://example.com:applicationName/</IISUrl>
Ankit
źródło
0

Innym możliwym problemem, który powoduje to samo zachowanie, są domyślne parametry routingu. W moim przypadku kontroler został zlokalizowany i utworzony poprawnie, ale POST został zablokowany z powodu Getokreślonej akcji domyślnej :

config.Routes.MapHttpRoute(
    name: "GetAllRoute",
    routeTemplate: "api/{controller}.{ext}"/*,
    defaults: new { action = "Get" }*/ // this was causing the issue
);
Eadel
źródło
0

Miałem dokładnie ten sam problem. Przez dwie godziny szukałem tego, co jest nie tak, ale bez powodzenia, dopóki nie zdałem sobie sprawy, że moja POSTmetoda była privatezamiast public.

Zabawne, że ten komunikat o błędzie jest dość ogólny. Mam nadzieję, że to pomoże!

Gonzo345
źródło
0

Upewnij się, że kontroler dziedziczy z Controllerklasy.

Może być nawet bardziej szalone, że rzeczy działałyby lokalnie nawet bez tego.

Baran
źródło