分布式技術在項目中會頻繁用到,以前接觸過WebService(可跨平台)、WCF(功能強大,配置繁瑣), 最近由於上層業務調整,將原來的MVC項目一分為三,將數據層提取出來,用API去訪問。然后新建一類庫項目,集成大量的輔助類來幫助MVC web端去訪問Web API。
VS2013上新建WebAPI的時候會多一個區域Areas的文件夾,這個區域可以看成是一個mini的MVC項目,我向來本着技術不夠,篇幅來湊的原則,來初步記錄下API的基礎學習,API和MVC還是有區別的,對於新手,比如我,狹隘的自認MVC主用戶請求返回視圖界面,API主用戶請求返回數據。訪問API一般分為 Jquery中的Ajax 訪問、HttpClient訪問,今天在這里,先寫一寫Ajax與Web API的那些事。
一、建Web API 項目
1、建立Web API項目之后,在Model文件夾下建立實體數據模型
2、新建一控制器StudentController,寫個根據學生ID返回學生對象的方法
public class StudentController : ApiController { IBCCEntities db = new IBCCEntities(); //返回學生信息集合 public IEnumerable<Student> AllStu() { return db.Student; } //根據學生ID查詢學生信息 //根據路由規則 調用: api/Student/id public Student GetStuById(int id) { Student student = db.Student.FirstOrDefault(m => m.StudentID == id); return student; } }
3. 在該項目上新建一視圖,用來請求后台API數據(同項目協議、端口、域名都相同,不存在跨域問題)
<script type="text/javascript"> $(document).ready(function () { $("#btnID").click(function () { var id = $("#txtID").val(); $.getJSON("/api/Student/" + id, function (data) { var html = "<ul>"; $(data).each(function (i, data) { html += "學號:" + data.StudentID + "<br/>"+"姓名:" + data.StudentName + "<br/>"+
"班級:"+ data.StudentClass +"<br/>"+"成績:"+data.grade+"<br/>"+"入學時間:"+data.updatetime+"<br/"; }); $("#contactID").html(html); }); }); }); </script>
只是一個最簡單的Ajax調用后台,因為前台需要接收數據,所以后台Student控制器返回的學生數據對象,而不是視圖
二、客戶端異步調用Web API
當客戶端不在服務器上, 客戶端調用API是存在跨域問題的,異步調用的跨域(協議、端口號、域名)問題該怎么處理,上文演示的前台發起請求,后台API返回數據,下面來模擬客戶端來調用API,另新建一MVC項目作為客戶端,起始和上面前台界面相同,為了作比較,寫一個ajax的底層用法
<script type="text/ecmascript"> $(function () { $("#btnID").click(function () { var id = $("#txtID").val(); $.ajax({ type: "GET", dataType: "json", url: "http://localhost:11308/api/Product/"+id, success: function (data) { var html = "<ul>"; $(data).each(function (i, item) { html += "學號:" + data.StudentID + "<br/>" + "姓名:" + data.StudentName + "<br/>" + "班級:" + data.StudentClass + "<br/>" + "成績:" + data.grade + "<br/>" + "入學時間:" + data.updatetime + "<br/"; }); html += "</ul>"; $("#contbyId").html(html); }, error: function () { alert("發送失敗"); } }); }) }); </script>
而此時進行請求,發現瀏覽器會提示 加載失敗,請求不被允許。
由於啟動每個項目時,配置的端口號不同,所以調用API項目時,就產生的跨域,不是任何客戶端都能得到服務端回執數據的,如果不在后台給客戶端MVC項目的訪問權限,客戶端是接收不到服務端返回的數據,
處理方法:
1.在客戶端添加一個類文件,用作過濾器,將客戶端的URL地址寫進去
public class ProductFilter:System.Web.Http.Filters.ActionFilterAttribute { private const string Origin = "Origin"; private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin"; private const string originHeaderdefault = "http://localhost:20630"; public override void OnActionExecuted( HttpActionExecutedContext actionExecutedContext) { actionExecutedContext.Response.Headers.Add(AccessControlAllowOrigin, originHeaderdefault); } }
2.添加特性,把這種行為標注到一個過多個控制器或動作方法上。如:把該類文件名放置StudentController方法上
//根據學生ID查詢學生信息 //根據路由規則 調用: api/Student/id [StudentFiltet] public Student GetStuById(int id) { Student student = db.Student.FirstOrDefault(m => m.StudentID == id); return student; }
目前這樣雖然能達到效果,如果有多個客戶端來調用此服務端的API,那豈不是需要把所有客戶端的URL加到服務端,如果用一個“泛稱” 添加服務端的過濾器中,這樣就類似於公開接口,
如下:
private const string Origin = "Origin"; private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin"; //private const string originHeaderdefault = "http://localhost:20630"; public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { actionExecutedContext.Response.Headers.Add(AccessControlAllowOrigin, "*"); }
用了泛稱 * 代替具體的客戶端好值之后,該API的接口便等於 公開接口,寫的這里前台Ajax 調用API 基本如此,后面會介紹HttpClient調用API。
世人皆大笑,舉手揶揄之