ASP.NET WebApi 增删改查

本篇是接着上一篇《ASP.NET WebApi 入门》来介绍的。

前言

     习惯说 CRUD操作,它的意思是"创建、 读取、 更新和删除"四个基本的数据库操作。许多 HTTP 服务通过REST的 Api 进行CRUD 操作。在本教程中,生成非常简单的 web API 来管理产品的列表。每个产品将包含名称、 价格和类别,再加上一个产品 id。访问Uri对应如下:

行动HTTP 方法相对 URI
获取所有产品的列表 GET /api/Product
根据ID得到一个产品 GET /api/Product/id
根据Category获取产品的列表 GET /api/Product?Category=类别
创建一个新的产品 POST /api/Product
根据ID更新一个产品 PUT /api/Product/id
根据ID删除一个产品 DELETE /api/Product/id
添加仓储库

      在Models文件夹下,创建IProductRepository.cs:      

using System.Collections.Generic;

namespace ApiDemo01.Models
{
    /// <summary>仓储操作接口</summary>
    public interface IProductRepository
    {
        IEnumerable<Product> GetAll();
        Product Get(int id);
        Product Add(Product item);
        void Remove(int id);
        bool Update(Product item);
    }
}

  在Models文件夹下,创建ProductRepository.cs:

using System;
using System.Collections.Generic;

namespace ApiDemo01.Models
{
    /// <summary>仓储操作实现</summary>
    public class ProductRepository : IProductRepository
    {
        private List<Product> products = new List<Product>();
        private int _nextId = 1;

        public ProductRepository()
        {
            Add(new Product { Name = "Tomato soup", Category = "Groceries", Price = 1.39M });
            Add(new Product { Name = "Yo-yo", Category = "Toys", Price = 3.75M });
            Add(new Product { Name = "Hammer", Category = "Hardware", Price = 16.99M });
        }

        public IEnumerable<Product> GetAll()
        {
            return products;
        }

        public Product Get(int id)
        {
            return products.Find(p => p.ID == id);
        }

        public Product Add(Product item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.ID = _nextId++;
            products.Add(item);
            return item;
        }

        public void Remove(int id)
        {
            products.RemoveAll(p => p.ID == id);
        }

        public bool Update(Product item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = products.FindIndex(p => p.ID == item.ID);
            if (index == -1)
            {
                return false;
            }
            products.RemoveAt(index);
            products.Add(item);
            return true;
        }
    }
}

  注:存储库中保持在本地内存中的列表。在实际的应用中,您将存储的数据在外部,任一数据库或在云存储中。存储库模式将使易于更改以后实施。

修改控制器

      由于是接着上一篇博文介绍的项目,所以这里修改Controllers文件下的ProductController.cs: 

using ApiDemo01.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace ApiDemo01.Controllers
{
    public class ProductController : ApiController
    {
        //TODO:接口引用具体实例(后面介绍MEF,使得接口解除使用具体实现)
        static readonly IProductRepository repository = new ProductRepository();

        //获取所有产品
        public IEnumerable<Product> GetAllProducts()
        {
            return repository.GetAll();
        }

        //根据ID获取一个产品
        public Product GetProduct(int id)
        {
            Product item = repository.Get(id);
            if (item == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return item;
        }

        //根据类别获取产品列表
        public IEnumerable<Product> GetProductsByCategory(string category)
        {
            return repository.GetAll().Where(
                p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
        }

        //添加一个产品
        //默认情况下,Web API 框架将响应状态代码设置为 200 (OK)。
        //但根据 HTTP/1.1 协议中,当 POST 请求的结果在创造一种资源,服务器应该回复状态为 201 (已创建)。

        //服务器将创建一个资源,它应在响应的位置标题中包括的新的资源的 URI。

        //public Product PostProduct(Product item)
        //{
        //    item = repository.Add(item);
        //    return item;
        //}

        //对上面方法进行改进
        //返回类型现在是HttpResponseMessage。
        //通过返回HttpResponseMessage而不是产品,我们可以控制的 HTTP 响应消息,包括状态代码和位置标头的详细信息。
        public HttpResponseMessage PostProduct(Product item)
        {
            item = repository.Add(item);
            //创建的HttpResponseMessage ,并自动将产品对象的序列化表示形式写入到身体火炭的响应消息。
            var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);

            string uri = Url.Link("DefaultApi", new { id = item.ID });
            response.Headers.Location = new Uri(uri);
            return response;
        }

        //根据ID更新一个产品
        public void PutProduct(int id, Product product)
        {
            product.ID = id;
            if (!repository.Update(product))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        //根据ID删除一个产品
        public void DeleteProduct(int id)
        {
            Product item = repository.Get(id);
            if (item == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            repository.Remove(id);
        }
    }

    #region 此段代码是上一篇博文里介绍的方式,这里注释掉
    //public class ProductController : ApiController
    //{
    //    //模拟数据
    //    List<Product> pList = new List<Product>
    //    { 
    //        new Product{ID=1, Name="Dell", Category="电脑" , Price=3500 },
    //        new Product{ID=2, Name="Apple", Category="手机" , Price=5500 },
    //        new Product{ID=3, Name="HP", Category="电脑" , Price=3000 }
    //    };

    //    //获取产品集合
    //    public IEnumerable<Product> GetProducts()
    //    {
    //        return pList;
    //    }

    //    //根据产品ID获取一个产品
    //    public IHttpActionResult GetProduct(int id)
    //    {
    //        var product = pList.FirstOrDefault((p) => p.ID == id);
    //        if (product == null)
    //        {
    //            return NotFound();
    //        }
    //        return Ok(product);
    //    }
    //} 
    #endregion
}

  注:以上采用封装数据库仓储操作方式!

小结

      通过前面的介绍,似乎WebApi应用并不难。其实,很多高级使用(如:OData)还没涉及到讲解。有人说,WebApi和WebService很像,似乎有点为了“淘汰”WCF技术而生。但没有WCF强大,只是更容易使用。

       好了。这节内容并没有演示如何界面展示!我也是正在学习这项技术当中,本着先过一边官方的例子后,再弄一个完整的DEMO!

posted @ 2014-05-13 20:02  范师傅  阅读(826)  评论(0编辑  收藏  举报