ASP.Net MVC Core API Question Revisited
-
I posted on this yesterday, but I haven't made any progress. I'm just trying to set up a simplet test API. Here's my controller:
[Route("api/user")]
[ApiController]
public class UserController : _ControllerBase
{
public UserController(IConfiguration configuration) :
base(configuration)
{
}\[HttpGet("getById/{id}")\] public IActionResult GetById(\[FromQuery\]int id) { try { var repo = new Repository(GetDataContext()); var owner = repo.GetById(id); if (owner is null) { return NotFound(); } else { return Ok(owner); } } catch (Exception ex) { return StatusCode(500, "Internal server error"); } } \[HttpGet\] public IActionResult GetAll() { try { var repo = new Repository(GetDataContext()); var owners = repo.GetAll(); return Ok(owners); } catch (Exception ex) { return StatusCode(500, "Internal server error"); } } \[HttpPost\] public IActionResult Test(\[FromBody\]TestEntity testEntity) { return StatusCode(200); }
}
I can call the first two methods, GetAll and GetById like this:
https: //localhost:5001/api/User
and
https: //localhost:5001/api/User/GetById/1and they both return data. But this gives me a Not Found error
[HttpPost]
public IActionResult Test([FromBody]TestEntity testEntity)
{
//...
}called using Postman like this:
https: //localhost:5001/api/User/test/{"id": 10,"name": Someone Else}
Questions First, I'm not even sure I have the controller methods set up right. I don't really understand when/why to use the various attributes such as [FromBody] & [FromQuery]. I'm slowly learning by I may have it wrong here. If I'm passing an object, as opposed to say an int, what should the method signature look like? Do I use FromBody or FromQuery? My Google searches return many different results. What would the correct syntax look like? Second, the way I'm passing params, seperated by '/' seems wrong. Shouldn't the call to the API look something like this?
https: //localhost:2001/api/User/GetById?id=123
Am I doing something wrong here?
In theory, theory and practice are the same. But in p
-
I posted on this yesterday, but I haven't made any progress. I'm just trying to set up a simplet test API. Here's my controller:
[Route("api/user")]
[ApiController]
public class UserController : _ControllerBase
{
public UserController(IConfiguration configuration) :
base(configuration)
{
}\[HttpGet("getById/{id}")\] public IActionResult GetById(\[FromQuery\]int id) { try { var repo = new Repository(GetDataContext()); var owner = repo.GetById(id); if (owner is null) { return NotFound(); } else { return Ok(owner); } } catch (Exception ex) { return StatusCode(500, "Internal server error"); } } \[HttpGet\] public IActionResult GetAll() { try { var repo = new Repository(GetDataContext()); var owners = repo.GetAll(); return Ok(owners); } catch (Exception ex) { return StatusCode(500, "Internal server error"); } } \[HttpPost\] public IActionResult Test(\[FromBody\]TestEntity testEntity) { return StatusCode(200); }
}
I can call the first two methods, GetAll and GetById like this:
https: //localhost:5001/api/User
and
https: //localhost:5001/api/User/GetById/1and they both return data. But this gives me a Not Found error
[HttpPost]
public IActionResult Test([FromBody]TestEntity testEntity)
{
//...
}called using Postman like this:
https: //localhost:5001/api/User/test/{"id": 10,"name": Someone Else}
Questions First, I'm not even sure I have the controller methods set up right. I don't really understand when/why to use the various attributes such as [FromBody] & [FromQuery]. I'm slowly learning by I may have it wrong here. If I'm passing an object, as opposed to say an int, what should the method signature look like? Do I use FromBody or FromQuery? My Google searches return many different results. What would the correct syntax look like? Second, the way I'm passing params, seperated by '/' seems wrong. Shouldn't the call to the API look something like this?
https: //localhost:2001/api/User/GetById?id=123
Am I doing something wrong here?
In theory, theory and practice are the same. But in p
Kevin Marois wrote:
called using Postman like this:
https://localhost:5001/api/User/test/{"id": 10,"name": Someone Else}
Aside from the syntax error in your JSON (no quotes around the
name
value), that doesn't look like a validPOST
request to me. In Postman, the method should be set toPOST
, and the JSON should be in the body, not the URL. Send parameters and body data with API requests in Postman | Postman Learning Center[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
Kevin Marois wrote:
called using Postman like this:
https://localhost:5001/api/User/test/{"id": 10,"name": Someone Else}
Aside from the syntax error in your JSON (no quotes around the
name
value), that doesn't look like a validPOST
request to me. In Postman, the method should be set toPOST
, and the JSON should be in the body, not the URL. Send parameters and body data with API requests in Postman | Postman Learning Center[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
OK, but do I have the method set up correctly?
In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.
-
OK, but do I have the method set up correctly?
In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.
The method looks OK, although you shouldn't really need the
[FromBody]
attribute. For ASP.NET Core:Model Binding in ASP.NET Core | Microsoft Learn[^]:
Route data and query string values are used only for simple types.
If you're still using WebAPI 2 in .NET Framework:
Parameter Binding in ASP.NET Web API - ASP.NET 4.x | Microsoft Learn[^]:
To force Web API to read a simple type from the request body, add the
[FromBody]
attribute to the parameter:In either case, your parameter is not a "simple type", so it should be bound from the request body by default.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
The method looks OK, although you shouldn't really need the
[FromBody]
attribute. For ASP.NET Core:Model Binding in ASP.NET Core | Microsoft Learn[^]:
Route data and query string values are used only for simple types.
If you're still using WebAPI 2 in .NET Framework:
Parameter Binding in ASP.NET Web API - ASP.NET 4.x | Microsoft Learn[^]:
To force Web API to read a simple type from the request body, add the
[FromBody]
attribute to the parameter:In either case, your parameter is not a "simple type", so it should be bound from the request body by default.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
OK, but even when I pass it in Postman from body, it still fails to find it. I'm not sure what's wrong
In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.
-
The method looks OK, although you shouldn't really need the
[FromBody]
attribute. For ASP.NET Core:Model Binding in ASP.NET Core | Microsoft Learn[^]:
Route data and query string values are used only for simple types.
If you're still using WebAPI 2 in .NET Framework:
Parameter Binding in ASP.NET Web API - ASP.NET 4.x | Microsoft Learn[^]:
To force Web API to read a simple type from the request body, add the
[FromBody]
attribute to the parameter:In either case, your parameter is not a "simple type", so it should be bound from the request body by default.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
OK, so I'm still having some issues. I created a new API and enabled Swagger. I added this controller method to the default out of the box WeatherForecastController:
[HttpPost("GetPersonInfo/{entity}")]
public IActionResult GetPersonInfo(PersonEntity person)
{
return StatusCode(200, $"{person.Id}: {person.Name}");
}When I run it, and click the Try It Out button, I enter
{
"id": 135,
"name": "Jack Smith"
}in the Body field and click Execute, and it works. I get back
135: Jack Smith
But when I go to Postman, and fill in the sample Json in the Body tab
{ "id": 135, "name": "Jack Smith"}
and call it
https: //localhost:7160/api/WeatherForecast/GetPersonInfo
I get a 404. That's the URL right out of swagger and the body I used. Any idea what this doesn't work in Postman?
In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.
-
OK, so I'm still having some issues. I created a new API and enabled Swagger. I added this controller method to the default out of the box WeatherForecastController:
[HttpPost("GetPersonInfo/{entity}")]
public IActionResult GetPersonInfo(PersonEntity person)
{
return StatusCode(200, $"{person.Id}: {person.Name}");
}When I run it, and click the Try It Out button, I enter
{
"id": 135,
"name": "Jack Smith"
}in the Body field and click Execute, and it works. I get back
135: Jack Smith
But when I go to Postman, and fill in the sample Json in the Body tab
{ "id": 135, "name": "Jack Smith"}
and call it
https: //localhost:7160/api/WeatherForecast/GetPersonInfo
I get a 404. That's the URL right out of swagger and the body I used. Any idea what this doesn't work in Postman?
In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.
Kevin Marois wrote:
[HttpPost("GetPersonInfo/{entity}")]
Assuming you're passing the JSON in the POST body, you shouldn't have the
{entity}
parameter as part of the route template. Given the current route template, it looks like you're trying to pass the request body in the URL, which is the wrong thing to do.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer