Saturday, July 22, 2017

Web API 404 error Delete request

Leave a Comment

I have a Web API that worked perfectly on development with all kind of HTTP requests (on the same controller), once I moved it to production (shared server, I don't even have access to it) the DELETE requests stopped working (the others are working fine), I get a 404 error:

Requested URL https://www.example.com:443/Rejected-By-UrlScan~/API/Users/DeleteUser/1

Physical Path d:\xx\yy\example.com\Rejected-By-UrlScan

Logon Method Anonymous

Logon User Anonymous

This is (a part of) the web.config:

 <system.web>     <customErrors mode="Off"/>     <authentication mode="None" />     <compilation debug="true" targetFramework="4.5" />     <httpRuntime targetFramework="4.5" />   </system.web>   <system.webServer>     <modules runAllManagedModulesForAllRequests="true">       <remove name="WebDAVModule" />     </modules>     <handlers>       <remove name="WebDAV" />       <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>   </system.webServer> 

The Delete Action:

[Authorize] [RoutePrefix("Users")] public class UsersController : ApiController     {     [HttpDelete]     [Route("DeleteUser/{id:int}")]     public void Delete(int id)     {         _UsersRepository.Delete(id);     } 

And the AJAX call:

deleteUser = function (id, callback) {     $.ajax({         url: "../API/Users/DeleteUser/" + id,         type: "DELETE",         success: function () {             callback;         }     }); } 

WebApiConfig.cs:

    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));          // Web API routes         config.MapHttpAttributeRoutes();           config.Routes.MapHttpRoute(             name: "DefaultApi",             routeTemplate: "{controller}/{id}",             defaults: new { id = RouteParameter.Optional }         );          //create json formatter and remove all others         var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();         jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();         jsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;         config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);         config.Formatters.Remove(config.Formatters.XmlFormatter);     } 

An example of a working call on the same Controller:

getUsers = function (callback) {     $.get("../API/Users/GetUsers/", callback); } 

And the Action:

[Route("GetUsers")] public IEnumerable<User> GetUsers() {     return _UsersRepository.GetUsers(); } 

3 Answers

Answers 1

In your IIS do you have the URLScan extension configured ?

https://www.iis.net/downloads/microsoft/urlscan

UrlScan is a security tool that restricts the types of HTTP requests that IIS will process.

The "Rejected-By-UrlScan" in your URL suggests that the extension may be configured to reject "Delete" requests.

You can ask your Administrator of the Server hosting the IIS about whether Delete requests are configured to be allowed in the IIS.

Answers 2

The URL is wrong in the JS snippet. It should be

deleteUser = function (id, callback) {     $.ajax({         url: "[Application_Path]/Users/DeleteUser/" + id,         type: "DELETE",         success: function () {             callback;         }     }); }  [RoutePrefix("Users")] overrides the default routing, so there should be no "API" in the URL. 

You should remove the [Application_Path] and put your virtual directory name or use the @Url.Action

Answers 3

I had to got it to work so I changed the type of the request from DELETE to POST and it works perfectly:

[Authorize] [RoutePrefix("Users")] public class UsersController : ApiController     {     [HttpPost]     [Route("DeleteUser/{id:int}")]     public void Delete(int id)     {         _UsersRepository.Delete(id);     }  deleteUser = function (id, callback) {     $.ajax({         url: "../API/Users/DeleteUser/" + id,         type: "POST",         success: function () {             callback;         }     }); } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment