Sam
Sam

Reputation: 30298

Want to centralize code for calling my Web API

In my MVC app, I make a lot of Web API calls that require a few lines of code. I'd like to create a centralized method for making API calls and just pass some simple parameters into it e.g. call type (GET, POST, etc), the Url, etc.

Where I need help is that in each scenario, I will return a different object type e.g. Employee, List<Project>, etc. How do I return different object types?

The other issue is that if I want to make a POST or PUT call, I will pass different types of objects into my centralized API call method. Again, I have the same issue, where I have to be able to accept different object types.

I guess, I can just pass Json objects in and out but I'm not sure if that's the right approach or there's a better approach out there. I'm sure others have tried to centralize their Web API call code.

* UPDATE * Here's what I have so far but I need a bit more help. How do I return the result?

public static async Task<object> GetApiCall(string apiActionUrl)
{
   using (var client = new HttpClient())
   {
      client.BaseAddress = new Uri("http://myApiBaseUrl");
      client.DefaultRequestHeaders.Accept.Clear();
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

      HttpResponseMessage response = await client.GetAsync(apiActionUrl);
      if (response.IsSuccessStatusCode)
      {
         var result = response.Content.ReadAsStringAsync().Result;
      }
   }
}

Upvotes: 2

Views: 1079

Answers (2)

Omar.Alani
Omar.Alani

Reputation: 4130

Try this : this is a starting point, you can build on this, but the idea is ApiCaller is a class that implements an interface IApiCaller (so you can mock it later), and this class starts the HttpClient with the same options/headers, and the method will use/dispose this HttpClient to connect to the server, and each method defines the return type T when the caller calls the method (like Get).

public interface IApiCaller
{
    Task<T> Get<T>(string apiActionUrl);
}

public class ApiCaller : IApiCaller
{
    private const string ApiBaseUrl = "http://myApiBaseUrl";

    public async Task<T> Get<T>(string apiActionUrl)
    {
        using (var client = GetHttpClient())
        {
            var response = await client.GetAsync(apiActionUrl);
            if (response.IsSuccessStatusCode)
            {
                var jsonString = response.Content.ReadAsStringAsync().Result;
                return JsonConvert.DeserializeObject<T>(jsonString);
            }
        }

        return default(T);
    }

    private static HttpClient GetHttpClient()
    {
        var client = new HttpClient
        {
            BaseAddress = new Uri(ApiBaseUrl),
        };

        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        return client;
    }
}

you can use this class like this:

public class SomeMvcController : Controller
{
    private readonly IApiCaller _apiCaller;

    // use this if you don't want to rely on Dependency Injection, OR
    // if you don't use Ioc container for now.     
    public SomeClass(): this(new ApiCaller())
    {
    }

    public SomeClass(IApiCaller apiCaller)
    {
        _apiCaller = apiCaller;
    }

    public async Task<string> GetStringFromWebApi()
    {
        string result = await _apiCaller.Get<string>("myApiUrl");

        return result;
    }
}

Hope that helps.

Upvotes: 1

zaitsman
zaitsman

Reputation: 9509

Either return a object or use dynamic return type.

Upvotes: 0

Related Questions