Kacey Ezerioha
Kacey Ezerioha

Reputation: 1218

HttpClient call to web api method with integer parameter Returns error 404

I really can't see what I am doing wrong here. I am trying to call a asp.net core web api method that accepts an integer via HttpClient but it returns a 404 error.

HospitalController (Web API)

[HttpGet("{id}")]
[Route("GetById")]
public JsonResult Get(int id)
{
    return Json(_hospitalService.Get(id));
}

HospitalController (MVC)

protected string url = "http://localhost:5001/api/Hospital";

[HttpGet]
public async Task<IActionResult> Edit(int id)
{
    if (id.Equals(0))
        return StatusCode(404);

    var accessToken = await HttpContext.GetTokenAsync("access_token");
    client.SetBearerToken(accessToken);
    HttpResponseMessage responseMessage = await client.GetAsync(url + "/GetById/" + id); //returns 404 error here.
    if (responseMessage.IsSuccessStatusCode)
    {
        var responseData = responseMessage.Content.ReadAsStringAsync().Result;

        var hospital = JsonConvert.DeserializeObject<Hospital>(responseData);
        var hospitalVM = Mapper.Map<HospitalViewModel>(hospital);
        return View(hospitalVM);
    }

    return View("Error");
}

I have a POST method in the same controller in MVC that works. But this GET method returns a 404 and I can't seem to know why.

Upvotes: 4

Views: 3832

Answers (1)

Nkosi
Nkosi

Reputation: 247631

There are two route templates being used in the api according to

[HttpGet("{id}")] //Matches GET api/Hospital/5
[Route("GetById")] //Matches GET api/Hospital/GetById

neither of which match what is being called

http://localhost:5001/api/Hospital/GetById/5

Http{Verb} attribute is usually used on RestFul APIs.

When building a REST API, it's rare that you will want to use [Route(...)] on an action method. It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

Reference Routing to Controller Actions

update the route template on the web api to map to the desired route

[Route("api/[controller]")]
public class HospitalController : Controller {

    //...code removed for brevity

    //Matches GET api/Hospital/GetById/5
    [HttpGet("GetById/{id:int}")]
    public IActionResult Get(int id) {
        return Ok(_hospitalService.Get(id));
    }
}

Also HttpClient is meant to be used asynchronously, so the MVC controller would also need to be refactored as mixing blocking calls .Result can cause deadlocks

protected string url = "http://localhost:5001/api/Hospital";

[HttpGet]
public async Task<IActionResult> Edit(int id) {
    if (id.Equals(0))
        return StatusCode(404);

    var accessToken = await HttpContext.GetTokenAsync("access_token");
    client.SetBearerToken(accessToken);
    HttpResponseMessage responseMessage = await client.GetAsync(url + "/GetById/" + id);
    if (responseMessage.IsSuccessStatusCode) {
        var responseData = await responseMessage.Content.ReadAsStringAsync();
        var hospital = JsonConvert.DeserializeObject<Hospital>(responseData);
        var hospitalVM = Mapper.Map<HospitalViewModel>(hospital);
        return View(hospitalVM);
    }

    return View("Error");
}

Upvotes: 4

Related Questions