2

I'm trying to create a basic ability to post comments on a blog, getting the following error for a POST request to my API using Angular2:

Error in comment.service: Response with status: 0  for URL: null

The form submit button calls my comment component, comment-form.component.ts

onSubmit() { 
    this.submitted = true;

    //TODO: replace hardcoded with form fields
    this.newComment = new CommentInputViewModel("temp", 0, 0, true, "null", 0); 
    this.newComment.text = this.model.text;
    this.newComment.ownerID = 6;
    this.newComment.parentID = 1305;
    this.newComment.score = 0.5;
    this.newComment.isFact = true;
    this.newComment.sideID = 1073;
    this.newComment.sideText = "For";


    this._postService.postNewComment(this.newComment)
             .subscribe(comment => this.returnedComment = comment,
              error => this.errorMessage = <any>error);
      console.log("commentList.component - After onSubmit:" + this.returnedComment);
    return JSON.stringify(this.model);
}

Which calls my service to the API:

postNewComment(newComment: IComment): Observable<IComment>{
    let _body = JSON.stringify(newComment); 
    let _headers = new Headers();
    _headers.append( 'Content-Type', 'application/json' );
    let _options = new RequestOptions({ headers: _headers });

    return this._http.post(this._postNewCommentUrl, _body, _options)
                        .map((res:Response) => res.json().value)
                        .catch(this.handleError);
}

The result on the API side, from VS2015 debugger is a 204 error (no content):

![enter image description here]1

What I've tried:

  1. Mostly ruled out COR issues. Most of the other Angular2 POST questions on here were COR problems. Since the request is hitting my Visual Studio debugger and returning 204 I don't think that's it. Plus my CORE startup.cs has "builder.AllowAnyOrigin(); as a policy.

  2. GET commands from the same service to the same API work fine. I can read comments I previously created on the API side.

  3. Intercepting the call with POSTMAN produces the following:

    The Content-Type header is missing.

    POSTMAN response

    If I modify the POSTMAN request by changing the 'text' to json and pasting in the model, it works fine. It hits the API's "Post" method and returns 200, and the json text "true". See below.

    enter image description here

It looks like the body and the headers aren't being transmitted. In the debugger both get passed to the back-end Angular2 code:

enter image description here

As recommended below, here's the dev-tools screencap. Shows pretty much the same thing as POSTMAN.

enter image description here

4
  • You should get an OPTIONS call followed by a POST. 204 isn't an error; it means the server has no content to send back, not that the incoming request had no content. If the request was malformed you'd get a 4xx error. Commented Jan 22, 2017 at 21:46
  • Agreed, although the server is sending 204 because the angular2 POST isn't working. When it does work (with POSTMAN) it returns json 'true' and a 200. I modified my question above to show the controller method in Visual Studio that gets hit when POSTMAN sends the post, vice when my angular2 method does. Commented Jan 23, 2017 at 2:54
  • 1
    Did you try debugging the ASP.NET Core application to see if anything happens over there? Also, did you test whether you can call the service from outside of a browser context (where CORS is not done)? The OPTIONS request you see is to expected; what is missing is the follow-up POST request (which would then contain your data). I see you’re using Firefox, can you try this in Chrome? Chrome often shows a bit more information about failed CORS requests. Commented Jan 23, 2017 at 11:10
  • Poke - The first and fourth screenshots above were from teh ASP.NET CORE side, I'm running my API in VS2015 and the Angular2 side in VS Code. I've been using the Chrome debugger within VS Code, but that is a good idea to use Chrome stand-alone and see what the console says. I'll look through it and see if it gives a better indication than the Chrome debugger. Commented Jan 23, 2017 at 19:47

3 Answers 3

4

It was a CORS problem. :/

In short, my ASP.NET CORE startup.cs had 'builder.AllowAnyOrigin', and that alone wasn't sufficient. It also needed 'builder.AllowAnyMethod' to account for Firefox/Google's OPTION method. This blog is good: https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas

Detail:

As I mentioned above, my CORS in ASP.NET CORE was:

services.AddCors(options =>
        {
            options.AddPolicy("CorsDevPolicy", builder =>
            {
                builder.AllowAnyOrigin();
            });

        });

I had been using Firefox and Chrome. I tried it in IE, and it worked. Turns out IE doesn't do the pre-flight OPTION request, which is the only request that was being turned down.

ASP.NET CORE's documentation on CORS is weak, so I used this blog: https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas

and modified my API's startup.cs file to read :

// in the ConfigureServices(IServiceCollection services) method
services.AddCors(options =>
        {
            options.AddPolicy("CorsDevPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
            });

        });

And then (also in startup.cs):

public async void Configure(IApplicationBuilder app, ......
    {
         // other unrelated code

        app.UseCors("CorsDevPolicy");
        // other unrelated code.

        // app.UseCors must come before this:
        app.UseMvc();

Appreciate all the comments. They kept me poking away and trying new things I wouldn't have thought of otherwise (like using IE).

Sign up to request clarification or add additional context in comments.

Comments

2

For those that care or those who, like me, didn't relish the idea of having a fully permissive CORS policy.

As stated the issue is a CORS problem and the CORS headers sort of point you in the right direction, albeit in a subtle way.

In both the postman and dev tools screen captures above they show an OPTIONS request being made to the server with the headers:

Access-Control-Request-Method: POST    
Access-Control-Request-Headers: content-type

Essentially asking if the content-type header is acceptable on POST requests from the specified origin. Because neither .AllowAnyHeader() or .WithHeaders("content-type") have been set in the CORS policy the server does not respond favourably and the actual POST is never sent by the browser.

My final policy looked something like this:

appBuilder.UseCors(options =>
{
    options.WithOrigins("http://myorigin")
         .WithMethods("POST")
         .WithHeaders("content-type")
});

It took me a ton more time than it should have done to figure this out so if it saves someone else some time this post is worth it :)

Comments

0

You want to use a content-type of application/json, but sending the body as a string: let _body = JSON.stringify(newComment);!!

Should be: const _body = newComment;.

3 Comments

Appreciate the reply, unfortunately that didn't work. Same error from Angular2 debugger (I'm using VS Code) and same response from the API debugger (using VS2015). The only difference was when I intercepted it with POSTMAN it had an additional header: Content-Type, with a value of 'application/x-www-form-urlencoded'. I believe json.stringify is correct. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Yep, angular would do it if your aren't. my fault. please look into browsers dev-tools what angular is sending.
Thanks, no worries. The dev-tools shows the same thing as POSTMAN, basically an empty OPTION is being sent. But that's a good idea, I'll go ahead and edit my question with a screenshot of the dev-tools.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.