標籤:
問題描述
當跨域(cross domain)調用ASP.NET MVC或者ASP.NET Web API編寫的服務時,會發生無法訪問的情況。
重現方式
- 使用模板建立一個最簡單的ASP.NET Web API項目,調試起來確認能正常工作
- public class UserController : ApiController
- {
- public UserModel getInfo()
- {
- UserModel um = new UserModel();
- um.Uid = 5;
- um.UserName = "addddn";
- um.Age = 117;
- return um;
- }
12.}
13.public class UserModel
- {
- public int Uid { get; set; }//編號
- public string UserName { get; set; }//姓名
- public int Age { get; set; }//年齡
- }
- 建立另外一個項目,僅僅包含一個HTML頁面,發起AJAX的調用
20.<script type="text/javascript">
- window.onload = function get() {
- $.ajax({
- type: ‘GET‘,
- url: ‘http://192.168.10.106:8088/api/user/getInfo‘,
dataType: ‘json‘,
- success: function (data, textStatus) {
- alert(data.Uid + " | " + data.UserName + "|" + data.Age);
- },
- error: function (xmlHttpRequest, textStatus, errorThrown) {
- }
- });
- }
- 在瀏覽器中開啟這個網頁,我們會發現如下的錯誤(405:Method Not Allowed)
【備忘】同樣的情況,也發生在ASP.NET MVC中。某些時候,MVC也可以直接用來開發服務,與WebAPI相比各有優缺點。下面是一個利用MVC開發的服務的例子
- public ActionResult Index()
{
UserModel um = new UserModel();
um.Uid = 5;
- um.UserName = "addddn";
- um.Age = 117;
return Json(um, JsonRequestBehavior.AllowGet);
}
原因分析
跨域問題僅僅發生在Javascript發起AJAX調用,或者Silverlight發起服務調用時,其根本原因是因為瀏覽器對於這兩種請求,所給予的許可權是較低的,通常只允許調用本域中的資源,除非目標伺服器明確地告知它允許跨域調用。
所以,跨域的問題雖然是由於瀏覽器的行為產生出來的,但解決的方法卻是在服務端。因為不可能要求所有用戶端降低安全性。
解決方案1
針對ASP.NET MVC和ASP.NET Web API兩種項目類型,我做了一些研究,確定下面的方案是可行的。
針對ASP.NET MVC,只需要在web.config中添加如下紅色的內容即可
<system.webServer>
<httpProtocol>
<customHeaders>
<addname="Access-Control-Allow-Origin" value="*" />
<addname="Access-Control-Allow-Headers" value="Content-Type"/>
<addname="Access-Control-Allow-Methods" value="GET, POST, PUT,DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
針對ASP.NET Web API,除了上面這樣的設定,還需要添加一個特殊的設計,就是為每個APIController添加一個OPTIONS的方法,但無需返回任何東西。
public string Options()
{
return null; // HTTP 200 response with empty body
}
【備忘】這個功能也可以進行一些研究,設計成Filter的形式可能就更好了。
解決方案2(針對MVC)
下面的index是需要調用的方法
public ActionResult Index()
{
string t = requestURL("http://192.168.1.3/api/user/getInfo");
JsonData js = JsonMapper.ToObject(t);
String name = (String)js["UserName"];
return Content(name);
}
public static string requestURL (string url)
{
string strURL = url;
System.Net.HttpWebRequest request;
request = (System.Net.HttpWebRequest)WebRequest.Create(strURL);
request.Method = "GET";
System.Net.HttpWebResponse response;
response = (System.Net.HttpWebResponse)request.GetResponse();
System.IO.Stream s;
s = response.GetResponseStream();
string StrDate = "";
string strValue = "";
StreamReader Reader = new StreamReader(s, Encoding.UTF8);
while ((StrDate = Reader.ReadLine()) != null)
{
strValue += StrDate + "\r\n";
}
return strValue;
}
AJAX跨域調用ASP.NET MVC或者WebAPI服務的解決方案