Aquí está la llamada al PUT
método en mi API web: la tercera línea del método (estoy llamando a la API web desde una interfaz ASP.NET MVC):
client.BaseAddress
es http://localhost/CallCOPAPI/
.
Aquí está contactUri
:
Aquí está contactUri.PathAndQuery
:
Y finalmente, aquí está mi respuesta 405:
Aquí está el WebApi.config en mi proyecto de API 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);
He intentado despojar por el camino que se pasa en PutAsJsonAsync
a string.Format("/api/department/{0}", department.Id)
, y string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id)
sin suerte.
¿Alguien tiene alguna idea de por qué me sale el error 405?
ACTUALIZAR
Según la solicitud, aquí está mi código de controlador de Departamento (publicaré tanto el código de controlador de Departamento para mi proyecto front-end, como el código de ApiController de Departamento para WebAPI):
Controlador del departamento de 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 });
}
}
}
API Web Departamento 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);
}
}
}
fuente
[HttpPut]
antes de la definición del método de acción? ([HttpPost]
y[HttpDelete]
cuando sea apropiado también)[HttpPut]
el controlador WebAPI (ApiController), ¿verdad? Porque el controlador de front-end para Departamento (método de edición) tiene un[HttpPost]
atributo.[HttpPut]
atributos, etc. en los métodos Put / Post / Delete ..Respuestas:
Entonces, verifiqué las características de Windows para asegurarme de que no tenía instalado este elemento llamado WebDAV, y decía que no. De todos modos, seguí adelante y coloqué lo siguiente en mi web.config (tanto front-end como WebAPI, solo para estar seguro), y funciona ahora. Puse esto adentro
<system.webServer>
.Además, a menudo se requiere agregar lo siguiente
web.config
en los controladores. Gracias a Babakfuente
applicationhost.config
. Me alegra que lo hayas arreglado.<handlers><remove name="WebDAV" />...
WebDav-SchmebDav .. .. asegúrese de crear la url con la ID correctamente. No lo envíe como http://www.fluff.com/api/Fluff?id=MyID , envíelo como http://www.fluff.com/api/Fluff/MyID .
P.ej.
Esto fue reventar mis bolas por una pequeña eternidad, vergüenza total.
fuente
public int PutFluffColor(int Id, int colorCode)
apublic int PutFluffColor(int Id, UpdateFluffColorModel model)
Agrega esto a tu
web.config
. Debe decirle a IIS quéPUT
PATCH
DELETE
y quéOPTIONS
significa. Y cuálIHttpHandler
invocar.También verifique que no tenga WebDAV habilitado.
fuente
PUT
, eso es lo que significa 405. Verifique que GET funcione, solo para descartar el enrutamiento. PD. Intente copiar el código de pegado en lugar de la captura de pantalla. PPS, NO LO USETask.Result
, obtendrá problemas de subprocesos no relacionados en ciertas situaciones. Simplemente convierta todo el método en asíncrono en su lugar. Sin mencionar que crea un código bloqueado sincrónico y multiproceso (más lento que un único subproceso).Estoy ejecutando una aplicación ASP.NET MVC 5 en IIS 8.5. Probé todas las variaciones publicadas aquí, y así es
web.config
como se ve mi :No pude desinstalar WebDav de mi servidor porque no tenía privilegios de administrador. Además, a veces recibía los
method not allowed
archivos .css y .js. Al final, con la configuración anterior configurada, todo comenzó a funcionar nuevamente.fuente
Decorar uno de los parámetros de acción con [FromBody] resolvió el problema para mí:
Sin embargo, ASP.NET lo inferiría correctamente si se usara un objeto complejo en el parámetro del método:
fuente
Otra causa de esto podría ser si no utiliza el nombre de variable predeterminado para el "id" que en realidad es: id.
fuente
En mi caso, el error 405 fue invocado por el controlador estático debido a que la ruta ("api / images") está en conflicto con la carpeta del mismo nombre ("~ / images").
fuente
Puede eliminar el módulo webdav manualmente de la GUI para el particular en IIS.
1) Ir a los IIs.
2) Ir al sitio respectivo.
3) Abra "Asignaciones
de controladores " 4) Desplácese hacia abajo y seleccione el módulo WebDav. Haga clic derecho sobre él y elimínelo.
Nota: esto también actualizará su web.config de la aplicación web.
fuente
Su aplicación cliente y la aplicación del servidor deben estar bajo el mismo dominio, por ejemplo:
cliente - localhost
servidor - localhost
y no :
cliente - localhost: 21234
servidor - localhost
fuente