Receiving IActionResult from WebApi

Viewed 1439

I have created Web API, and my problem is reading results from it to client.

WebApi method which creating user:

[HttpPost]
public IActionResult PostNewUser([FromBody]UserDto userDto)
{
    if (userDto == null)
        return BadRequest(nameof(userDto));
    IUsersService usersService = GetService<IUsersService>();
    var id = usersService.Add(userDto);
    return Created("api/users/", id.ToString());
}

And the client which want to call API code is:

public int CreateUser(UserDto dto)
{
    using (HttpClient client = new HttpClient())
    {
        string endpoint = ApiQuery.BuildAddress(Endpoints.Users);
        var json = new StringContent(JsonConvert.SerializeObject(dto), Encoding.UTF8, "application/json");
        var postReult = client.PostAsync(endpoint, json).Result;
        return 1; //?? 
    }
}

It works, response gives 201 (Created) but I have no idea how to return correct result, which should be:

/api/users/id_of_created_user

I'm using netcore2.0 in both projects

2 Answers

In the Web API either construct the created location URL manually

[HttpPost]
public IActionResult PostNewUser([FromBody]UserDto userDto) {
    if (userDto == null)
        return BadRequest(nameof(userDto));
    IUsersService usersService = GetService<IUsersService>();
    var id = usersService.Add(userDto);
    //construct desired URL
    var url = string.Format("api/users/{0}",id.ToString());
    return Created(url, id.ToString());
}

Or use one of the CreateAt* overloads

//return 201 created status code along with the 
//controller, action, route values and the actual object that is created
return CreatedAtAction("ActionName", "ControllerName", new { id = id }, id.ToString());

//OR 

//return 201 created status code along with the 
//route name, route value, and the actual object that is created
return CreatedAtRoute("RouteName", new { id = id }, id.ToString());

In the client, the location is retrieved from the header of the response.

status HttpClient client = new HttpClient();

public async Task<int> CreateUser(UserDto dto) {
    string endpoint = ApiQuery.BuildAddress(Endpoints.Users);
    var json = new StringContent(JsonConvert.SerializeObject(dto), Encoding.UTF8, "application/json");

    var postResponse = await client.PostAsync(endpoint, json);

    var location = postResponse.Headers.Location;// api/users/{id here}

    var id = await postResponse.Content.ReadAsAsync<int>();

    return id;
}

You also appear to be sending the id as part of the response which can be retrieved from the response content.

Note the refactoring of HttpClient to avoid creating an instance every time which can lead to socked exhaustion that can cause errors.

Related