Question

I'm getting a 404 error when trying to use an HttpClient to connect to a WebApi service using GET. However, POST works without any problem. In the code below, I have a CreditCard class that I use throughout.

Here's my routing configuration:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Here's my code that calls the async operation:

Task task1 = RegisterCard(card, false);
Task task2 = FetchCard(cardid, false);

Here's my code that contains the the async operations:

private async Task RegisterCard(CreditCard card, bool runAsync)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:63801/");
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = runAsync
                                            ? await client.PostAsJsonAsync("api/card", card)
                                            : client.PostAsJsonAsync("api/card", card).Result;

            response.EnsureSuccessStatusCode();
        }
    }
    catch (HttpRequestException ex)
    {
        throw new HttpRequestException(ex.Message, ex.InnerException);
    }
}

private async Task FetchCard(int cardid, bool runAsync)
{
    CreditCard card = new CreditCard();

    try
    {
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:63801/");
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = runAsync
                                            ? await client.GetAsync("api/card/" + cardid)
                                            : client.GetAsync("api/card/" + cardid).Result;

            response.EnsureSuccessStatusCode();
            }
        }
    }
    catch (HttpRequestException ex)
    {
        throw new HttpRequestException(ex.Message, ex.InnerException);
    }
}

Here's my code for the apiController:

[HttpPost]
public HttpResponseMessage Register(CreditCard card)
{
    HttpResponseMessage result;

    try
    {
        RegisterResponse response = _cardRepository.Register(card);

        result = Request.CreateResponse(HttpStatusCode.Created, response);
    }
    catch (Exception ex)
    {
        // TODO: add logging
        result = Request.CreateErrorResponse(HttpStatusCode.BadRequest, "failed to register card");
    }
    finally
    {
        // TODO: add audit logging of what attempted and who attempted it
    }

    return result;
}

[HttpGet]
public CreditCard Fetch(int cardid)
{
    CreditCard card = new CreditCard();

    try
    {
        card = _cardRepository.Fetch(cardid);
    }
    catch (Exception ex)
    {
        // TODO: add logging
    }
    finally
    {
        // TODO: add audit logging of what attempted and who attempted it
    }

    return card;
}

And my code for the CardRepository:

public RegisterResponse Register(Models.CreditCard card)
{
    using (CreditCardContext ccContext = new CreditCardContext())
    {
        card.MaskedNumber = "XXXXXXXXXXXX" + card.Number.Substring(card.Number.Length - 4, 4);
        card.Number = Crypto.EncryptData_Aes(card.Number, KeyType.CardNumberKey);
        card.CardGuid = Guid.NewGuid().ToString();
        ccContext.CreditCards.Add(card);
        ccContext.SaveChanges();
    }
    card.ResetSensitive();

    RegisterResponse response = new RegisterResponse
    {
        IsSuccess = true,
        Message = "successfully registered card",
        CreditCard = card
    };

    return response;
}

public CreditCard Fetch(int cardid) // , bool masked
{
    CreditCard card;

    using (CreditCardContext ccContext = new CreditCardContext())
    {
        card = ccContext.CreditCards.SingleOrDefault(x => x.Card_ID == cardid);
    }

    return card;
}

QUESTION: Why am I getting a 404 error when using an HttpClient object to connect to my WebApi service using HttpGet, but when I use HttpPost, it works correctly?

Was it helpful?

Solution

The problem is the parameter naming in your Fetch method.

If you change it to id as per the route specified it should work:

[HttpGet]
public CreditCard Fetch(int id) // , bool masked
{
   ...
}

Or, alternatively, you could call the api with the named param (e.g. api/card/?cardid=2)

OTHER TIPS

In Web API 2 you can use Attribute Routing

[Route("api/card/{cardid:int}")]
[HttpGet]
public CreditCard Fetch(int cardid)
{
    ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top