65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 WebApiClient 调用 ASP.NET WebApi 等 RESTful 服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (11投票s)

2014 年 7 月 10 日

CPOL

2分钟阅读

viewsIcon

42671

downloadIcon

540

在本教程的第一部分,我们将学习如何使用 NuGet 包 WebApiRestService.WebApiClient 调用 Web Api REST 服务。

引言

在本教程的第一部分,我们将学习如何使用 NuGet 包WebApiRestService.WebApiClient调用 Web Api REST 服务。

什么是 WebApiClient?

WebApiClient 是一个简单而强大的 .NET 可移植库,它作为应用程序和RESTful 服务(如 Microsoft WebApi)之间的中间层。它提供使用HttpClient 类发出异步、类型化WebApi 请求的方法。它负责创建请求、等待响应、处理异常并将响应转换为对象的所有逻辑,使您无需编写重复代码。

特点

  • 它是可移植的。支持 .NET Framework 4.5+、Windows 8+ 应用、Windows Phone Silverlight 8+
  • 支持任何类型的 RESTful 服务,不仅限于 Microsoft WebApi
  • 可以与使用 ASP.NET Identity 安全性的服务一起使用
  • 使用 NuGet 轻松安装
  • 支持 Json 和 Xml 序列化/反序列化
  • 支持 GET、POST、PUT 和 DELETE 方法
  • 易于扩展功能
  • 包含 WindowsIntegratedAuthentication(Negotiate、NTLM、Basic、Kerberos)和 BearerTokenAuthentication
  • 易于发送或接收 Cookie

资源

您可以在以下网址找到更多信息和示例:http://webapiclient.azurewebsites.net
要下载 NuGet 包:https://nuget.net.cn/packages/WebApiRestService.WebApiClient

使用代码

首先,您需要设置一个解决方案,至少包含 3 个项目

  1. 一个 WebApi 项目
  2. 一个 MVC 项目(您可以选择您想要的项目类型)
  3. 一个类库项目,用于容纳 DTO 对象

在类库项目中

  • 创建以下类
public class Restaurant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
}

在 WebApi 项目中

  • 添加对您在上一步中创建的 DTO类库项目的引用。
  • 创建一个名为 RestaurantController 的控制器,并粘贴此类
public class RestaurantController : ApiController
{
    List<Restaurant> restaurants = new List<Restaurant>() {
        new Restaurant(){ Id = 1, Name = "Restaurant 1", Address = "1111 Oxford Street" },
        new Restaurant(){ Id = 2, Name = "Restaurant 2", Address = "2222 Oxford Street" },
        new Restaurant(){ Id = 3, Name = "Restaurant 3", Address = "3333 Oxford Street" },
        new Restaurant(){ Id = 4, Name = "Restaurant 4", Address = "4444 Oxford Street" }
    };

    // GET: api/Restaurant
    public IEnumerable<Restaurant> Get()
    {
        return restaurants;
    }
    
    // GET: api/Restaurant/5
    public Restaurant Get(int id)
    {
        return restaurants.SingleOrDefault(r => r.Id == id);
    }

    // POST: api/Restaurant
    public void Post([FromBody]Restaurant value)
    {
        restaurants.Add(value);
    }

    // PUT: api/Restaurant/5
    public void Put([FromBody]Restaurant value)
    {
        restaurants.RemoveAll(r => r.Id == value.Id);
        restaurants.Add(value);
    }

    // DELETE: api/Restaurant/5
    public void Delete(int id)
    {
        restaurants.RemoveAll(r => r.Id == id);
    }
}

在 MVC 项目中

  • 添加对 DTO 类库项目的引用
  • 打开程序包管理器控制台并运行以下命令来安装WebApiClient(更多详细信息,请参见这里这里

Install-Package WebApiRestService.WebApiClient

  • 创建一个名为 RestaurantsController 的控制器,并粘贴此类
public class RestaurantsController : Controller
{
    private WebApiClientOptions options = 
                    new WebApiClientOptions("https://:60214/api", "restaurant");

    public async Task<ActionResult> Index()
    {
        List<Restaurant> list = null;

        using(WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            list = await client.GetManyAsync();
        }

        return View(list);
    }

    public async Task<ActionResult> IndexOldFashioned()
    {
        List<Restaurant> list = null;

        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri("https://:60214/api/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
                                new MediaTypeWithQualityHeaderValue("application/json"));

        var response = await client.GetAsync("restaurant");

        if (!response.IsSuccessStatusCode)
        {
            return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); 
        }

        list = await response.Content.ReadAsAsync<List<Restaurant>>();
        
        return View("Index", list);
    }

    public async Task<ActionResult> Details(int? id)
    {
        Restaurant restaurant = null;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(id);
        }
        
        if (restaurant == null)
        {
            return HttpNotFound();
        }
        
        return View(restaurant);
    }

    public ActionResult Create()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(Restaurant restaurant)
    {
        if (ModelState.IsValid)
        {
            using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
            {
                await client.CreateAsync(restaurant);
            }
            
            return RedirectToAction("Index");
        }

        return View(restaurant);
    }

    public async Task<ActionResult> Edit(int? id)
    {
        Restaurant restaurant = null;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        
        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(id);
        }
        
        if (restaurant == null)
        {
            return HttpNotFound();
        }
        
        return View(restaurant);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(Restaurant restaurant)
    {
        if (ModelState.IsValid)
        {
            using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
            {
                await client.EditAsync(restaurant);
            }
            
            return RedirectToAction("Index");
        }
        
        return View(restaurant);
    }

    public async Task<ActionResult> Delete(int? id)
    {
        Restaurant restaurant = null;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        
        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(id);
            
            if (restaurant == null)
            {
                return HttpNotFound();
            }
        }
        
        return View(restaurant);
    }

    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> DeleteConfirmed(Restaurant restaurant)
    {
        if (restaurant == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(restaurant.Id);

            if (restaurant == null)
            {
                return HttpNotFound();
            }

            await client.DeleteAsync(restaurant.Id);
        }

        return RedirectToAction("Index");
    }
}

现在,您可以运行 MVC 项目,指向类似于 https://:60232/restaurants/ 的 URL 并查看结果。

正如您在上面的代码中看到的,使用WebApiClient调用RESTful 服务非常简单。您只需创建一个WebApiClientOptions对象,根据需要进行配置

private WebApiClientOptions options = 
    new WebApiClientOptions("https://:60214/api", "restaurant");

然后开始使用WebApiClient对象来调用您的服务。请查看 Index 操作方法

public async Task<ActionResult> Index()
{
    List<Restaurant> list = null;

    using(WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
    {
        list = await client.GetManyAsync();
    }

    return View(list);
}

如果您一直在使用HttpClient,请查看下一个操作方法……您应该编写类似这样的代码

public async Task<ActionResult> IndexOldFashioned()
{
    List<Restaurant> list = null;

    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("https://:60214/api/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new 
                         MediaTypeWithQualityHeaderValue("application/json"));

    var response = await client.GetAsync("restaurant");

    if (!response.IsSuccessStatusCode)
    {
        return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); 
    }

    list = await response.Content.ReadAsAsync<List<Restaurant>>();
    
    return View("Index", list);
}

现在,如果您比较这两个不同的操作方法,您可能会发现传统方法(使用HttpClient)比使用WebApiClient的方法更难阅读和维护。当您添加更多配置(如身份验证)时,代码会变得更加复杂。

其他特性

WebApiClient 库还有许多其他功能,我们将在后续教程中介绍。

  • 身份验证
  • Cookie
  • 继承
  • 异常处理
  • 线程
  • 超时

 

 

 

 

 

© . All rights reserved.