Web API的CRUD操作

概要

http 四个主要的处理方法(get,put,post,delete)能够用来处理匹配增删改查操作:

Get 可以在服务端检索匹配URI匹配的资源,不会对服务器数据进行修改操作

Put 用户修改URI指定的特定资源,如果服务端允许,Put 也可以用户创建新的资源

Post 可以用于创建一个资源。服务端会为这个资源创建一个新的URI,并且将这个资源作为ResposeMessage 的一部分返回

    Delete 用户删除URI匹配的资源

1. 添加Model

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }

2. 添加Repository

    public interface IProductRepository
    {
        IEnumerable<Product> GetAll();
        Product Get(int id);
        Product Add(Product item);
        void Remove(int id);
        bool Update(Product item);
    }

3.实现IProductRepository

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

4. 添加Controllers

创建资源响应状态:

Response Code 默认情况下,web api框架设置响应的状态为200(OK), 基于Http/1.1 协议,在使用post创建一个资源contact的时候,服务器响应状态为201 (Created)

Location:  当创建一个新的资源之后,我们需要 Response Headers 路径中包含一个URI

HttpResponseMessage返回的是一个HttpResponseMessage 而不是一个contact对象,我们可以获得请求响应的详细信息,包括状态码以及响应头信息。

    使用CreateResponse可以创建一个HttpResonseMessage,并且会自动将Contact对象序列化写入响应Body中。

  public class ProductsController : ApiController
    {
        static readonly IProductRepository repository = new ProductRepository();
        public IEnumerable<Product> GetAllProducts()
        {
            return repository.GetAll();
        }
        public Product GetProduct(int id)
        {
            Product item = repository.Get(id);
            if (item == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return item;
        }
        public IEnumerable<Product> GetProductByCategory(string category)
        {
            return repository.GetAll().Where(p=>string.Equals(p.Category,category,StringComparison.OrdinalIgnoreCase));
        }
        public HttpResponseMessage PostProduct(Product item)
        {
            item = repository.Add(item);
            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;

        }
        public void PutProduct(int id, Product product)
        {
            product.Id = id;
            if (!repository.Update(product))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }
        public void DeleteProduct(int id)
        {
            repository.Remove(id);
        }
    }

5. 添加页面

@{
    ViewBag.Title = "Product Store";
}
@section scripts { 
    <style type="text/css">
        table
        {
            border: 1px solid #000;
            border-collapse: collapse;
            color: #666666;
            min-width: 200px;
        }
        
        tr
        {
            border: 1px solid #000;
            line-height: 25px;
        }
        
        th
        {
            background-color: #B1C3CC;
            color: #000;
            font-size: 13px;
            text-align: left;
        }
        
        th, td
        {
            padding-left: 5px;
        }

        #status {
            color: red;
        }
        
    </style>
    <script src="~/Scripts/knockout-2.1.0.js"></script>
    <script type="text/javascript">
        function ViewModel() {
            var self = this;
            // A nested view model that represents a single product.
            function ProductViewModel(product) {
                var self = this;
                self.Id = product.id; 
                self.Name = product.Name;
                self.Price = product.Price;
                self.Category = product.Category;
            }
            self.products = ko.observableArray();  // Contains the list of products
            self.product = ko.observable();
            self.status = ko.observable();
            // Get a list of all products
            self.getAll = function () {
                self.products.removeAll();
                $.getJSON("/api/products", function (products) {
                    $.each(products, function (index, product) {
                        self.products.push(new ProductViewModel(product));
                    })
                });
            }
            // Find a product by product ID
            self.getById = function () {
                self.status("");
                var id = $('#productId').val();

                if (!id.length) {
                    self.status("ID is required");
                    return;
                }

                // Send AJX request to get the product by ID
                $.getJSON(
                    'api/products/' + id,
                    function (data) {
                        self.product(new ProductViewModel(data));
                    })
                    // Handler for error response:
                    .fail(
                        function (xhr, textStatus, err) {
                            self.product(null);
                            self.status(err);
                        });
            }

            // Update product details
            self.update = function () {
                self.status("");
                var id = $('#productId').val();

                var product = {
                    Name: $('#name').val(),
                    Price: $('#price').val(),
                    Category: $('#category').val()
                };

                $.ajax({
                    url: 'api/products/' + id,
                    cache: false,
                    type: 'PUT',
                    contentType: 'application/json; charset=utf-8',
                    data: JSON.stringify(product),
                    success: self.getAll
                })
                .fail(
                function (xhr, textStatus, err) {
                    self.status(err);
                });
            }

            self.create = function () {
                self.status("");

                var product = {
                    Name: $('#name2').val(),
                    Price: $('#price2').val(),
                    Category: $('#category2').val()
                };

                $.ajax({
                    url: 'api/products',
                    cache: false,
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    data: JSON.stringify(product),
                    statusCode: {
                        201 /*Created*/: function (data) {
                            self.products.push(data);
                        }
                    }
                })
                .fail(
                function (xhr, textStatus, err) {
                    self.status(err);
                });

            }

            // Initialize the view-model
            $.getJSON("/api/products", function (products) {
                $.each(products, function (index, product) {
                    self.products.push(new ProductViewModel(product));
                })
            });

        }

        function clearStatus() {
            $('#status').html('');
        }

        function add() {

            clearStatus();

            var product = ko.toJS(viewModel);
            var json = JSON.stringify(product);

            $.ajax({
                url: API_URL,
                cache: false,
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                data: json,
                statusCode: {
                    201 /*Created*/: function (data) {
                        self.products.push(data);
                    }
                }
            });
        }

        var viewModel = new ViewModel();
        ko.applyBindings(viewModel);

        // Initialize jQuery tab widget
   //     $("#tabs").tabs();

    </script>
} 


<div id="body">
    <section class="content-wrapper main-content">
        <h3>Products</h3>

        <table id="products">
        <thead>
            <tr><th>ID</th><th>Name</th><th>Category</th><th>Price</th></tr>
        </thead>
        <tbody data-bind="foreach: products">
            <tr>
                <td data-bind="text: Id"></td>
                <td data-bind="text: Name"></td>
                <td data-bind="text: Category"></td>
                <td data-bind="text: Price"></td>
            </tr>
        </tbody>
        </table>
    </section>
    <section id="detail" class="content-wrapper">

    <div id="tabs"> <!-- div for jQuery UI tabs -->
	    <ul>
		    <li><a href="#viewTab">View Product</a></li>
		    <li><a href="#addNewTab">Add New Product</a></li>
	    </ul>

        <div id="viewTab">
        <label for="productId">ID</label>
        <input type="text" title="ID" name='Id' id="productId" size="5"/>
        <input type="button" value="Get" data-bind="click: getById"/>

        <div data-bind="if: product()">
            <div>
            <label for="name">Name</label>
            <input data-bind="value: product().Name" type="text" title="Name" id="name" />
            </div>

            <div>
            <label for="category">Category</label>
            <input data-bind="value: product().Category" type="text" title="Category" id="category" />
            </div>

            <div>
            <label for="price">Price</label>
            <input data-bind="value: product().Price" type="text" title="Price" id="price" />
            </div>

            <div>
            <input type="button" value="Update" data-bind="click: update" />
            </div>
        </div>
        </div>

        <div id="addNewTab">
            <div>
            <label for="name">Name</label>
            <input type="text" title="Name" id="name2" />
            </div>

            <div>
            <label for="category">Category</label>
            <input type="text" title="Category" id="category2" />
            </div>

            <div>
            <label for="price">Price</label>
            <input type="text" title="Price" id="price2" />
            </div>

            <div>
            <input type="button" value="Add New" data-bind="click: create"" />
            </div>
        </div>

    </div>
    <div>
        <p id="status" data-bind="text: status" />
    </div>

    </section>
</div>

  

  

posted @ 2012-11-02 10:27  bradleydan  阅读(349)  评论(0)    收藏  举报