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>

浙公网安备 33010602011771号