Является ли HttpClient лучшим вариантом для использования API в. NET Core MVC - PullRequest
0 голосов
/ 02 мая 2020

Я делаю веб-приложение (. NET Core 3.1), и в настоящее время у меня есть созданный API (с использованием контроллера API), который я хочу использовать в своем веб-приложении (и отображать его данные в представлении). 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);
        }

Теперь на моей домашней странице я хочу разрешить пользователю вводить конечную точку на моя форма, и я верну JSON из моего API. Это моя форма:

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

И контроллер моей домашней страницы, чтобы получить введенную конечную точку и получить JSON из API:

 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, но я не думаю, что это возможно (по крайней мере, в моем исследовании). Кроме того, возможно ли вернуть RAW (предпочтительно предварительно подтвержденный) JSON непосредственно на главной странице или мне нужно будет показать его в другом представлении? Я не уверен на 100%, что мой метод должен возвращать вместо 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);
        }

Это оба моих метода индекса в контроллере. Кажется, я получаю исключение 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 Ответ

0 голосов
/ 02 мая 2020

У вас есть несколько вариантов:

  1. Я бы лично сделал это. Если у вашего API нет проблем с Cors, я бы назвал его напрямую, используя JavaScript или jquery Ajax, у них также есть библиотеки, которые поддерживают остальные вызовы. Это позволит обойти необходимость go через ваши контроллеры, плюс это может быть сделано ajax способом. Если вы go этот маршрут, вы даже можете сделать это, чтобы довольно распечатать ваш json:

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

  2. Если все, что вам нужно, это выставить свои конечные точки API, вы смотрели на пользовательский интерфейс Swagger? Может быть, это не то, что вам нужно, но, глядя на код, которым вы поделились, кажется, что это то, что вы создаете.

  3. Фабрика Http-клиента действительно лучше, чем использование http-клиента. Вот некоторые из библиотек, которые вы можете использовать для использования REST API:

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

Хорошая печать: в c# вы можете сделать что-то вроде JsonConvert.SerializeObject(object, Formatting.Indented); для красивой печати, но убедитесь, что вы добавили его с помощью Raw tag helper или просто сделали отступ в представлении следующим образом:

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

Последнее для вашего обратного просмотра. Вы можете вернуть ту же модель, в которой вы Заполните 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);
    }

По вашему мнению, сделайте следующее:

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