Click here to Skip to main content
15,887,373 members
Articles / Web Development / ASP.NET / ASP.NETvNext

How Do You Call a Web API Endpoint Without Using JavaScript?

Rate me:
Please Sign up or sign in to vote.
3.36/5 (5 votes)
4 Jan 2016CPOL2 min read 14.6K   5   1
How do you call a Web API Endpoint without using JavaScript?

Ever had to call an API from your MVC app? A lot of the time, you can use JavaScript. But there are times when the client-side approach just doesn't cut it. Maybe your app needs to use the API as if it were a database, or you’re calling a public API. Chances are you need to transform the data somehow before it gets anywhere near the browser. Looks like you’ll have to call the API from your C# code. Sounds simple enough, right? Trouble is, you can’t seem to find any examples showing how to do this. You know how to do it using jQuery via a simple AJAX call. Can you do it in C# though?

HttpClient to the Rescue

The good news is that you can and it’s quite straightforward. HttpClient exists for just this kind of scenario. In this post, we’ll look at how to call a WebAPI Controller endpoint from MVC. By default, WebAPI Controller actions return JSON. So when you call them, you get back a big string. You then parse this string into an object inside your MVC application and you're good to go. Let’s see this in action.

View the original article

In our scenario, we've got a simple WebAPI Controller that returns a product by its id. The JSON returned looks something like this:

C#
{"ProductId":3,"Name":"Product 3","Description":"Description 3",
"CreatedOn":"2015-11-13T17:01:18.6953449+00:00"}

Let's start by creating an ApiClient that we can call to hit any API and return the result. We'll then create a specific product client that uses the ApiClient. It will hit the product API controller and return a ProductApiModel. Here’s the ApiClient:

C#
public interface IApiClient
{
    Task<HttpResponseMessage> GetFormEncodedContent
	(string requestUri, params KeyValuePair<string, string>[] values);
}

public class ApiClient : IApiClient
{
    private const string BaseUri = "Http://localhost:28601/";

    public async Task<HttpResponseMessage> 
	GetFormEncodedContent(string requestUri, params KeyValuePair<string, string>[] values)
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(BaseUri);
            using (var content = new FormUrlEncodedContent(values))
            {
                var query = await content.ReadAsStringAsync();
                var requestUriWithQuery = string.Concat(requestUri, "?", query);
                var response = await client.GetAsync(requestUriWithQuery);
                return response;
            }
        }
    }
}

Both FormEncodedContent and HttpClient expose async methods only, so the calls are both awaitable. First of all, we encode the parameters we’re passing across. We then retrieve the JSON data from the API as a string.

Data Classes

Now it’s time to turn that into an ApiModel object. Before we do that, let's have a look at the data classes we'll be using:

C#
public abstract class ApiResponse
{
    public bool StatusIsSuccessful { get; set; }
    public HttpStatusCode ResponseCode { get; set; }
    public string ResponseResult { get; set; }
}

public abstract class ApiResponse<T> : ApiResponse
{
    public T Data { get; set; }
}

public class ProductApiModel
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime CreatedOn { get; set; }
}

public class ProductResponse : ApiResponse<ProductApiModel>
{
}

The Product Client

And now the product client itself. We're introducing a base class here too with methods for decoding the JSON. This also allows us to hide the ApiClient from any calling code:

C#
public interface IProductClient
{
    Task<ProductResponse> GetProduct(int productId);
}

public class ProductClient : ClientBase, IProductClient
{
    private const string ProductUri = "api/product";

    public ProductClient(IApiClient apiClient) : base(apiClient)
    {
    }

    public async Task<ProductResponse> GetProduct(int productId)
    {
        var idPair = new KeyValuePair<string, string>("id", productId.ToString());
        return await GetJsonDecodedContent<ProductResponse, ProductApiModel>(ProductUri, idPair);
    }
}

public abstract class ClientBase
{
    private readonly IApiClient apiClient;

    protected ClientBase(IApiClient apiClient)
    {
        this.apiClient = apiClient;
    }

    protected async Task<TResponse> GetJsonDecodedContent<TResponse, TContentResponse>
	(string uri, params KeyValuePair<string, string>[] requestParameters) 
	where TResponse : ApiResponse<TContentResponse>, new()
    {
        var apiResponse = await apiClient.GetFormEncodedContent(uri, requestParameters);
        var response = await CreateJsonResponse<TResponse>(apiResponse);
        response.Data = Json.Decode<TContentResponse>(response.ResponseResult);
        return response;
    }

    private static async Task<TResponse> CreateJsonResponse<TResponse>
	(HttpResponseMessage response) where TResponse : ApiResponse, new()
    {
        var clientResponse = new TResponse
        {
            StatusIsSuccessful = response.IsSuccessStatusCode,
            ResponseCode = response.StatusCode
        };
        if (response.Content != null)
        {
            clientResponse.ResponseResult = await response.Content.ReadAsStringAsync();
        }

        return clientResponse;
    }
}

How Do We Call This?

The last thing to do is see how we could call this from an MVC controller (or anywhere else). Because our API call is asynchronous, the MVC Controller action must be asynchronous too.

C#
public class ProductController : Controller
{
    private readonly IProductClient productClient;

    public HomeController(IProductClient productClient)
    {
        this.productClient = productClient;
    }

    public async Task<ActionResult> GetProduct(int id)
    {
        var product = await productClient.GetProduct(id);
        var model = 	// Create ViewModel via some kind of mapping 
			// (check the accompanying VS solution to see this in action)
        return View(model);
    }
}

Wrapping Up

We covered a fair bit in this article. Let's recap:

  • We created an ApiClient to call out to an API endpoint
  • We wrapped that call in a ProductClient that called out to a specific endpoint to return a product
  • We parsed the JSON string from the API into a ProductApiModel within our domain
  • We hooked all of this up within an async Controller action in our MVC code

View the original article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Levelnis Ltd
United Kingdom United Kingdom
Follow along my journey as I create a newsletter about launching websites. Just message me with "I'm in" and I'll add you

Comments and Discussions

 
Questionunfortunately ... Pin
GerVenson6-Jan-16 2:34
professionalGerVenson6-Jan-16 2:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.