PUT and Delete not working with ASP.NET WebAPI and Database on Windows Azure
Solution 1
Finally I found what I messed up. The naming of the Id (productId) in both controller methods (Post and Put) must be the same as in the customized routing (id). When I changed it from productId to id both POST and PUT worked in fiddler. After that I switched back my Web.config settings to the default one. This is what I changed:
Controller:
[HttpPut]
public HttpResponseMessage Put(int id, [FromBody] Product product)
{
//..
}
[HttpDelete]
public HttpResponseMessage Delete(int id)
{
//..
}
Web.config:
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
Solution 2
The "Attribute Routing in ASP.NET Web API 2" (20-Jan-2014) article tells us the following;
Routing is how Web API matches a URI to an action. Web API 2 supports a new type of routing, called attribute routing.
( See: "Attribute Routing in ASP.NET Web API 2" )
So, as of Web API 2, you can also fix it by adding the route attribute [to the method in question] with the placeholder named as you wish.
[HttpDelete]
[Route("api/product/{productId}")]
public HttpResponseMessage Delete(int productId)
{
if (values.Count > productId) {
values.RemoveAt(productId);
}
}
Tested this in my own code, because I got hit with the same problem, and it worked like a charm!
oldsport
Updated on August 02, 2022Comments
-
oldsport almost 2 years
I'm working on a ASP.NET WebAPI project with basic CRUD operations. The project runs locally and has a sample database living inside Windows Azure.
So far, the Http GET and POST works fine, giving me a 200 and 201. But I'm struggling with DELETE and POST. I changed the handlers in the Web.config, removed WebDav, but none of this worked. Also enabling CORS and all sorts of Attributes like [AcceptVerbs] didn't work.
Any idea what I am doing wrong?
Fiddler Raw Output:
HTTP/1.1 405 Method Not Allowed Cache-Control: no-cache Pragma: no-cache Allow: GET Content-Type: application/json; charset=utf-8 Expires: -1 Server: Microsoft-IIS/8.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcTWFyY1xPbmVEcml2ZVxEb2t1bWVudGVcRmlcVnNQcm9qZWt0ZVxONTIwMTQwODI1XE41XE41XGFwaVxwcm9kdWN0XDEwODM=?= X-Powered-By: ASP.NET Date: Sun, 14 Sep 2014 15:00:43 GMT Content-Length: 75 {"Message":"The requested resource does not support http method 'DELETE'."}
Web.config:
<system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules runAllManagedModulesForAllRequests="true"> <remove name="WebDAVModule" /> </modules> <handlers> <remove name="WebDAV" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> </system.webServer>
Controller:
public class ProductController : BaseApiController { public ProductController(IRepository<Product> repo) : base(repo) { } [HttpGet] public IEnumerable<Product> Get() { //... } [HttpGet] public Product Get(int id) { //... } [HttpPost] public HttpResponseMessage Post([FromBody] Product product) { //... } [HttpPut] public HttpResponseMessage Put(int productId, [FromBody] Product product) { //.. } [HttpDelete] public HttpResponseMessage Delete(int productId) { //.. } }
Routing & Formatters:
public static void Register(HttpConfiguration config) { // Web API configuration and services // Configure Web API to use only bearer token authentication. config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); config.Routes.MapHttpRoute( name: "Product", routeTemplate: "api/product/{id}", defaults: new {controller = "product", id = RouteParameter.Optional } ); // Custom Formatters: config.Formatters.XmlFormatter.SupportedMediaTypes.Remove( config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml")); var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } }