141 votes

La requête Put de l'API Web génère une erreur Http 405 Method Not Allowed (méthode non autorisée)

Voici l'appel au PUT sur mon API Web - la troisième ligne de la méthode (j'appelle l'API Web depuis un frontal ASP.NET MVC) :

enter image description here

client.BaseAddress es http://localhost/CallCOPAPI/ .

Voici contactUri :

enter image description here

Voici contactUri.PathAndQuery :

enter image description here

Et enfin, voici ma réponse sur les 405 :

enter image description here

Voici le WebApi.config de mon projet d'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);

J'ai essayé de supprimer le chemin d'accès qui est passé dans le fichier PutAsJsonAsync a string.Format("/api/department/{0}", department.Id) y string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id) sans succès.

Quelqu'un a-t-il une idée de la raison pour laquelle j'obtiens l'erreur 405 ?

UPDATE

Comme demandé, voici mon code de contrôleur de département (je posterai à la fois le code du contrôleur de département pour mon projet frontal, ainsi que le code de l'ApiController de département pour la WebAPI) :

Contrôleur du département 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 });
        }
    }
}

Département API 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);
        }
    }
}

0 votes

Ne devriez-vous pas utiliser [HttpPut] avant la définition de la méthode d'action ? ( [HttpPost] y [HttpDelete] le cas échéant également)

0 votes

@ChrisPratt Juste pour être clair, vous voulez dire mettre [HttpPut] sur le contrôleur WebAPI (ApiController), n'est-ce pas ? Parce que le contrôleur frontal du département (méthode d'édition) possède une méthode [HttpPost] attribut.

1 votes

@ChrisPratt Le ValuesController (celui qui est fourni avec le modèle WebAPI) n'a pas de [HttpPut] etc. sur les méthodes Put/Post/Delete .

1voto

Adam Levitt Points 2312

Une autre cause de ce problème pourrait être que vous n'utilisez pas le nom de variable par défaut pour le "id" qui est en fait : id.

0voto

Petr Šugar Points 1

Dans mon cas, l'erreur 405 a été invoquée par le gestionnaire statique en raison d'un conflit entre la route ("api/images") et le dossier du même nom ("~/images").

0voto

Naveen Kumar G C Points 384

Vous pouvez supprimer le module webdav manuellement à partir de l'interface graphique pour le particulier dans IIS.
1) Allez dans les II.
2) Allez sur le site correspondant.
3) Ouvrez "Handler Mappings".
4) Faites défiler vers le bas et sélectionnez le module WebDav. Faites un clic droit dessus et supprimez-le.

Note : ceci mettra également à jour votre web.config de l'application web.

0voto

Ce simple problème peut causer un véritable casse-tête !

Je peux voir votre contrôleur EDIT ( PUT ) attend 2 paramètres : a) un id int, et b) un objet département.

C'est le code par défaut lorsque vous le générez à partir de VS > add controller with read/write options. Cependant, vous devez vous rappeler de consommer ce service en utilisant les deux paramètres, sinon vous obtiendrez l'erreur 405.

Dans mon cas, je n'ai pas eu besoin du paramètre id pour la fonction PUT Je l'ai donc supprimé de l'en-tête... après avoir passé quelques heures sans le remarquer ! Si vous le conservez, le nom doit également être conservé comme identifiant, à moins que vous n'apportiez les modifications nécessaires à vos configurations.

-1voto

Lev K. Points 238

Votre application client et votre application serveur doivent être sous le même domaine, par exemple :

client - localhost

serveur - localhost

et non :

client - localhost:21234

serveur - localhost

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X