【问题标题】:Want to centralize code for calling my Web API想要集中调用我的 Web API 的代码
【发布时间】:2014-12-07 05:55:01
【问题描述】:

在我的 MVC 应用程序中,我进行了很多需要几行代码的 Web API 调用。我想创建一个用于进行 API 调用的集中式方法,并将一些简单的参数传递给它,例如调用类型(GET、POST 等)、Url 等。

我需要帮助的地方是,在每种情况下,我都会返回不同的对象类型,例如Employee、List 等。如何返回不同的对象类型?

另一个问题是,如果我想进行 POST 或 PUT 调用,我会将不同类型的对象传递到我的集中式 API 调用方法中。同样,我有同样的问题,我必须能够接受不同的对象类型。

我想,我可以将 Json 对象传入传出,但我不确定这是正确的方法还是有更好的方法。我相信其他人已经尝试过集中他们的 Web API 调用代码。

* 更新 * 这是我到目前为止所拥有的,但我需要更多帮助。如何返回结果?

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;
      }
   }
}

【问题讨论】:

  • 可以从您想要集中的代码中显示 2 个示例吗?您也许可以为您的代码创建一个基类,或创建调用处理程序类,但在这两种情况下,您都必须使用泛型来传递参数和返回类型。
  • 刚刚用我想出的示例代码更新了我的原始帖子。我以前从未返回过通用对象,所以我试图了解我是如何做到这一点的。我在代码中不清楚的另一部分是当我从我的 Web API 收到错误响应时。那我会返回什么?
  • 太好了,让我给你写一些代码,然后在这里发布。

标签: c# asp.net-mvc asp.net-web-api2


【解决方案1】:

试试这个:这是一个起点,您可以在此基础上进行构建,但想法是 ApiCaller 是一个实现接口 IApiCaller 的类(因此您可以稍后对其进行模拟),并且该类使用相同的选项启动 HttpClient /headers,方法会使用/dispose这个HttpClient连接服务器,每个方法定义调用者调用方法时的返回类型T(如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;
    }
}

你可以像这样使用这个类:

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;
    }
}

希望对您有所帮助。

【讨论】:

  • 这段代码看起来不错,也很精致,但有些东西超出了我的水平。你能帮助我理解它吗?首先,我无法从需要进行 API 调用的 MVC 操作方法中调用它。我尝试了 MyApp.ApiCaller.Get() 但所有智能感知给我的是 Equals 和 ReferenceEquals。我没有看到 Get 方法。我也不清楚你为什么要从 IApiCaller 接口继承。它有什么好处?
  • 1- 以前您的 GetApiCaller 方法是静态方法,但我已将其更改为实例方法,这意味着您必须通过 new 初始化 ApiCaller 类。 2- 我使用了接口 IApiCaller,因此您可以模拟此类进行单元测试,谷歌“Moq 库”或“C# 单元测试”以了解有关单元测试的更多信息。 3- 你的 MVC 控制器将获得 IApiCaller 接口注入它,你可以使用像 Autofac 这样的 IoC 容器来设置依赖项。这足够清楚还是您需要更多?
  • 我有点清楚,但我不想占用您太多时间。你已经超级有帮助了!如果你不介意的话,我还想再问一个问题。将其设为静态类不是更好,这样我就不必在每次需要进行 API 调用时都创建 ApiCaller 类的新实例吗?
  • 不用担心,当您开始使用代码时,一切都会变得有意义;)并在它之上构建。如果我的代码有帮助,请将您的问题标记为有帮助/已回答,以便其他人寻找相同的场景。
  • 如果您不想依赖 Ioc 容器为您初始化 ApiCaller 类,我在上面的代码中添加了一个空构造函数,如果还有不清楚的地方请告诉我。
【解决方案2】:

要么返回一个对象,要么使用动态返回类型。

【讨论】:

  • 我需要更多帮助。我如何返回“结果”。另外,如果我的 Web API 调用出错了,我应该返回什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 2012-05-05
  • 2014-11-16
相关资源
最近更新 更多