ASP.NET Web API - 404 On Delete - asp.net-web-api

I am trying to implement a Delete method on a Web API controller. However, I always get a 404 - Not Found. At this point, I have GET, POST and PUT methods that are working just fine. I've been reading a handful of the other SO posts about the same issue - just none of them are working.
The Controller Action
public virtual HttpResponseMessage Delete(string customerId)
{
adapter.RemoveCustomer(customerId);
return Request.CreateResponse(HttpStatusCode.OK, "The customer was deleted.");
}
The AJAX Request
function remove(customer, success, error) {
var url = '/api/Customer';
var data = JSON.stringify({ 'customerId': customer.CustomerId });
$.ajax({
url: url,
type: 'DELETE',
data: data,
contentType: 'application/json'
})
.done(function (data, textStatus, handler) {
success(data);
})
.fail(function (handler, textStatus, errorThrown) {
error(errorThrown);
});
};
The Web.Config
This is my web.config file. Except for the modules section, everything is the same as when I created the project:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<!--<modules runAllManagedModulesForAllRequests="true"></modules>-->
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
I am using IIS Express, but the issue still occurs if I switch back to Visual Studio Development Server.
The Raw HTTP
Here is the raw HTTP request captured by Fiddler:
DELETE http://localhost:63654/TestMvcApplication/api/Customer HTTP/1.1
Host: localhost:63654
Connection: keep-alive
Content-Length: 49
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:63654
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36
Content-Type: application/json
Referer: http://localhost:63654/TestMvcApplication/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
{"customerId":"e107e2dc20834545ae209849bff195f0"}
And here is the response:
HTTP/1.1 404 Not Found
Cache-Control: no-cache
Pragma: no-cache
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?QzpcVXNlcnNcdHBhcmtzXERvY3VtZW50c1xHaXRIdWJcVGVzdE12Y0FwcGxpY2F0aW9uXFRlc3RNdmNBcHBsaWNhdGlvblxhcGlcQ3VzdG9tZXI=?=
X-Powered-By: ASP.NET
Date: Tue, 02 Jul 2013 13:11:52 GMT
Content-Length: 220
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:63654/TestMvcApplication/api/Customer'.","MessageDetail":"No action was found on the controller 'Customer' that matches the request."}
This is an open source project for teaching myself. I have checked in the latest in case anyone wants to see the complete source.

public virtual HttpResponseMessage Delete(string customerId)
Parameter is a simple type and is bound from URI and not from request body. Either pass the customer ID in query string like this - http://localhost:63654/TestMvcApplication/api/Customer?customerId=123 or change the signature to public virtual HttpResponseMessage Delete(string id) and use a URI http://localhost:63654/TestMvcApplication/api/Customer/123.

Related

Cors issue specifically in Internet Explorer XMLHttpRequest: Network Error 0x80070005, Access is denied

Cors issue specifically in Internet Explorer only when
calling API from ajax call.
1)Request header content-type was not present in the Access-Control-Allow-
Headers list
2)XMLHttpRequest: Network Error 0x80070005, Access is denied.
I tried by followings
xhrFields: {
withCredentials: true
}
also by setting
...
crossDomain: true
...
headers: {
'Access-Control-Allow-Origin': '*'
},
Ajax call
var url = "https://dev-connectivity.dummylink";
var data = JSON.stringify({
"lang": "en",
"ClientId": "asdfasf3452345c42352345c",
"CountryCode": "34"
});
$.ajax({
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
headers: {
'Access-Control-Allow-Origin': '*' },
data: data,
success: function (data) {
alert("tets");
},
error: function (error) {
alert("error");
}
});
//My api Webconfig code
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
</customHeaders>
</httpProtocol>
// also Enabling Cors in startup
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder.AllowAnyMethod()
.AllowAnyHeader();
}));
app.UseCors("CorsPolicy");
IE doesn't accept Content-Type header if you have provided * in you web.config file so to fix this issue, you need to manually add Content-Type header in Access-Control-Allow-Headers list inside your web.config file.
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Any-Other-Header" />
</customHeaders>

How to make an HTTP PUT with a param in an ionic 2 app to a WebAPI?

I am trying to make an HTTP PUT with an integer parameter to a MVC WebApi.
I tried to follow the angular 2 guidelines for HTTP PUT: https://angular.io/docs/ts/latest/guide/server-communication.html
My WebApi:
public IHttpActionResult Put([FromBody]int id)
{
return Ok();
}
My Http PUT in my service in my ionic 2 app:
makePut(){
let body = JSON.stringify({id:155320});
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return new Promise(resolve => {
this.http.put('API_URL', body, options)
.subscribe(
response => {
console.log(response.text());
},
error => {
//Failed to Login.
alert(error.text());
console.log(error.text());
});
});
}
And finally the call to my service from my home page:
this.service.makePut().then(data => {console.log(data);});
When I run this I get a 405 method not allowed. Is there anything I am missing?
UPDATE here is part of the web.config in my web api:
<system.webServer>
<security>
</security>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
It might be Web Api error and you can resolve that by adding this code to your web.config file
<handlers accessPolicy="Read, Script">
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
path="*."
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
preCondition="classicMode,runtimeVersionv4.0,bitness64"
responseBufferLimit="0" />
this article can give you more information about 405 error.
I was able to fix the problem, which turned out to be a CORS issue. You can view how to disable same origin policy in Chrome here: How to resolve CORS issue and JSONP issue in Ionic2
Once I disabled it in chrome, the HTTP PUT succeed.
Here is my final code:
makePut(){
let body = 155320; // this is different
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return new Promise(resolve => {
this.http.put('API_URL', body, options)
.subscribe(
response => {
console.log(response.text());
},
error => {
//Failed to Login.
alert(error.text());
console.log(error.text());
});
});
}

Call webservice works from IE, not from Chrome or Firefox

I have a webservice in the same domain of my site. I have an ajax call to consult that webservice and works fine from IE but from Chrome and Firefox, I cannot make it work.
My ajax call is:
$.ajax({
type: 'POST',
async: false
data: xml,
url: url,
dataType: "xml",
success: function (data, textStatus, XmlHttpRequest) {
//On sucess action
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
//On error action
},
headers: {
"Content-Type": "text/xml; charset=utf-8",
"SOAPAction": soapAction,
"Content-Length": xml.length + 1
}
});
But from chrome and firefox I receive:
XMLHttpRequest cannot load https://mydomain:83/<webservice>/<webservice>.asmx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://mydomain' is therefore not allowed access. The response had HTTP status code 500.
I add to the webconfig:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="https://mydomain"/>
<add name="Access-Control-Allow-Origin" value="http://mydomain"/>
<add name="Access-Control-Allow-Credentials" value="true"/>
</customHeaders>
</httpProtocol>
But no luck. Any idea what am I missing?
I gave up to soon. In my particular case, this do the trick for Chrome and Firefox
<add name="Access-Control-Allow-Origin" value="https://mydomain" />
<add name="Access-Control-Allow-Headers" value="Content-Type, SOAPAction" />
<add name="Access-Control-Allow-Methods" value="GET, POST" />

Compression of OData in IIS

I use dynamic compression in IIS7 and enabled the following lines in the configuration:
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/json" enabled="true" />
<add mimeType="application/json; charset=utf-8" enabled="true" />
<add mimeType="application/json; odata=fullmetadata; charset=utf-8" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimetype="application/atom+xml" enabled="true">
<add mimetype="application/atom+xml;charset=utf-8" enabled="true">
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
</httpCompression>
I have an OData controller in Web API which is based off a ODataController.
The OData part work fine, but dynamic compression seems not to work on them, the request looks like this:
Accept:application/atomsvc+xml;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,nl;q=0.6
Connection:keep-alive
DataServiceVersion:3.0
MaxDataServiceVersion:3.0
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
X-SchemaVersion:2.0.0.265
And the response like this:
Cache-Control:no-cache
Content-Length:34862
Content-Type:application/json; odata=fullmetadata; charset=utf-8
DataServiceVersion:3.0
Date:Wed, 11 Jun 2014 16:35:12 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
I suppose the config you posted are web.config of your application. The most easy solution is to changed "add mimeType="/" enabled="false"" to "add mimeType="/" enabled="true"" in dynamicTypes of config. You can try if it works.
Another solution is to change the config in IIS manager. you can follow:Here

Requested resource does not support http method "PUT"

I'm using AttributeRouting with my Web API (MVC 4).
Why does this work?
[AcceptVerbs("PUT")]
[PUT("api/v1/tokens/current")]
public MemoryToken UpdateToken([FromBody] DeviceTokenViewModel viewModel)
{...}
And this one does not?
[PUT("api/v1/tokens/current")]
public MemoryToken UpdateToken([FromBody] DeviceTokenViewModel viewModel)
{...}
Error message: The requested resource does not support http method "PUT".
Why do I have to explicitly accept the PUT verb?
I'm just confused because something similar with POST works just fine (I don't have to specify the accepted verbs):
[POST("api/v1/tokens")]
public MemoryToken CreateToken()
{...}
From various other posts I believe it has to do with the setting in my web.config. The web server section currently looks like this:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="AttributeRouting" path="routes.axd" verb="*" type="AttributeRouting.Web.Logging.LogRoutesHandler, AttributeRouting.Web" />
</handlers>
I tried a couple things like removing WebDav and stuff. But nothing worked so far (unless explicitly allowing the PUT verb in the annotation).
Oh, I am using Visual Studios built-in development server.
Thanks guys!
In this link they describe the POST method as being the default if none of the actions match. So that's why it still works for your CreateToken() method without an HttpPost attribute .
You can specify the HTTP method with an attribute: AcceptVerbs, HttpDelete, HttpGet, HttpHead, HttpOptions, HttpPatch, HttpPost, or HttpPut.
Otherwise, if the name of the controller method starts with "Get", "Post", "Put", "Delete", "Head", "Options", or "Patch", then by convention the action supports that HTTP method.
If none of the above, the method supports POST.

Resources