【问题标题】:Consuming WEB API using HttpClient in c# console application在 c# 控制台应用程序中使用 HttpClient 使用 WEB API
【发布时间】:2018-03-08 18:04:26
【问题描述】:

我在 Visual Studio 2015 中使用 MySQL 数据库创建了一个 Web API。 API 运行良好。

所以我决定制作一个控制台client 应用程序,我可以在其中使用我的网络服务(网络 API)。客户端代码基于HttpClient,在API中我使用了HttpResponse。现在,当我运行控制台应用程序代码时,我什么也得不到。以下是我的代码:

class meters_info_dev
{
    public int id { get; set; }
    public string meter_msn { get; set; }
    public string meter_kwh { get; set; }
}

这个类和我的 web API 模型类一样:

Web API 中的模型

namespace WebServiceMySQL.Models
{

using System;
using System.Collections.Generic;

public partial class meters_info_dev
{
    public int id { get; set; }
    public string meter_msn { get; set; }
    public string meter_kwh { get; set; }
}

控制台应用程序代码

static HttpClient client = new HttpClient();

static void ShowAllProducts(meters_info_dev mi)
{
    Console.WriteLine($"Meter Serial Number:{mi.meter_msn}\t Meter_kwh: {mi.meter_kwh}", "\n");
}

static async Task<List<meters_info_dev>> GetAllRecordsAsync(string path)
{
    List<meters_info_dev> mID = new List<meters_info_dev>();
    HttpResponseMessage response = await client.GetAsync(path);
    if (response.IsSuccessStatusCode)
    {
        mID = await response.Content.ReadAsAsync<List<meters_info_dev>>();
    }
    else
    {
        Console.WriteLine("No Record Found");
    }
    return mID;
}

static void Main()
{
    RunAsync().Wait();
}

static async Task RunAsync()
{
    client.BaseAddress = new Uri("http://localhost:2813/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var m = await GetAllRecordsAsync("api/metersinfo/");

    foreach(var b in m)
    {
        ShowAllProducts(b);
    }
}

在我的 API 中,我在单个控制器下有 3 个 GET 方法,因此我为它们创建了不同的路由。它们的 URL 也不同。

  1. http://localhost:2813/api/metersinfo/ 将返回所有记录

在调试代码的时候发现List&lt;meters_info_dev&gt; mID = new List&lt;meters_info_dev&gt;();是空的:

虽然回复是302 Found,但网址也是正确的:

更新 1

根据一个建议,我做了以下事情:

using (var client = new HttpClient())
{
    List<meters_info_dev> mID = new List<meters_info_dev>();
    HttpResponseMessage response = await client.GetAsync(path);
    if (response.IsSuccessStatusCode)
    {
        mID = await response.Content.ReadAsAsync<List<meters_info_dev>>();
    }
    else
    {
        Console.WriteLine("No Record Found");
    }
   return mID;
}

当我运行应用程序时,我收到异常“提供了无效的请求 URI。请求 URI 必须是绝对 URI 或必须设置 BaseAddress。”

更新 2

我添加了一段新代码:

using (var cl = new HttpClient())
{
    var res = await cl.GetAsync("http://localhost:2813/api/metersinfo");
    var resp = await res.Content.ReadAsStringAsync();
}

在回复中,我得到了所有记录:

我不知道为什么它不能与其他逻辑一起使用以及问题是什么。我还阅读了Httpclient consume web api via console app C#Consuming Api in Console Application 的问题。

任何帮助将不胜感激。

【问题讨论】:

  • 在您的第一个屏幕截图中,您将在mID 列表初始化之后立即停留。所以,它不可能被填充。在return mID; 语句中放置一个断点并再次检查。
  • @astef return mID 上的计数为零 (0)

标签: c# rest api asp.net-web-api2


【解决方案1】:

代码需要做很多工作。

您突出显示的行将始终为空,因为这是您初始化变量的位置。你想要的是通过代码运行,直到你从调用中得到结果。

首先,确保你的 api 确实有效,你可以在浏览器中调用你想要的 GET 方法并看到结果。

 using (var client = new HttpClient())
 {
      var result = await client.GetAsync("bla");
      return await result.Content.ReadAsStringAsync();
 } 

这当然是一个例子,所以用你的特定数据和方法替换它。

现在,当您仅仅因为您的 response.IsSuccessStatusCode 为 false 而检查结果时,这并不意味着没有记录。这意味着呼叫完全失败。空列表的成功结果与完全失败不同。

如果你想看看你得到了什么,你可以稍微修改一下你的代码:

if(response.IsSuccessStatusCode)
        {
            var responseData = await response.Content.ReadAsStringAsync();
            //more stuff
        }

在这一行放一个断点,看看你实际上得到了什么,然后你担心将结果投射到你的对象列表中。只需确保您在浏览器中测试调用时获得的结果与您获得的相同。

编辑后的更多细节。

为什么不稍微简化一下代码。

例如,只需一次性设置请求的 URL:

 using (var client = new HttpClient())
            {
                var result = await client.GetAsync("http://localhost:2813/api/metersinfo");
                var response = await result.Content.ReadAsStringAsync();
                 //set debug point here and check to see if you get the correct data in the response object
            }

您一天中的第一个任务是查看您是否可以点击 url 并获取数据。 一旦得到正确的响应,您就可以担心基址。一旦你有一个工作样本,就从简单开始,然后从那里开始。

好的,既然您收到了回复,您可以使用 Newtonsoft.Json 之类的东西将字符串序列化回对象列表。这是一个 NuGet 包,你可能已经安装了它,如果不只是添加它。

在文件顶部添加 using 语句。

using Newtonsoft.Json;

然后你的代码变成这样:

using (var client = new HttpClient())
 {
      var result = await client.GetAsync("bla");
      var response = await result.Content.ReadAsStringAsync();
      var mID = JsonConvert.DeserializeObject<List<meters_info_dev>>(response);
 } 

此时,您应该拥有对象列表,您可以做任何其他需要的事情。

【讨论】:

  • 我已经根据您的建议进行了处理。请查看我的更新代码
  • 添加了另一个与请求的 URL 相关的建议
  • 对此不确定:“从最佳实践的角度来看,您希望在 using 语句中使用 HttpClient...”请参阅:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
  • 公平点,我们可以更改代码以考虑到这一点。看看我们是否可以先点击 URL 并获取一些数据仍然会很好
  • @AndreiDragotoniu 请检查我更新的问题。我添加了你建议的一段新代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 2018-01-29
  • 2017-07-04
相关资源
最近更新 更多