Oto wywołanie PUT
metody w moim interfejsie API sieci Web - trzeci wiersz w metodzie (wywołuję interfejs API sieci Web z interfejsu ASP.NET MVC):
client.BaseAddress
jest http://localhost/CallCOPAPI/
.
Oto contactUri
:
Oto contactUri.PathAndQuery
:
I na koniec moja odpowiedź 405:
Oto plik WebApi.config w moim projekcie interfejsu API sieci Web:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApiGet",
routeTemplate: "api/{controller}/{action}/{regionId}",
defaults: new { action = "Get" },
constraints: new { httpMethod = new HttpMethodConstraint("GET") });
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
Próbowałem zedrzeć ścieżkę, która prowadzi PutAsJsonAsync
do string.Format("/api/department/{0}", department.Id)
i string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id)
bez powodzenia.
Czy ktoś ma jakieś pomysły, dlaczego otrzymuję błąd 405?
AKTUALIZACJA
Zgodnie z żądaniem, oto mój kod kontrolera działu (opublikuję zarówno kod kontrolera działu dla mojego projektu frontendowego, jak i kod działu ApiController dla interfejsu WebAPI):
Kontroler działu Front End
namespace CallCOP.Controllers
{
public class DepartmentController : Controller
{
HttpClient client = new HttpClient();
HttpResponseMessage response = new HttpResponseMessage();
Uri contactUri = null;
public DepartmentController()
{
// set base address of WebAPI depending on your current environment
client.BaseAddress = new Uri(ConfigurationManager.AppSettings[string.Format("APIEnvBaseAddress-{0}", CallCOP.Helpers.ConfigHelper.COPApplEnv)]);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
// need to only get departments that correspond to a Contact ID.
// GET: /Department/?regionId={0}
public ActionResult Index(int regionId)
{
response = client.GetAsync(string.Format("api/department/GetDeptsByRegionId/{0}", regionId)).Result;
if (response.IsSuccessStatusCode)
{
var departments = response.Content.ReadAsAsync<IEnumerable<Department>>().Result;
return View(departments);
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot retrieve the list of department records due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return RedirectToAction("Index");
}
}
//
// GET: /Department/Create
public ActionResult Create(int regionId)
{
return View();
}
//
// POST: /Department/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(int regionId, Department department)
{
department.RegionId = regionId;
response = client.PostAsJsonAsync("api/department", department).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Edit", "Region", new { id = regionId });
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot create a new department due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return RedirectToAction("Edit", "Region", new { id = regionId });
}
}
//
// GET: /Department/Edit/5
public ActionResult Edit(int id = 0)
{
response = client.GetAsync(string.Format("api/department/{0}", id)).Result;
Department department = response.Content.ReadAsAsync<Department>().Result;
if (department == null)
{
return HttpNotFound();
}
return View(department);
}
//
// POST: /Department/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int regionId, Department department)
{
response = client.GetAsync(string.Format("api/department/{0}", department.Id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.PutAsJsonAsync(string.Format(contactUri.PathAndQuery), department).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index", new { regionId = regionId });
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot edit the department record due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return RedirectToAction("Index", new { regionId = regionId });
}
}
//
// GET: /Department/Delete/5
public ActionResult Delete(int id = 0)
{
response = client.GetAsync(string.Format("api/department/{0}", id)).Result;
Department department = response.Content.ReadAsAsync<Department>().Result;
if (department == null)
{
return HttpNotFound();
}
return View(department);
}
//
// POST: /Department/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int regionId, int id)
{
response = client.GetAsync(string.Format("api/department/{0}", id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.DeleteAsync(contactUri).Result;
return RedirectToAction("Index", new { regionId = regionId });
}
}
}
Web API Department ApiController
namespace CallCOPAPI.Controllers
{
public class DepartmentController : ApiController
{
private CallCOPEntities db = new CallCOPEntities(HelperClasses.DBHelper.GetConnectionString());
// GET api/department
public IEnumerable<Department> Get()
{
return db.Departments.AsEnumerable();
}
// GET api/department/5
public Department Get(int id)
{
Department dept = db.Departments.Find(id);
if (dept == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return dept;
}
// this should accept a contact id and return departments related to the particular contact record
// GET api/department/5
public IEnumerable<Department> GetDeptsByRegionId(int regionId)
{
IEnumerable<Department> depts = (from i in db.Departments
where i.RegionId == regionId
select i);
return depts;
}
// POST api/department
public HttpResponseMessage Post(Department department)
{
if (ModelState.IsValid)
{
db.Departments.Add(department);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, department);
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
// PUT api/department/5
public HttpResponseMessage Put(int id, Department department)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
if (id != department.Id)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
db.Entry(department).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
// DELETE api/department/5
public HttpResponseMessage Delete(int id)
{
Department department = db.Departments.Find(id);
if (department == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
db.Departments.Remove(department);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK, department);
}
}
}
źródło
[HttpPut]
przed definicją metody akcji? ([HttpPost]
i[HttpDelete]
tam, gdzie jest to stosowne)[HttpPut]
włączenie kontrolera WebAPI (ApiController), prawda? Ponieważ kontroler frontonu dla działu (metoda edycji) ma[HttpPost]
atrybut.[HttpPut]
atrybutów itp. W metodach Put / Post / Delete ..Odpowiedzi:
Więc sprawdziłem Funkcje systemu Windows, aby upewnić się, że nie mam zainstalowanej rzeczy o nazwie WebDAV, i powiedziałem, że nie. W każdym razie poszedłem dalej i umieściłem następujący plik w moim web.config (zarówno interfejs użytkownika, jak i WebAPI, dla pewności) i teraz działa. Włożyłem to do środka
<system.webServer>
.Ponadto często wymagane jest dodanie następujących elementów do
web.config
w programach obsługi. Dzięki Babakźródło
applicationhost.config
. Cieszę się, że to naprawiłeś.<handlers><remove name="WebDAV" />...
WebDav-SchmebDav .. .. upewnij się, że poprawnie utworzyłeś adres URL z identyfikatorem. Nie wysyłaj jak http://www.fluff.com/api/Fluff?id=MyID , wysyłaj jak http://www.fluff.com/api/Fluff/MyID .
Na przykład.
To rozwalało mi jaja na małą wieczność, totalne zażenowanie.
źródło
public int PutFluffColor(int Id, int colorCode)
napublic int PutFluffColor(int Id, UpdateFluffColorModel model)
Dodaj to do swojego
web.config
. Musisz powiedzieć usługom IIS, coPUT
PATCH
DELETE
i coOPTIONS
oznacza. IIHttpHandler
do którego przywołać.Sprawdź również, czy nie masz włączonego protokołu WebDAV.
źródło
PUT
, to właśnie oznacza 405. Sprawdź, czy działa GET, aby wykluczyć routing. PS. Spróbuj skopiować kod wklejany zamiast zrzutu ekranu. PPS, NIE UŻYWAJTask.Result
, w niektórych sytuacjach pojawią się niepowiązane problemy z wątkami. Zamiast tego po prostu zmień całą metodę na async await. Nie wspominając o tym, że tworzy synchroniczny, wielowątkowy blokowany kod (wolniejszy niż jednowątkowy).Używam aplikacji ASP.NET MVC 5 w usługach IIS 8.5. Wypróbowałem wszystkie zamieszczone tutaj odmiany i tak
web.config
wygląda mój wygląd:Nie mogłem odinstalować WebDav z mojego serwera, ponieważ nie miałem uprawnień administratora. Czasami otrzymywałem
method not allowed
pliki .css i .js. W końcu po powyższej konfiguracji wszystko zaczęło działać ponownie.źródło
Udekorowanie jednego z parametrów działania za pomocą [FromBody] rozwiązało problem:
Jednak ASP.NET wywnioskowałby to poprawnie, gdyby w parametrze metody zastosowano obiekt złożony:
źródło
Inną przyczyną może być to, że nie używasz domyślnej nazwy zmiennej dla „id”, którą w rzeczywistości jest: id.
źródło
W moim przypadku błąd 405 został wywołany przez procedurę obsługi statycznej z powodu konfliktu trasy („api / images”) z folderem o tej samej nazwie („~ / images”).
źródło
Możesz ręcznie usunąć moduł webdav z GUI dla konkretnego w IIS.
1) Idź do IIs.
2) Przejdź do odpowiedniej witryny.
3) Otwórz „Handler Mappings”
4) Przewiń w dół i wybierz moduł WebDav. Kliknij go prawym przyciskiem myszy i usuń.
Uwaga: spowoduje to również zaktualizowanie pliku web.config aplikacji internetowej.
źródło
Twoja aplikacja kliencka i aplikacja serwerowa muszą znajdować się w tej samej domenie, na przykład:
klient - localhost
serwer - localhost
i nie :
klient - localhost: 21234
serwer - localhost
źródło