0

description of my issue below.

Situation :

My back-end server is running on WebApi.NET. I have already implemented database model and all of the basic controllers, and they handles GET requests (to download some objects) very well. I've obviously added such entry in Web.config file to allow CORS responds to my AngularJS app, which is running on the other port :

<httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
      </customHeaders>
</httpProtocol>

However I cannot force AngularJS to send new object (that should be placed in database) properly. I've tried to add some headers in AngularJS request too, but no effect.


Here's crucial part of AngularJS app :

    self.newRespond = function ()
    {
        var newRespond = {
            'respondID': 3,
            'date': ((new Date().getTime()).toString()),
            'location': 'PL',
            'content': self.respContent,
            'author': globalService.nickname,
            'imgScr':'Resources/thumb.jpg',
            'refID': 1};

        $http.post("http://localhost:52095/api/responds", newRespond, {
            headers: {
                'Access-Control-Allow-Origin':'*',
                'Access-Control-Allow-Methods' : 'POST, GET, PUT, DELETE',
                'Access-Control-Allow-Headers' : 'Content-Type, Authorization, Content-Length, X-Requested-With',
                'Content-Type': 'application/x-www-form-urlencoded' }})
        .success(function (data)
        {
            console.log("New respond added!");
        })
        .error(function (data)
        {
            console.log("Error while sending respond.")
        });
    };

And the part of WebApi controller (which does not really matter) :

    // POST api/Responds
    [ResponseType(typeof(Respond))]
    public IHttpActionResult PostRespond(Respond respond)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.Responds.Add(respond);
        db.SaveChanges();

        return CreatedAtRoute("DefaultApi", new { id = respond.respondID }, respond);
    }

Problem :

After invoking this object-send method, the exception is being thrown :

issue_ss

Since error seems to be connected with OPTIONS header, I've added this :

angularModule.config(['$httpProvider', function ($httpProvider)
{
    //Reset headers to avoid OPTIONS request
    $httpProvider.defaults.headers.common = {};
    $httpProvider.defaults.headers.post = {};
    $httpProvider.defaults.headers.put = {};
    $httpProvider.defaults.headers.patch = {};
}]);

Sadly, still no results.

Question :

Question is simple - how to fix this issue and force AngularJS to send that damned object to .NET server?


@Edited :

Changed Angular method, as Vu Quyet advised. Still same exception thought :

$http.post("http://localhost:52095/api/responds", newRespond, {
                headers: {
                    'Access-Control-Allow-Origin':'*',
                    'Access-Control-Allow-Methods' : 'GET,POST',
                    'Access-Control-Allow-Headers' : 'Content-Type',
                    'Content-Type': 'application/x-www-form-urlencoded' }})
            .success(function (data)
            {
                console.log("New respond added!");
            })
            .error(function (data, error)
            {
                console.log("Error while sending respond. " + error)
            });

@Edited2 :

Now I have trouble with sending serialized object to WebApi controller. With 'Content-Type' header WebApi controller revives blank object (all fields are equals to null or 0).

$http.post("http://localhost:52095/api/responds", newRespond, {
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }}) ...

And without this header, controller respond with 415 error - HTTP Error 415 Unsupported media type.

 $http.post("http://localhost:52095/api/responds", newRespond) ...
baka1408
  • 433
  • 4
  • 21
  • There is a Access-Control-Allow-Credentials header that you need to setup too if you want the cookie to be sent via XHR – loopingz Jun 04 '16 at 00:27

2 Answers2

1

That is cors trouble. By adding some keys in headers to your request:

'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods' : 'POST, GET, PUT, DELETE',
'Access-Control-Allow-Headers' : 'Content-Type, Authorization, Content-Length, X-Requested-With'

You made your request from simple request to become Preflighted_requests. To handle prelighted request, you will need change your config in server to allow new keys in header by config value for Access-Control-Request-Headers

Access-Control-Request-Headers: Content-Type, Authentication ...

But in your case, I think you just need to remove some redundant keys in your request then your request will become a simple cors request (Content-Type is a accepted key of simple request). And your server can receive it.

'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods' : 'POST, GET, PUT, DELETE',
'Access-Control-Allow-Headers' : 'Content-Type, Authorization, Content-Length, X-Requested-With'

If you really need add some custom keys such as TokenAuthentication then adding config values in Access-Control-Request-Headers

Read here for more infor about prelighted request and here for accepted keys of a simple request

Vu Quyet
  • 1,675
  • 1
  • 16
  • 22
  • I've changed headers, but still the same error occurs. – baka1408 Jun 04 '16 at 10:49
  • Remove three keys in your headers, it still three – Vu Quyet Jun 04 '16 at 11:01
  • Post method seems to work now, but since it's impossible to add 'application/json' content-type header and WebApi controller receives null object (all fields are equal 0 or null). Any ideas? – baka1408 Jun 04 '16 at 13:20
  • 1
    Take care with version of odata you use. See here for more about 415 with odata http://stackoverflow.com/questions/19396696/415-unsupported-media-type-post-json-to-odata-service-in-lightswitch-2012 – Vu Quyet Jun 04 '16 at 14:31
0

After spending several hours on searching for a solution eventually I've found one - hope it will help others who will encounter same problem.

How to send an object from AnuglarJS app to a WebApi controller with CORS and Preflighted request headers?

1. AngularJS method :

var postObject = new Object();
postObject.someProperty = "someValue";
postObject.otherProperty = 125.289;

$http.post("http://myServerAdress:1234/api/someRoute", postObject, {
        headers: { 'Content-Type': 'application/json' }})
    .success(function (data)
    {
        console.log("New object added!"); // do what you wish with response data
    })
    .error(function (data, error)
    {
        console.log("Error while sending an object. " + error)
    });

As you can see I am sending basic JS object with a 'application/json' header. No wrapping, serializing or parsing needed.

2. WebAPI .NET project configuration :

I needed to install following packages via NuGet package manager :

  • Microsoft ASP.NET Cross-Origin Support (5.2.3)
  • Microsoft ASP.NET Web API 2.2 Core Libraries (5.2.3)
  • Microsoft ASP.NET Web API 2.2 Web Host (5.2.3)

and then run command to update dependencies in config files :

Update-Package Microsoft.AspNet.WebApi -reinstall

3. WebAPI code :

In the last step I've simply added those two lines into 'App_Start/WebApiConfig.cs' :

EnableCorsAttribute atribbutes = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(atribbutes);

Obviously, you can restrict what origins, headers or methods are about to pass CORS. In this case all are allowed.

And thats all. Objects are now free to be posted and received from all the controllers in the project.

baka1408
  • 433
  • 4
  • 21