The requested resource does not support http method 'OPTIONS'.? - angularjs

I am making the following request to an asp.net web api PUT method from my angular.js client:
var org = {
OrgId: 111,
name: 'testing testing'
};
$http.put("http://localhost:54822/api/data/putorganisation/1/", org).then(function(status) {
console.log("success PUT");
return status.data;
});
However getting the following errormsg (in fiddler):
{"message":"The requested resource does not support http method 'OPTIONS'."}
This is a part of my asp.net web api web.config file:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type,x-xsrf-token,X-Requested-With" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<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" />
<remove name="WebDAV" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
</system.webServer>
data controller web api:
public HttpResponseMessage Options()
{
var response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
return response;
}
public HttpResponseMessage PutOrganisation(int id, [FromBody]Organisation org)
{
var opStatus = _Repository.UpdateOrganisation(org);
if (opStatus.Status)
{
return Request.CreateResponse<Organisation>(HttpStatusCode.Accepted, org);
}
return Request.CreateErrorResponse(HttpStatusCode.NotModified, opStatus.ExceptionMessage);
}
This is my question: Why do I get the errormsg ( see above) when I make exactly the same request in fiddler ( works) as in the angularclient (does not work)??

I know this is an old question, but I ran into the same problem and figured I could help others who are trying to figure out.
I solved it by removing 2 of the handler configurations in the Web.config:
<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>
I don't know exactly why it fixed the problem, but my working theory is that <remove name="OPTIONSVerbHandler" /> makes OPTIONS requests forbidden by default. When sending the request from a browser, it sends an OPTIONS request first before the PUT request, so it never gets to the PUT request because the first OPTIONS request was denied as an invalid http method on the api.
In fiddler, I am assuming that it just sends only the PUT request (I observed the same behavior using the Postman web app sending requests manually). So it skips the forbidden OPTIONS request and succeeds.

I also faced the same issue, after few research, I did following changes to web.config and Global.asax.cs files
<configuration>
<system.webServer>
<directoryBrowse enabled="true" />
<validation validateIntegratedModeConfiguration="false" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, PATCH, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="WebDAV" />
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler" />
<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="C:\windows\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="C:\windows\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>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
</system.webServer>
</configuration>
Add the following code global.ascx.cs
protected void Application_BeginRequest()
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}

This is almost certainly a CORS problem. I'd first read up about it to make sure you understand what this is and why it is important. And I would guess that your server configuration is not correct.
Unfortunately, I don't know much about .net, but this CORS tutorial for .net describes what you should do quite clearly.
It looks like you are missing an EnableCors annotation. It looks like you need to add something like [EnableCors("*", "*", "*")] to your controller. Explicit handling of OPTIONS is not necessary. Of course, in producition, you don't want to use wildcards for your CORS handling. They should be more specific, but this is fine for testing.

Andrew is correct, it is most probably a CORS issue. What you need is to add EnableCors attribute to your Controller class so that is looks something like this
[EnableCors(origins: "https://example.com,http://example.org", headers: "*", methods: "*")]
public class TestController : ApiController
{
// your code
The other way to do this is mentioned in this stack overflow post

Yep, an oldie but a goodie. I had the same problem and symptom but my resolution was self-inflicted. I'll share it anyway. The way our service configured the controller used in all of the MapHttpRoute calls at startup included the [DisableCors] attribute. As soon as I reconfigured my local machine startup to use a different controller, everything worked. So if you've done everything else listed here then check your controller and make sure you didn't do something stupid, like I did.

Apparently, in certain cases, an OPTIONS request is sent before the "real" request to determine whether the real request is safe to send due to CORS. See the following MS article at: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api and search for "Preflight Requests".
Some of the following Q&As might also help:
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?
Why does this jQuery AJAX PUT work in Chrome but not FF
How to support HTTP OPTIONS verb in ASP.NET MVC/WebAPI application

Related

Access to XMLHttpRequest at 'http://localhost:56557/api/tw/' from origin 'http://localhost:4200' has been blocked by CORS policy:

I am getting following error.When i tried to send the request from angular 5.0.
Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
(using Postman, the API call works)
following is the angular code
let config = {
headers: {
"Content-Type": "application/json,charset=utf-8",
"access-control-allow-origin": "*",
"access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS",
"access-control-allow-headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization"
}
}
let obs = this.httpClient.post('http://localhost:56557/api/tw/',bodypara,config);
following is the web config changes
<system.webServer>
<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" />-->
<add name="Browser Link for HTML" path="*.html" verb="*"
type="System.Web.StaticFileHandler, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
resourceType="File" preCondition="integratedMode" />
</handlers>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Authorization" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
You've told your app that the access-control-allow-* headers are not allowed by not including them in the Access-Control-Allow-Headers options:
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Authorization" />
Which is why you are seeing the error.
Also, the access-control-allow-* headers, are all response headers and would normally be ignored by the server anyway. Simply remove them from your request.
Just add the following code at the top of your file on the server.
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
In case you set a specific headers in angular or requesting file
You will need to enter them as seen below:
Access-Control-Allow-Origin: [SCHEME]://[HOST]:[PORT_OPTIONAL]
SCHEME => http/https
HOST => server ip/domain name
PORT_OPTIONAL => port //optional

Getting error 405 (Method Not Allowed) while calling POST WEBAPI from AngularJS $http?

I have WEBAPI project and AngularJS client side project. $http.get calls are working fine and also $http.post calls with null data are working but with data its throwing error '405 (Method Not Allowed)'.I have enabled CORS too. Please provide solution.
I have added following things in web.config
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS,XYZ" 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,XYZ" 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="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<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>
This is the WEBAPI
[HttpPost]
public bool SubmitQuesiton(JObject data)
{
return Factory.SubmitQuestion(data);
}
This is AngularJS code
data = JSON.stringify(data);
$http({
method: 'POST',
url: "http://localhost:53546/api/demo/SubmitQuesiton",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
data: data
})
Answering own question. Issue is due CORS, it should be enabled in WEBAPI project. The CORS enabling not works through WEB.config code, you need to enable CORS through backend.
Note - remove all web.config CORS enabling code if its there in web.config i.e the below code
<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>
Steps
1. Install CORS package Install-Package Microsoft.AspNet.WebApi.Cors for WEBAPI project
2. In WebApiConfig.cs add this code
var corsAttribute = new EnableCorsAttribute("*","Origin, Content-Type, Accept",
"GET, PUT, POST, DELETE, OPTIONS");
config.EnableCors(corsAttribute);
Done.

Cors not working in web api2 project

Hi I am developing web api2 project. I hosted application in server 192.168.0.213 and I am trying to access the methods as below.
this.getSubs = function () {
var url = 'http://192.168.0.213:7777/api/User_Creation/';
return $http.get(url).then(function (response) {
return response.data;
});
}
Above function returns the data with no issues.
For example my below methods with verbs such as PUT,DELETE and POST not working.
this.saveSubscriber = function (sub) {
return $http({
method: 'post',
data: JSON.stringify(sub),
url: 'http://192.168.0.213:7777/api/User_Creation/',
contentType: "application/json"
});
}
I tried many ways still did not worked any methods. Currently i have below code in web.config file.
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="POST,GET,PUT,DELETE" />
</customHeaders>
Also i have below line of code in webapiconfig.cs file.
private static void EnableCrossSiteRequests(HttpConfiguration config)
{
var cors = new EnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*");
config.EnableCors(cors);
}
Also i have below line of code in controller. Still does not working anything.
[EnableCors(origins: "http://192.168.0.213:7777", headers: "*", methods: "*")]
Also i commented . I tried all the ways only GET verb is working fine. My insert update delete operations are not working. May I know where i am doing things wrong? May i get some help on this as i tried my best still no luck.. Thank you all.
try wigh something like this: (for me work perfectly):
Startup.cs file: (install Microsoft.Owin.Cors nuget packages before)
using Goocity.API;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Owin;
[assembly: OwinStartup("API", typeof(Goocity.API.Startup))]
namespace Goocity.API
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
#region TO UNCOMMENT WHEN IS IN PRODUCTION
//var corsPolicy = new CorsPolicy
//{
// AllowAnyMethod = true,
// AllowAnyHeader = true,
// SupportsCredentials = true,
// Origins = { "http://www.mysite.it" }
//};
//app.UseCors(new CorsOptions
//{
// PolicyProvider = new CorsPolicyProvider
// {
// PolicyResolver = context => Task.FromResult(corsPolicy)
// }
//});
#endregion TO UNCOMMENT WHEN IS IN PRODUCTION
app.UseCors(CorsOptions.AllowAll);
ConfigureAuth(app);
}
}
}
then your webconfig: (in the system.webserver section)
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, X-Token, Cache-Control" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="FormsAuthentication" />
</modules>
<staticContent>
<remove fileExtension=".woff" />
<mimeMap fileExtension=".woff" mimeType="application/font-woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
<remove fileExtension=".json" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
<!--<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>-->
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<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>
Hope it help you!!...
You should have [EnableCors(origins: "http://192.168.0.54", headers: "*", methods: "*")] in other words, your EnableCors should specify the client that attempts to connect, not the server itself

Angular post, put, delete returns 405

I am new to angular.
I cant invoke POST, PUT and DELETE methods using angular (GETs working fine)
I have a .NET WebApi server which all methods and all resources URLs works and tested using Advanced Rest Client.
This is the code:
$scope.updateUser = function() {
var url = 'http://localhost/api/users/' + $scope.selectedId;
$http.put(url, $scope.user,{'content-type' : 'application/json'})
.then(
function(response) {
alert("1");
},
function(errResponse) {
alert("2");
}
);
};
I tried with 'content-type':'application/x-www-form-urlencoded', I tried with no config at all, I tried the one with success and error and I tried the one whith command and data attributes.
I get nothing back and while debugging, errResponse contains only the request data. Checked the network tab in the developer tools, and I found that 405 returned.
Again, all URLs are valid and tested using a third party REST client app.
Can any one help?
EDIT:
web.config:
<system.webServer>
<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>
<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>
</system.webServer>
PUT example:
[HttpPut]
[Route("api/users/{id}")]
public IHttpActionResult updateUser(int id, User user)
Regards,
Ido
adding this snippet to web.config should resolve problem :
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
</system.webServer>

AngularJS Allow-Origin to WebApi2

I want to host my API on a separate domain. I have configured my auth-interceptor for token in angular with a bearer:
config.headers.Authorization = 'Bearer ' + sessionStorage.getItem('token');
In my My WebApi2 I have configured the WebApiConfig with cors.
var cors = new EnableCorsAttribute("http://mydomain.com", "*", "*");
config.EnableCors(cors);
And in web.config of the API I also included:
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
I still canĀ“t access the api due to origin not allowed. Can I add something more in my header of the auth-interceptor in angular or what do I need to do?
In web.config of API, include the below mentioned code:
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDAV" />
<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 hope this helps.
Thanks.
your Angular.js interceptor settings are ok.
I've got a public project with your same scenario, with OAuth+Owin authentication. The steps I followed are:
Installation of Microsoft.Owin.Cors library
Creation of custom section config to enable/config CORS
Creation of custom CORS Policy class (with the origins to enable)
Setup of CORS policy depending on configurations
Hope this helps
I've had the same issue before and what worked for me was to remove the settings from the web.config and just leave the configuration settings in the WebApiConfig class
See this answer for more details

Resources