5
votes

I am trying to post some JSON to a web api .net core but for some reason this is always null no matter what i have tried see code below.

this is my .net core web api code

    [Produces("application/json")]
    [Route("api/v1/Issues")]
    [Authorize]
    [EnableCors("AllowCors")]
    public class IssuesController : Controller
    {
        [HttpPost]
        public IActionResult PostIssues([FromBody] string issue)
        {
          //some code to desirialize
        }
    }

and this is how i am trying to post via angular (note that the appropriate services are loaded)

    public addIssue(issue) {
    const headers = new Headers();
    this.authService.getToken().toPromise().then( t => {
      headers.append('Authorization', `Bearer ${t.toString()}`);
      headers.append('Content-Type', 'application/json')
      this.http.post(`${this.baseUrl}/v1/issues`, issue, {
        headers: headers
      }).toPromise()
        .then(res => {
          console.log(res.json());
        });
    });
  }

i have tried changing the post to

this.http.post(`${this.baseUrl}/v1/issues`, JSON.stringify(issue))

and even

this.http.post(`${this.baseUrl}/v1/issues`, {'issue', JSON.stringify(issue)})

but nothing seems to work anyone has any idea why this is happening? To clarify the string issue received on the API is what is always null. Here is the successfull response of when i reaches the server you can see the request payload is not null but reaches the web api as null enter image description here

UPDATE 1 Explanation required if possible Alright i wanted to do a little experiment the same code worked fine for a 4.5 framework instead of a .net core however what i tried to do for .net core and worked was create a class called foo see below

public class Foo
    {
        public string Name { get; set; }
        public string Json { get; set; }
    }

And modify my Controller to accept this object

   [HttpPost]
    public IActionResult PostIssues([FromBody] Foo issue)
    {
       Debug.Write(issue);
       return Ok(issue);
    }

As well as my Angular project to pass a similar format body

public addIssue(issue) {
const headers = new Headers();
this.authService.getToken().toPromise().then( t => {

  headers.append('Authorization', `Bearer ${t.toString()}`);
  headers.append('Content-Type', 'application/json');

  this.http.post(`${this.baseUrl}/v1/issues`, {'name' : 'name', 'json': JSON.stringify(issue)}, {
    headers: headers,
    withCredentials: true
  }).toPromise()
    .then(res => {
      console.log(res.json());
    });
});

}

And this manages to pass successfully and bind to the controller enter image description here

Why is this Ok but not able to pass a Json directly? and why does my original code works on 4.5 framework but not on .net core?

2
What are you returning in PostIssues()? What's the value of issue in your JS?chakeda
I am returning Ok(desieralized issue) but i dont see why that would be an issue the issue is that the json i post is received as null on the apiHarry
Ah okay - I thought you meant res.json() was null. What does your client request look like (from Fiddler or dev tools)?chakeda
I have posted the client request as per your requestHarry
I believe your request body needs an issue attribute. Have you tried adding it to the request body?chakeda

2 Answers

4
votes

I'll try to answer all your questions.

string issue received on the API is always null

Passing a JSON to this will always get you a null because you are trying to bind to a primitive data type. To fix this you have two options

Bind to a model ( viewmodel )

When your parameter is a class, asp will bind this class to the json data you passed that's why you were able to get the name data. Based on your update, you might probably go this route.

More info: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding

Now you might be wondering why would you create a class just to be used on your api when the parameter is just a string?! If you want to use just the string in your api then you can do this

Pass the data using FormData

You need to change your api like this

 public IActionResult PostIssues(string issue){..}

You don't need to specify the [FromBody] here.

In your client-side,

 public addIssue(issue) {
    const headers = new Headers();
    this.authService.getToken().toPromise().then( t => {
      headers.append('Authorization', `Bearer ${t.toString()}`);
     // new code here
    var formData = new FormData();
    formData.append('issue',issue); //you need to specify the parameter name here.
      this.http.post(`${this.baseUrl}/v1/issues`, formData, {
        headers: headers
      }).toPromise()
        .then(res => {
          console.log(res.json());
        });
    });
  }

Hope this helps.

0
votes

since it is a single string you can pass it in the url

${this.baseUrl}/v1/issues?issue=yourVarIssue