使用 .Net 客户端应用程序使用 Web API

Consume a Web API using a .Net Client App

我一直在学习一些教程(例如 https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client)并尝试检索作业列表并在我的 .Net 控制台应用程序中打印出来。

我正在使用的测试数据位于 https://boards-api.greenhouse.io/v1/boards/vaulttec/jobs 并提供给 client.BaseAddress.

因为我能够编译和 运行 教程成功,所以我只是使用相同的代码并将其中的一些更改为 运行 上面的测试数据(见下文)。

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace GreenhouseJobs
{
public class Job
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Location { get; set; }
    public DateTime LastUpdated { get; set; }
}

class GreenhouseJobsClient
{
    static HttpClient client = new HttpClient();

    static void ShowJob(Job job)
    {
        Console.WriteLine($"Id: {job.Id}\tTitle: " +
            $"{job.Title}\tLocation: {job.Location}\tLast Updated: {job.LastUpdated}");
    }

    static async Task<Uri> CreateJobAsync(Job job)
    {
        HttpResponseMessage response = await client.PostAsJsonAsync(
            "vaulttec/jobs", job);
        response.EnsureSuccessStatusCode();

        // return URI of the created resource.
        return response.Headers.Location;
    }

    static async Task<Job> GetJobAsync(string path)
    {
        Job job = null;
        HttpResponseMessage response = await client.GetAsync(path);
        if (response.IsSuccessStatusCode)
        {
            job = await response.Content.ReadAsAsync<Job>();
        }
        return job;
    }

    //static async Task<Product> UpdateProductAsync(Product product)
    //{
    //    HttpResponseMessage response = await client.PutAsJsonAsync(
    //        $"api/products/{product.Id}", product);
    //    response.EnsureSuccessStatusCode();

    //    // Deserialize the updated product from the response body.
    //    product = await response.Content.ReadAsAsync<Product>();
    //    return product;
    //}

    //static async Task<HttpStatusCode> DeleteProductAsync(string id)
    //{
    //    HttpResponseMessage response = await client.DeleteAsync(
    //        $"api/products/{id}");
    //    return response.StatusCode;
    //}

    static void Main()
    {
        RunAsync().GetAwaiter().GetResult();
        Console.ReadLine();
    }

    static async Task RunAsync()
    {
        // Update port # in the following line.
        client.BaseAddress = new Uri("https://boards-api.greenhouse.io/v1/boards/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        try
        {
            // Create a new product
            Job job = new Job
            {
                Id = "323232",
                Title = "Test",
                Location = "Test",
                LastUpdated = DateTime.Now
            };

            var url = await CreateJobAsync(job);
            Console.WriteLine($"Created at {url}");

            // Get the product
            job = await GetJobAsync(url.PathAndQuery);
            ShowJob(job);

            // Update the product
            //Console.WriteLine("Updating price...");
            //product.Price = 80;
            //await UpdateProductAsync(product);

            // Get the updated product
            //product = await GetProductAsync(url.PathAndQuery);
            //ShowProduct(product);

            // Delete the product
            //var statusCode = await DeleteProductAsync(product.Id);
            //Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        Console.ReadLine();
    }
}

}

问题是,当我 运行 应用程序时,它没有 return 任何东西。错误信息:"Response status code does not indicate success: 404 (Not Found)".

这行代码正在返回 404:

HttpResponseMessage response = await client.PostAsJsonAsync("vaulttec/jobs", job);

这是因为当您尝试发出 POST 请求时 URL https://boards-api.greenhouse.io/v1/boards/vaulttec/jobs returns 404。可能您需要获得授权才能创建工作。

不过,您可以向 URL 发出 GET 请求就好了。

这里有几个问题

  1. 您不仅要尝试检索,还要先创建。我不确定这个 api 是否支持 POST ,它可能不支持,因此是 404
  2. 作业实体不正确。如果您需要正确反序列化,则 Location 本身必须是一个对象,而不仅仅是一个字符串。这是 get call
  3. 的工作版本

https://pastebin.com/85NnAQY9

namespace ConsoleApp3
{

    public class JobsJson
    {
        public List<Job> Jobs { get; set; }
    }
    public class Job
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public Location Location { get; set; }
        public DateTime LastUpdated { get; set; }
    }

    public class Location
    {
        public string Name { get; set; }
    }

    class GreenhouseJobsClient
    {
        static HttpClient client = new HttpClient();

        static void ShowJobs(List<Job> jobs)
        {
            foreach (var job in jobs)
            {
                Console.WriteLine($"Id: {job.Id}\tTitle: " +
                                  $"{job.Title}\tLocation: {job.Location}\tLast Updated: {job.LastUpdated}");
            }
        }


        static async Task<List<Job>> GetJobAsync(string path)
        {
            var jobs = new List<Job>();
            HttpResponseMessage response = await client.GetAsync(path);

            if (response.IsSuccessStatusCode)
            {
                var stringResponse = await response.Content.ReadAsStringAsync();
                var re = JsonConvert.DeserializeObject<JobsJson>(stringResponse);
                jobs = re.Jobs;
            }
            return jobs;
        }

        static void Main()
        {
            RunAsync().GetAwaiter().GetResult();
            Console.ReadLine();
        }

        static async Task RunAsync()
        {
            // Update port # in the following line.
            client.BaseAddress = new Uri("https://boards-api.greenhouse.io/v1/boards/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            try
            {
                // Get the product
                var jobs = await GetJobAsync("vaulttec/jobs");
                ShowJobs(jobs);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadLine();
        }
    }
}