HttpClient 是我在 .NET Core MVC 中使用 API 的最佳选择吗

Is HttpClient My Best Option to Consume an API in .NET Core MVC

我正在制作一个 Web 应用程序 (.NET Core 3.1),目前创建了一个 API(使用 API 控制器),我想在我的 Web 应用程序中使用它(并显示它视图上的数据)。 API 是一些简单的 GET 请求,如下所示(在访问正确的端点时效果很好):

//GET: api/Fish
        [HttpGet]
        public IActionResult Get()
        {
            IEnumerable<Fish> fish = _dataRepository.GetAll();
            return Ok(fish);
        }

        //GET: api/Fish/5
        [HttpGet]
        [Route("{id}")]
        public IActionResult Get(long id)
        {
            Fish fish = _dataRepository.Get(id);

            if (fish == null)
            {
                return NotFound("The fish could not be found");
            }

            return Ok(fish);
        }

现在,在我的主页上,我想允许用户在我的表单上输入端点,我将 return 来自我的 API 的 JSON。这是我的表格:

<form class="form-inline" asp-action="Index" asp-controller="Home">
    <div class="form-group">
        <label asp-for="Endpoint">https://url.com/api/</label>
        <input type="text" class="form-control" placeholder="Try entering fish/4" asp-for="Endpoint"/>
        <button type="submit" class="btn btn-primary">GET</button>
    </div>
</form>
<div>
    @Model.ReturnedJson
</div>

这是视图模型:

public class GetDataViewModel
    {
        public string Endpoint { get; set; }
        public string ReturnedJson { get; set; }
    }

我的主页控制器获取输入的端点,并从 API:

检索 JSON
 public async Task<IActionResult> Index(GetDataViewModel model)
        {

            var url = "https://localhost:44398/api/" + model.Endpoint;

            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var data = await response.Content.ReadAsStringAsync();
                    var table = Newtonsoft.Json.JsonConvert.DeserializeObject(data);
                    model.ReturnedJson = data;
                }
            }

            return View();
    }

我想知道的是: HttpClient 是我处理这个问题的最佳选择吗?我希望有一种方法可以调用我的 API 方法,例如 ApiController().Get 但我认为这是不可能的(至少在我的研究中)。另外,是否可以直接在主页上 return RAW(最好美化)JSON,或者我需要在不同的视图上显示它吗?我不是 100% 确定我的方法应该是 returning 代替 return View() 来显示 JSON 数据。

编辑:

[HttpGet]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Index(GetDataViewModel model)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44398/api/" + model.Endpoint);
            var client = _clientFactory.CreateClient();
            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsStringAsync();
                model.ReturnedJson = JsonConvert.SerializeObject(data, Formatting.Indented);
            }

            return View(model);
        }

这些都是我在控制器中的 Index 方法。当网络应用程序启动时,我似乎得到了 Sustem.NullReferenceException。我假设这是因为我的模型没有在加载时传入(第一个 Index 方法),但是如果我将它添加到那里,我会收到一个错误,因为它与第二个 Index 方法的声明相同。以下是我的看法:

@model TheFishAPI.Models.ViewModels.GetDataViewModel

@{
    ViewData["Title"] = "Home Page";
}

<form class="form-inline" asp-action="Index" asp-controller="Home">
    <div class="form-group">
        <label asp-for="Endpoint">https://url/api/</label>
        <input type="text" class="form-control" placeholder="Try entering fish/4" asp-for="Endpoint"/>
        <button type="submit" class="btn btn-primary">GET</button>
    </div>
</form>
<div>
    @if (!string.IsNullOrEmpty(Model.ReturnedJson))
    {
        Html.Raw(Model.ReturnedJson);
    }
</div>

您有几个选择:

  1. 我个人会做这个。如果你的 api 没有任何 Cors 问题,我会直接使用 JavaScript 或 jquery Ajax 调用它,它们也有支持 rest 调用的库。这将绕过通过您的控制器的需要,而且它可以以 ajax 方式完成。如果你走这条路,你甚至可以这样做来漂亮地打印你的 json:

    JSON.stringify({ uno: 1, dos: 2 }, null, '\t');

  2. 如果你只需要公开你的 api 端点,你看过 swagger ui 了吗?可能这不是您需要的,但查看您共享的代码,似乎这就是您正在创建的。

  3. HTTP 客户端工厂确实是比使用 http 客户端更好的方法。 以下是一些可用于使用 REST apis:
  4. 的库

https://code-maze.com/different-ways-consume-restful-api-csharp/amp/

漂亮的打印: 在 C# 中,你可以做类似 JsonConvert.SerializeObject(object, Formatting.Indented); 的事情 漂亮的打印,但确保你使用原始标签助手添加它,或者像这样在视图上缩进它:

@Html.Raw(JsonConvert.SerializeObject(ModelProperty, Formatting.Indented))

最后,对于您的 return 视图,您可以 return 填充 json 的相同模型,只需确保在操作中或直接在视图中缩进以漂亮打印它。

public async Task<IActionResult> Index(GetDataViewModel model)
        {

            var url = "https://localhost:44398/api/" + model.Endpoint;

            using (HttpClient client = new HttpClient())
            {
                client.BaseAddress = new Uri(url);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage response = await client.GetAsync(url);
                if (response.IsSuccessStatusCode)
                {
                    var data = await response.Content.ReadAsStringAsync();
      // deserialize first since json is your response type
 var table=Newtonsoft.Json.JsonConvert.DeserializeObject(data);
// re serialize with formatting:
                    model.ReturnedJson = JsonConvert.SerializeObject(table, Formatting.Indented);
                }
            }

            return View(model);
    }

在你看来这样做:

<pre>
    @Html.Raw(Model.ReturnedJson) 
</pre>