Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Moving forward with my mobile app development learning process, I've found a new obstacle: Cross-origin Request Sharing or CORS.

I am using a combination of AngularJS + jQuery Mobile (Cordova phone client) and ASP.NET Web API (backend). My issue is that I have not bee able to complete a POST request (or any other type of request) to an API controller.

My AngularJS controller uses the $http.post() service method to call the Web API controller. However, Chrome debugger says that the call failed in an OPTIONS request (possibly the CORS preflight request).

I have implemented the CORS action selector from the following post: Enabling CORS in Web API Project. Even tough I can call the api method from Fiddler, AngularJS keeps failing on the OPTIONS preflight request.

Is there anything I should be aware of about AngularJS and cross-domain calls? Any possible solution to my predicament?

Thanks.

share|improve this question
    

3 Answers 3

Check out Thinktecture Cors objects, with those (nugettable) you can get full CORS support in WebApi without any code of your own.

Even with a correct CORS implementation I've had a really strange issue with IIS 7 that was solved by enabling all verbs for WebDav (yes, WebDav - don't ask me why I just followed instructions on a blog post :-D).

Do this:

  • Open IIS manager, go to your application's Handler Mapping.
  • Double click the WebDav handler
  • Click "Request Restriction"
  • On the "Verbs" tab, select "All verbs".

Again, no idea why WebApi uses WebDav, but this solved problems with POST and DELETE that wouldn't work in spite of a correct CORS implementation.

share|improve this answer

You can skip the preflight option request by using content-type : application/x-www-form-urlencoded.

AngularJS:

var user = {
   ID: 1,
   Name: 'test'
};

$http({
  url: "api.localhost/api/users/addUser",
  method: "POST",
  data: $.param(user),
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  withCredentials: true,
  }).success(function (data, status, headers, config) {
     console.log(data);
})

Web api:

[HttpPost]
public string AddUser(User user)
{
    // Do something
    return user.Name + " added";
}

Web.config

    <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
            <handlers>
                <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
                <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
                <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
                <remove name="OPTIONSVerbHandler" />
                <remove name="TRACEVerbHandler" />

                <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="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
            </handlers>
            <httpProtocol>
                <customHeaders>
                    <add name="Access-Control-Allow-Origin" value="http://localhost" />
                    <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Cache-Control" />
                    <add name="Access-Control-Allow-Credentials" value="true" />
                    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
                </customHeaders>
            </httpProtocol>
      </system.webServer>
share|improve this answer
up vote 0 down vote accepted

Following up on this, I found an article that pretty much address this scenario. Here is the article.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.