What is the correct package to create an HTTP client in a WPF Core3 desktop app?

Michael 81 Reputation points
2020-06-18T11:50:13.437+00:00

I have a WPF desktop app using Microsoft.WnidowsDesktop.App.WPF and Microsoft.NETCore.App v3.1. I would like to add an HTTP client for simple GET/POST...

What is the correct package to add an HTTP client so I can accomplish WPF-REST Web API consumption? Per chance is it Microsoft.AspNet.WebApi.Client?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,709 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,311 Reputation points
    2020-06-18T13:34:51.03+00:00

    Hi, you can use System.Net.Http.HttpClient.GetAsync like in following demo. Only NewtonSoft.Json is necessary.

    <Window x:Class="WpfApp1.Window03"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp03"
            mc:Ignorable="d"
            Title="Window03" Height="450" Width="800">
      <Window.DataContext>
        <local:ViewModel/>
      </Window.DataContext>
      <Grid>
        <DataGrid Name="DGD_UserList" 
                  AutoGenerateColumns="False"  
                  ItemsSource="{Binding ContentModels}">
          <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Name}" Header="Object Id" IsReadOnly="True"/>
            <DataGridTextColumn Binding="{Binding ProductUrl}" Header="Continent" IsReadOnly="True"/>
          </DataGrid.Columns>
        </DataGrid>
      </Grid>
    </Window>
    

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Net.Http;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows;
    
    namespace WpfApp03
    {
      public class ViewModel : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
    
        private static string _RootUrl = @"https://api.predic8.de/shop/products/";
        private AsyncObservableCollection<ContentModel> _ContentModels = null;
    
        public AsyncObservableCollection<ContentModel> ContentModels
        {
          get { return _ContentModels; }
          set { _ContentModels = value; OnPropertyChanged(); }
        }
        public ViewModel() => this.ContentModels = this.GetContentData();
    
        #region "Read"
        private AsyncObservableCollection<ContentModel> GetContentData()
        {
          AsyncObservableCollection<ContentModel> ReturnContentModles = null;
          Task<AsyncObservableCollection<ContentModel>> ContentTask = this.GetContentModels();
          ContentTask.Wait();
          if (ContentTask.Result.Count > 0) ReturnContentModles = ContentTask.Result;
          return ReturnContentModles;
        }
        private async Task<AsyncObservableCollection<ContentModel>> GetContentModels()
        {
          AsyncObservableCollection<ContentModel> ReturnContinentModels = new AsyncObservableCollection<ContentModel>();
          try
          {
            using (HttpClient httpClient = new HttpClient())
            {
              httpClient.DefaultRequestHeaders.Add("Accept", "application/json;charset=UTF-8");
              using (HttpResponseMessage HttpResponseMessage = await httpClient.GetAsync(string.Concat(_RootUrl, ""), HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
              {
                if (HttpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                  using (HttpContent HttpContent = HttpResponseMessage.Content)
                  {
                    string MyContent = await HttpContent.ReadAsStringAsync();
                    var root = JsonConvert.DeserializeObject<RootObject>(MyContent);
                    ReturnContinentModels = new AsyncObservableCollection<ContentModel>(root.products);
                  }
              }
            }
          }
          catch (Exception ex) { Console.WriteLine(ex.Message); }
          return ReturnContinentModels;
        }
        #endregion
    
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    
      public class AsyncObservableCollection<T> : ObservableCollection<T>
      {
        private readonly SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
        public AsyncObservableCollection() { }
        public AsyncObservableCollection(IEnumerable<T> list) : base(list) { }
        private void ExecuteOnSyncContext(Action action)
        {
          if (SynchronizationContext.Current == _synchronizationContext) action();
          else _synchronizationContext.Send(_ => action(), null);
        }
        protected override void InsertItem(int index, T item) => ExecuteOnSyncContext(() => base.InsertItem(index, item));
        protected override void RemoveItem(int index) => ExecuteOnSyncContext(() => base.RemoveItem(index));
        protected override void SetItem(int index, T item) => ExecuteOnSyncContext(() => base.SetItem(index, item));
        protected override void MoveItem(int oldIndex, int newIndex) => ExecuteOnSyncContext(() => base.MoveItem(oldIndex, newIndex));
        protected override void ClearItems() => ExecuteOnSyncContext(() => base.ClearItems());
      }
    
      public class RootObject
      {
        public Meta meta { get; set; }
        public List<ContentModel> products { get; set; }
      }
    
      public class Meta
      {
        public int count { get; set; }
        public int limit { get; set; }
        public int page { get; set; }
        public string next_url { get; set; }
      }
    
      public class ContentModel
      {
        [JsonProperty("name")]
        public string Name { get; set; }
    
        [JsonProperty("product_url")]
        public string ProductUrl { get; set; }
      }
    }