Web API 跨域請求


       分布式技術在項目中會頻繁用到,以前接觸過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。

 

 世人皆大笑,舉手揶揄之    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM