1

I have the following issue. Whenever I send something to my Api endpoint, ASP.NET Core 3.1 is not able to process the request. However, when I add the ApiController attribute it works perfectly fine.

My code is correct but only works when I add this attribute. How is that so?

For reference, here's my code

API

[ApiController] //Remove this and the code breaks
[Route("api/SomeApi")]
public class ApiController : Controller {

    private readonly IService service;

    public ApiController(IService service)
    {
        this.service = service;
    }

    [HttpPost]
    [Route("Add")]
    public SomeClass Add(SomeClass foo)
    {
        var userId = service.GetCurrentUserId(User);
        foo.Id = Guid.NewGuid();
        foo.UserId = userId;
        service.Add(foo);
        return foo;
    }
}

JS

axios.post('/api/SomeApi/Add', {
   foo: this.foo,

}).then(function (response: any) {
   this.Id = response.Id;
});

FYI, I have other methods on my ApiController using GET/POST. The GET ones work perfectly fine but the POST methods only work when I use query parameters. In this case, I didn't use query parameters because I have more data to send to my Api than actually given in the example.

I've already tried to get my response using [FromBody]. It did not work. I instead got null. foo was not even instantiated.

4
  • 1
    It only works when that is there because that's what's telling the program it's an Api Controller (and not some other class) and to do various things with it like use and serve HTTP API responses Commented Jan 20, 2020 at 14:09
  • @George It used to work even without adding the ApiController attribute Commented Jan 20, 2020 at 14:11
  • What do you mean it used to work? The various things I mentioned that the attribute does is add model binders Commented Jan 20, 2020 at 14:27
  • @George What I mean is that you didn't have to add the attribute in order to be able to call an endpoint. You were still able to jump into the method, but you were greeted with an exception. Specifically Object reference not set to an instance of an object You still got an instance of SomeClass but all values were empty/null. Commented Jan 20, 2020 at 14:30

2 Answers 2

5

For binding request body to model, there are two types, one is binding from form data and the other is application/json.

For Controller,it would fetch the form data by default.For ApiController,it would fetch the json data by default.

If you want bind request body without using [ApiController],you could add [FromBody]:

//[ApiController] 
[Route("api/SomeApi")]
public class ApiController : Controller
{
    private readonly IService service;
    public ApiController(IService service)
    {
        this.service = service;
    }

    [HttpPost]
    [Route("Add")]
    public SomeClass Add([FromBody]SomeClass foo)
    {
        //do your stuff...
    }
}

Model:

public class SomeClass 
{
    public int Id { get; set; }
    public string Name { get; set; }
}

View:

@section Scripts{
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    axios.post('/api/SomeApi/Add', {
        id: 1,
        name: 'sdfsdf'
    })
        .then(function (response) {
            console.log(response);
        })
        .catch(function (error) {
            console.log(error);
        });
</script>
}

Result: enter image description here

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

4 Comments

I have already tried this but had no success. My foo object was null. It was not instantiated.
I could get the data successfully.Could you share how to define the foo in js?
@Vins it's because you're sending up the object with the property foo whereas foo is the object, change your axios post to be axios.post('/api/SomeApi/Add', {this.foo}) and it should work
@Rena Huh, interesting. It seemingly works now. The issue I had yesterday is gone. I can't explain how. Before I posted this question, I tried out the same example like the one you provided but for some reason, it did not work. I'm really confused but anyways, thank you :)
0

I had the same problem and solved it using qs library for stringifying the JSON Object.

axios.post('/controller/action', Qs.stringify({Id: 1, Name: 'Test'}))
    .then(function (response) {
        console.log(response);
    })
    .catch(function (response) {
        console.log(response);      
    });  

Another way that worked for plain objects is using URLSearchParams.

var requestData = {Id: 1, Name: 'Test'}
var params = new URLSearchParams();

for(key in requestData)
params.append(key, requestData[key]);

axios.post('/controller/action', params)
.then(function (response) {
    console.log(response);
})
.catch(function (response) {
    console.log(response);      
}); 

Comments

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.