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; } }); }
0 comments:
Post a Comment