系列導(dǎo)航地址http://www.companysz.com/fzrain/p/3490137.html
經(jīng)過前2節(jié)的介紹,我們已經(jīng)把數(shù)據(jù)訪問層搭建好了,從本章開始就是Web Api部分了。在正式開始之前,再一次回顧一下Web Api的應(yīng)用場景:Web Api可以與 MVC,WebForm結(jié)合使用,也可以作為一個單獨的Web服務(wù)。在正式討論Web Api的配置以及如何構(gòu)造我們的URI來消費資源之前,我們必須理解Http方法與我們將要訪問的資源之間的關(guān)系。舉個簡單的例子,我們把模型”Course”作為我們訪問的資源,下面就列舉了訪問這個資源的http方法:
Action | HTTP Verb | Relative URI |
獲取所有課程信息 | GET | /api/courses |
根據(jù)某個Id獲取單個課程 | GET | /api/courses/id |
新增一個課程 | POST | /api/coursesNew course is sent in POST body |
更新一個課程 | PUT or PATCH | /api/courses/idUpdated course is sent in POST body |
刪除一個課程 | DELETE | /api/courses/id |
右擊解決方案->添加新建項目
下一步:
點擊確定
在創(chuàng)建好項目之后,我們可以在App_Start文件夾下看到“WebApiConfig”類。這個類就是用來配置路由信息的,這個類最終會在“Global.asax”的application_Start()方法中被調(diào)用,后面我們會在這個這個類里面配置多條路由信息。
配置第一個路由:
config.Routes.MapHttPRoute( name: "Courses", routeTemplate: "api/courses/{id}", defaults: new {controller="courses", id = RouteParameter.Optional } );
分析一下上面這段代碼:我們創(chuàng)建了一個Courses的路由規(guī)則,這個路由模板會匹配到“api/courses/{id}”的URI,在這個模板定義了2個默認值(api,courses)以及一個可選值(id)。對于“/api/courses or /api/courses/5”URI就會被我們的路由模板匹配到,同時“/api/courses”URI也會被匹配到,因為Id是可選的。
Web Api中的Controller是用來處理客戶端Http請求的(與MVC中的Controller類似),首先,創(chuàng)建Controller——右擊Controller文件夾->新建項->控制器
然后出現(xiàn)下面窗口:
選擇Web API 2控制器-空,并命名為CoursesController。然后確定
打開剛才創(chuàng)建的Controller,可以看到我們創(chuàng)建的類繼承自“ApiController”。同時對于這個類的類名必須是“CoursesController”,因為在Web Api中默認的控制器選擇方式是尋找所有繼承自“ApiController”類并且這個類是以“Courses”開頭(這是在我們的路由規(guī)則中配置的)的控制器。
首先,我們創(chuàng)建上述表格列舉到的前2個方法(GetAllCourses,GetCourseById)
方法的選擇是智能的,如果我們創(chuàng)建了2個方法Get()和GetCourse(int id),假設(shè)我們發(fā)送一個GET請求并且URI是“/api/courses/5”,那么“GetCourse(int id)”方法就會被選擇執(zhí)行,這是因為方法是以Get開頭而且URI中包含Id的值。這種選擇方式同樣適用以其他的Http方法(put,delete,post),下面上代碼:
public class CoursesController : ApiController { public List<Course> Get() { ILearningRepository repository = new LearningRepository(new LearningContext()); return repository.GetAllCourses().ToList(); } public Course GetCourse(int id) { ILearningRepository repository = new LearningRepository(new LearningContext()); return repository.GetCourse(id); } }
當(dāng)我們創(chuàng)建一個Get請求并且URI是“http://localhost:{your_port}/api/courses”時候,Get()方法會被選擇調(diào)用,下面是相應(yīng)的部分代碼:
[ { "Id": 1, "Name": "History Teaching Methods 1", "Duration": 3, "DescrOutlook.com", "UserName": "AhmadJoudeh", "PassWord": "SWDQNPSE", "FirstName": "Ahmad", "LastName": "Joudeh", "Gender": 0 }, "CourseSubject": { "Courses": [], "Id": 1, "Name": "History" }, "Enrollments": [] }, { "Id": 2, "Name": "History Teaching Methods 2", "Duration": 3, "Description": "The course will talk in depth about: History Teaching Methods 2", "CourseTutor": { "Courses": [], "Id": 1, "Email": "[email protected]", "UserName": "AhmadJoudeh", "Password": "SWDQNPSE", "FirstName": "Ahmad", "LastName": "Joudeh", "Gender": 0 }, "CourseSubject": { "Courses": [], "Id": 1, "Name": "History" }, "Enrollments": [] },
如果你發(fā)送一個Get請求并且URI是“http://localhost:{your_port}/api/courses/5”。那么GetCourse(int id)將會被選擇調(diào)用執(zhí)行。但是很遺憾在調(diào)用這個方法之后就會產(chǎn)生一個異常,這個異常信息簡單來說就是“序列化對象的時候出現(xiàn)了循環(huán)依賴”,換句話說就是對象間循環(huán)引用(Course>Enrollment>Course>Enrollment>etc…)
到目前為止我們已經(jīng)讓W(xué)eb Api跑起來了,但仍然有很多不足之處:
返回對象時出現(xiàn)循環(huán)依賴,可以通過模型工廠模式解決。
我們返回了領(lǐng)域模型中所有的字段給客戶端,然而有一些敏感信息不應(yīng)該返回(例如:password字段),解決方案:模型工廠模式
每一個返回給客戶端的資源都應(yīng)該包含一個URI以便客戶端查詢,解決方案依舊是模型工廠模式。
對于返回單個資源,我們應(yīng)當(dāng)返回相應(yīng)的狀態(tài)碼(例如:成功200,資源未找到404等),解決方案:HttpResponseMessage對象
在每個方法里我們都實例化了一個repository,這個對象包含了一些昂貴的操作(例如:數(shù)據(jù)庫連接),解決方案:依賴注入模式
對于返回的Json對象格式是以“帕斯卡”風(fēng)格的(例如“FirstName”),然而我們的Api有很大的可能被帶有javascript的客戶端消費,對于JS開發(fā)者來說可能更適合“駝峰”風(fēng)格(例如”firstName”)的數(shù)據(jù)。解決方案:配置Json格式。
ok,下一章我們就著重解決上述的問題
本章代碼:http://yun.baidu.com/share/link?shareid=2010367762&uk=17559114&third=0
新聞熱點
疑難解答