本篇體驗在MVC4下,實現一個對Book資訊的管理,包括增刪查等,用到了EF Code First, 使用Unity進行依賴注入,前端使用Bootstrap美化。先上最終效果:
→建立一個MVC4專案,選擇Web API模版。
→在Models資料夾建立一個Book.cs類。
namespace MyMvcAndWebApi.Models
{public class Book{public int Id { get; set; }public string Name { get; set; }public decimal Price { get; set; }}}
→在Models資料夾建立BookInitializer類,用來初始化資料庫表資料。
using System.Data.Entity;
namespace MyMvcAndWebApi.Models
{public class BookInitializer : DropCreateDatabaseIfModelChanges<BookStore>{protected override void Seed(BookStore context){context.Books.Add(new Book() {Name = "我有一頭小毛驢", Price = 200M});context.Books.Add(new Book() { Name = "今天天氣真好", Price = 300M });context.Books.Add(new Book() { Name = "秋天是落葉的季節", Price = 500M });}}}
→在Models資料夾中,建立BookStore類,派生於DbContext。
using System.Data.Entity;
namespace MyMvcAndWebApi.Models
{public class BookStore : DbContext{public BookStore() : base("conn"){Database.SetInitializer(new BookInitializer());
}public DbSet<Book> Books { get; set; }}}
→在Web.config中配置連線字串。
<connectionStrings>......<add name="conn" connectionString="Data Source=.;User=yourusername;Password=yourpassword;Initial Catalog=BookStore;Integrated Security=True" providerName="System.Data.SqlClient" /></connectionStrings>
→Repository首先需要一個介面,在Models資料夾中建立IBookRepository介面。
using System.Collections.Generic;
namespace MyMvcAndWebApi.Models
{public interface IBookRepository{IEnumerable<Book> GetAll();Book Get(int id);
Book Add(Book book);void Remove(int id);bool Update(Book book);
}}
→實現IBookRepository介面,用到BookStore這個上下文。
using System.Collections.Generic;
using System.Data;
namespace MyMvcAndWebApi.Models
{public class BookRepository : IBookRepository{private BookStore db = new BookStore();public BookRepository(){}
public IEnumerable<Book> GetAll()
{return db.Books;
}public Book Add(Book book)
{db.Books.Add(book);db.SaveChanges();return book;
}public void Remove(int id){Book book = db.Books.Find(id);db.Books.Remove(book);db.SaveChanges();}public bool Update(Book book){db.Entry(book).State = EntityState.Modified;db.SaveChanges();return true;}public Book Get(int id){return db.Books.Find(id);
}}}
→有了介面和實現,接下來會用到依賴注入。選擇使用Unity,在NuGet中下載。
→首先需要一個依賴注入容器。在專案下建立Helper資料夾,在其中建立IoCContainer類。
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
using Microsoft.Practices.Unity;
namespace MyMvcAndWebApi.Helper
{class ScopeContainer : IDependencyScope
{protected IUnityContainer container;
public ScopeContainer(IUnityContainer container)
{if (container == null){throw new ArgumentNullException("container");}this.container = container;
}public object GetService(Type serviceType){if (container.IsRegistered(serviceType))
{return container.Resolve(serviceType);
}else
{return null;}}public IEnumerable<object> GetServices(Type serviceType){if (container.IsRegistered(serviceType))
{return container.ResolveAll(serviceType);
}else
{return new List<object>();}}public void Dispose(){container.Dispose();}}class IoCContainer : ScopeContainer, IDependencyResolver
{public IoCContainer(IUnityContainer container)
: base(container)
{}public IDependencyScope BeginScope()
{var child = container.CreateChildContainer();return new ScopeContainer(child);}}}
→在Global.asax中註冊Unity。
sing System.Web.Http;using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using MyMvcAndWebApi.Controllers;
using MyMvcAndWebApi.Helper;
using MyMvcAndWebApi.Models;
namespace MyMvcAndWebApi
{// 注意: 有關啟用 IIS6 或 IIS7 經典模式的說明,
// 請訪問 http://go.microsoft.com/?LinkId=9394801
public class WebApiApplication : System.Web.HttpApplication{//註冊控制器,介面和實現
void ConfigureApi(HttpConfiguration config)
{var unity = new UnityContainer();
unity.RegisterType<BooksController>();unity.RegisterType<IBookRepository, BookRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
}protected void Application_Start(){AreaRegistration.RegisterAllAreas();//註冊依賴注入
ConfigureApi(GlobalConfiguration.Configuration);WebApiConfig.Register(GlobalConfiguration.Configuration);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);}}}
→建立一個空的Api控制器,編寫如下:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MyMvcAndWebApi.Models;
namespace MyMvcAndWebApi.Controllers
{public class BooksController : ApiController{//_repository執行時變數,在首次引用IBookRepository方法時動態分配記憶體
private static IBookRepository _repository;public BooksController(IBookRepository repository)
{if (repository == null){throw new ArgumentNullException("repository");}_repository = repository;}//根據慣例,如果action名稱以Get開頭,那就接收Get請求
public IEnumerable<Book> GetAllBooks()
{return _repository.GetAll();
}//ASP.NET Web API會自動幫我們把URL中的字串id轉換成引數型別int
public Book GetBook(int id){Book book = _repository.Get(id);if (book == null){//HttpResponseException封裝返回的異常
//HttpResponseMessage封裝返回的資訊
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));}return book;
}//新增
//action名以post開頭,按照慣例,接收post請求
//客戶端傳送來序列化的Book物件,在服務端對Book物件反序列化
public HttpResponseMessage PostBook(Book book)
{book = _repository.Add(book);// Web API預設返回的狀態碼為200,可是,根據HTTP/1.1協議,在新增完,我們希望返回201狀態碼
var response = Request.CreateResponse(HttpStatusCode.Created, book);//返回新建立資源的url
string uri = Url.Route(null, new {id = book.Id});response.Headers.Location = new Uri(Request.RequestUri, uri);
return response;
}//修改
//引數id從url中獲取,book從request中反序列化
//根據慣例,Put開頭的action,接收put請求
public void PutBook(int id, Book book){book.Id = id;if (!_repository.Update(book))
{throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));}}//刪除
//根據管理,Delete開頭接收delete請求
public HttpResponseMessage DeleteBook(int id){_repository.Remove(id);//返回200狀態碼錶示刪除成功
//返回202狀態碼錶示正在刪除
//返回204狀態碼錶示沒有內容
return new HttpResponseMessage(HttpStatusCode.NoContent);}}}
以上,所有action方法名稱都符合了慣例。
→修改Home/Index.cshtml,我們在此使用jquery與服務端api控制器進行互動。
@section scripts {<script src="@Url.Content("~/Scripts/jquery-1.6.2.js")" type="text/javascript"> </script><script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"> </script><script src="@Url.Content("~/Scripts/jQuery.tmpl.js")" type="text/javascript"> </script><script type="text/javascript">
$(function () {//Get請求
$.getJSON("api/books",
function (data) {$.each(data,function (index, value) {
$("#bookTemplate").tmpl(value).appendTo("#books");});$("#loader").hide("slow");$("#addBook").show("slow");});//新增
$("#addBook").submit(function () {
$.post("api/books",
$("#addBook").serialize(), //序列化Book物件function (value) {
$("#bookTemplate").tmpl(value).appendTo("#books");$("#name").val("");
$("#price").val("");
},"json"
);return false;});//刪除
$(".removeBook").live("click", function () {$.ajax({type: "DELETE",
url: $(this).attr("href"),context: this,
success: function () {$(this).closest("li").remove();}});return false;});$("input[type=\"submit\"], .removeBook, .viewImage").button();
});//根據id搜尋
function find() {var id = $('#bookId').val();$.getJSON("api/books/" + id,
function (data) {var str = data.Name + ': $' + data.Price;$('#book').html(str);}).fail(function (jqXHR, textStatus, err) {$('#book').html('Error: ' + err);});}</script><script id="bookTemplate" type="text/html"><li><p><strong> Book ID:</strong> ${ Id}<br /><strong> Book Name:</strong> ${ Name }<br /><strong> Price: $</strong> ${ Price }</p><p><a href="${ Self }" class="button small red removeBook">移除</a></p></li></script>}<body><form method="post" id="addBook"><div class="container_16"><h1 class="title-01">Book資訊</h1></div><div class="container_16"><div class="grid_16 body-container"><div class="margin grid_6 alpha"><label for="Name">Name</label><br /><input type="text" id="name" name="Name" class="text grid_4" /><br class="clear" /><label for="Price">Price</label><br /><input type="text" id="price" name="Price" class="text grid_4" /><br class="clear" /><input type="submit" value="新增" class="button small green" /><br /><br /><br class="clear" /><strong id="book">@* <label id="book"></label>*@ </strong><br /><br class="clear" /><br /><label for="bookId">根據ID搜尋</label><br /><input type="text" id="bookId" size="20" class="text grid_4" /><br class="clear" /><input type="button" value="搜尋" onclick="find();" class="button small gray" /></div><div class="grid_8 omega"><img id="loader" src="images/ajax-loader.gif" /><ul id="books" class="books"></ul></div></div></div><br class="clear" /><div class="footer clearfix"></div></form></body>
另外,有關Bootsrap的樣式在BundleConfig類中定義。
參考資料:http://www.codeproject.com/Articles/344078/ASP-NET-WebAPI-Getting-Started-with-MVC-and-WebAP