0

I am currently looking at Angular for the first time and trying to post a simple string to an MVC controller. However, when I try to post the string using the Angular client, I get a bad request response.

Test Class:

public class Test 
{
    public string Email { get; set; }
}

Posting via Angular client:

this.client.post<boolean>(this.baseUrl + 'weatherforecast/Test', { Email: Email });

This results in a bad request response.

[HttpPost]
[Route("Test")]
public bool Test([FromBody] string Email)
{
    if (Email == "TestInput")
    {
        return true;
    }
    return false;
}

However this works:

[HttpPost]
[Route("Test")]
public bool Test([FromBody] Test EmailObject)
{
    if (EmailObject.Email == "TestInput")
    {
        return true;
    }
    return false;
}

If I try posting the JSON as simply "StringValue" instead of { Email: "StringValue" }, I get an Unsupported Media Type response.

I imagine there is a simple solution, but is there a way to allow a string to be posted to an MVC controller without requiring it to be passed in as a class?

Drogan41
  • 51
  • 5

2 Answers2

2

A typical endpoint returns an IActionResult or an implementation of IActionResult. For example Ok(), which translates to an HTTP 200 response, NotFound translates to HTTP 404.

[HttpPost]
[Route("Test")]
public IActionResult Test([FromBody] Test EmailObject)
{
    if (EmailObject.Email == "TestInput")
    {
        return Ok(true);
    }
    return Ok(false);
}

Pretty sure you have to wrap it in an object in order to post it. That isn't a limitation of ASP.NET Core, but rather a rule of JavaScript in general. Simply typing "StringValue" is not valid JSON, but { Email:Email } is.

Side note:

You could use query strings:

[HttpGet]
[Route("Test")]
public IActionResult Test([FromQuery] string email)
{
    if (email == "TestInput")
    {
        return Ok(true);
    }
    return Ok(false);
}

Then call it like this:

http://example.com/api/Test?email=TestInput

Then a string would work.

Disclaimer: I do not know how Angular works, at all.

Andy
  • 12,859
  • 5
  • 41
  • 56
1

Controller method that is tested with Postman and with payload "TestInput" and Content-Type: application/json

[HttpPost("Test")]
public bool Test([FromBody] string email)
{
   return email?.Equals("TestInput") == true;
}

Following description in this answer: https://stackoverflow.com/a/50021779/14072498

const httpOptions = {
  headers: new HttpHeaders({'Content-Type': 'application/json'})
}

const payload = 'TestInput';

this.client.post<boolean>(this.baseUrl + 'weatherforecast/Test', `\"${payload}\"`, httpOptions);

Note

`\"${payload}\"`

can (should) be replaced with

JSON.stringify(payload)

but the latter did not work for a person that commented this answer.

Roar S.
  • 8,103
  • 1
  • 15
  • 37
  • It works using Postman, but not when sent by Angular as the string gets unquoted before being sent, you can test that by copying the `xhr` request from the browser and import it in postman – Rafi Henig Aug 23 '20 at 12:47
  • @RafiHenig: Several posts are indicating that missing content-type is causing this problem. By passing a simple string instead of a JSON, Angular fails to guess content-type. But, maybe I'm wrong. – Roar S. Aug 23 '20 at 12:55
  • 1
    I've tried setting `Contnet-Type` header to `Application/Json` with both Postman and Angular, only the former works – Rafi Henig Aug 23 '20 at 13:02
  • @RafiHenig: Updated my answer with JSON.stringify('TestInput') – Roar S. Aug 23 '20 at 13:21