Aqui está a chamada para o PUT
método na minha API da Web - a terceira linha do método (estou chamando a API da Web de um front end do ASP.NET MVC):
client.BaseAddress
é http://localhost/CallCOPAPI/
.
Aqui está contactUri
:
Aqui está contactUri.PathAndQuery
:
E, finalmente, aqui está a minha resposta 405:
Aqui está o WebApi.config no meu projeto de API da 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);
Eu tentei seguir o caminho que é passado PutAsJsonAsync
para string.Format("/api/department/{0}", department.Id)
e string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id)
sem sorte.
Alguém tem alguma idéia de por que estou recebendo o erro 405?
ATUALIZAR
Conforme a solicitação, aqui está o código do meu controlador de departamento (postarei o código do controlador de departamento do meu projeto de front-end, bem como o código do departamento ApiController da WebAPI):
Controlador de departamento 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 });
}
}
}
Departamento de API da Web 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);
}
}
}
fonte
[HttpPut]
antes da definição do método de ação? ([HttpPost]
e sempre[HttpDelete]
que apropriado)[HttpPut]
o controlador WebAPI (ApiController), certo? Como o controlador front-end do Departamento (método Editar) tem um[HttpPost]
atributo[HttpPut]
, etc. atributos na Put / Post / métodos excluem ..Respostas:
Portanto, verifiquei os Recursos do Windows para ter certeza de que não estava instalado o WebDAV, e ele disse que não. Enfim, fui em frente e coloquei o seguinte no meu web.config (front-end e WebAPI, apenas para ter certeza), e ele funciona agora. Eu coloquei isso dentro
<system.webServer>
.Além disso, geralmente é necessário adicionar o seguinte
web.config
nos manipuladores. Graças a Babakfonte
applicationhost.config
. Fico feliz que você tenha consertado.<handlers><remove name="WebDAV" />...
WebDav-SchmebDav .. .. certifique-se de criar o URL com o ID corretamente. Não envie como http://www.fluff.com/api/Fluff?id=MyID , envie como http://www.fluff.com/api/Fluff/MyID .
Por exemplo.
Isso estava estourando minhas bolas por uma pequena eternidade, total vergonha.
fonte
public int PutFluffColor(int Id, int colorCode)
parapublic int PutFluffColor(int Id, UpdateFluffColorModel model)
Adicione isso ao seu
web.config
. Você precisa informar ao IIS o quePUT
PATCH
DELETE
e o queOPTIONS
significa. E qualIHttpHandler
invocar.Verifique também se você não tem o WebDAV ativado.
fonte
PUT
, é isso que significa 405. Verifique se o GET funciona, apenas para descartar o roteamento. PS. Tente copiar o código de colagem em vez da captura de tela. PPS, NÃO USETask.Result
, você terá problemas de segmentação não relacionados em determinadas situações. Basta transformar todo o método em assíncrono aguardar. Sem mencionar que ele cria código bloqueado síncrono e multithread (mais lento que o thread único).Estou executando um aplicativo ASP.NET MVC 5 no IIS 8.5. Eu tentei todas as variações postadas aqui, e é assim que minha
web.config
aparência:Não consegui desinstalar o WebDav do meu servidor porque não tinha privilégios de administrador. Além disso, às vezes eu estava obtendo os
method not allowed
arquivos .css e .js. No final, com a configuração acima, tudo começou a funcionar novamente.fonte
Decorar um dos parâmetros de ação com [FromBody] resolveu o problema para mim:
No entanto, o ASP.NET inferiria corretamente se objeto complexo fosse usado no parâmetro method:
fonte
Outra causa disso pode ser se você não usar o nome da variável padrão para o "id", que na verdade é: id.
fonte
No meu caso, o erro 405 foi invocado pelo manipulador estático devido à rota ("api / images") entrar em conflito com a pasta com o mesmo nome ("~ / images").
fonte
Você pode remover o módulo webdav manualmente da GUI para o particular no IIS.
1) Vá para os IIs.
2) Vá para o respectivo site.
3) Abra "Mapeamentos de manipulador"
4) Role para baixo e selecione o módulo WebDav. Clique com o botão direito e exclua-o.
Nota: isso também atualizará seu web.config do aplicativo web.
fonte
Seu aplicativo cliente e servidor devem estar no mesmo domínio, por exemplo:
client - localhost
servidor - host local
e não :
cliente - localhost: 21234
servidor - host local
fonte