随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细。比如前端项目使用Angularjs的框架来做UI,而数据则由另一个Web Api 的网站项目来支撑。注意,这里是两个Web网站项目了,前端项目主要负责界面的呈现和一些前端的相应业务逻辑处理,而Web Api则负责提供数据。
这样问题就来了,如果前端通过ajax访问Web Api项目话,就涉及到跨域了。我们知道,如果直接访问,正常情况下Web Api是不允许这样做的,这涉及到安全问题。所以,今天我们这篇文章的主题就是讨论演示如何配置Web Api以让其支持跨域访问(Cors)。好了,下面我们以一个简单的示例直接进入本文的主题。
首先打开Visual Studio 2013,创建一个空白的解决方案,命名为:CrossDomainAccessWebAPI。
再创建一个空的Web Api项目,命名为:CrossDomainAccess.WebAPI
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
namespace
CrossDomainAccess.WebAPI.Models
{
public
class
UserInfo
{
public
int
Id {
get
;
set
; }
public
string
UserName {
get
;
set
; }
public
string
UserPass {
get
;
set
; }
public
string
Email {
get
;
set
; }
public
DateTime RegTime {
get
;
set
; }
}
}
|
然后在WebAPI项目中添加一个示例控制器:UserInfoController,这个控制器用来返回数据集合,具体代码如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Net;
using
System.Net.Http;
using
System.Web.Http;
using
CrossDomainAccess.WebAPI.Models;
namespace
CrossDomainAccess.WebAPI.Controllers
{
public
class
UserInfoController : ApiController
{
/// <summary>
/// 获取用户信息集合的方法
/// </summary>
/// <returns>返回用户信息集合</returns>
public
IHttpActionResult GetList()
{
//对象集合模拟数据
List<UserInfo> list =
new
List<UserInfo>()
{
new
UserInfo()
{
Id = 1,
UserName =
"张三"
,
UserPass =
"FDASDFAS"
,
Email =
"zhangsan@163.com"
,
RegTime = DateTime.Now
},
new
UserInfo()
{
Id = 2,
UserName =
"李四"
,
UserPass =
"FDASDFAS"
,
Email =
"lisi@163.com"
,
RegTime = DateTime.Now
},
new
UserInfo()
{
Id = 3,
UserName =
"王五"
,
UserPass =
"FDASDFAS"
,
Email =
"wangwu@163.com"
,
RegTime = DateTime.Now
},
new
UserInfo()
{
Id = 4,
UserName =
"赵六"
,
UserPass =
"FDASDFAS"
,
Email =
"zhaoliu@163.com"
,
RegTime = DateTime.Now
},
new
UserInfo()
{
Id = 5,
UserName =
"田七"
,
UserPass =
"FDASDFAS"
,
Email =
"tianqi@163.com"
,
RegTime = DateTime.Now
},
new
UserInfo()
{
Id = 6,
UserName =
"王八"
,
UserPass =
"FDASDFAS"
,
Email =
"wangba@163.com"
,
RegTime = DateTime.Now
}
};
return
Ok(list);
}
}
}
|
接着我们需要修改一下App_Start目录下的WebApiConfig.cs文件中webapi的路由规则,以便通过api/{controller}/{action}的方式进行访问,同时让修改序列化方式,让WebAPI默认输出json格式的数据,具体操作如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Net.Http.Formatting;
using
System.Web.Http;
namespace
CrossDomainAccess.WebAPI
{
public
static
class
WebApiConfig
{
public
static
void
Register(HttpConfiguration config)
{
// Web API 配置和服务
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name:
"DefaultApi"
,
routeTemplate:
"api/{controller}/{action}/{id}"
,
defaults:
new
{ id = RouteParameter.Optional }
);
//清除所有序列化格式
config.Formatters.Clear();
//添加Json格式的序列化器
config.Formatters.Add(
new
JsonMediaTypeFormatter());
}
}
}
|
重新生成一下项目,并在浏览器中访问,这时我们可以的到json格式的数据,如下:
好了,到这里我们Web Api端的数据输出就准备好了。为了测试是否可以跨域访问,我们再转到CorsDemo.UI网站项目中。首先创建一个index.aspx页面(这个命名自己可以任意取)后打开,修改成如下的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
<%@ Page Language=
"C#"
AutoEventWireup=
"true"
CodeBehind=
"Index.aspx.cs"
Inherits=
"CrossDomainAccess.Web.Index"
%>
<!DOCTYPE html>
<head runat=
"server"
>
<meta http-equiv=
"Content-Type"
content=
"text/html; charset=utf-8"
/>
<title></title>
<script src=
"Scripts/jquery-2.2.3.min.js"
></script>
<script type=
"text/javascript"
>
$(function () {
$(
'#getData'
).click(function () {
$.ajax({
dataType:
'json'
,
success: function (data) {
//以表格的形式在浏览器控制台显示数据,IE下不支持
console.table(data);
}
});
});
});
</script>
</head>
<body>
<form id=
"form1"
runat=
"server"
>
<div>
<input type=
"button"
value=
"跨域获取数据"
id=
"getData"
/>
</div>
</form>
</body>
</html>
|
完成以上步骤以后,启动WebAPI项目和Web项目,并在Web项目的Index页面中点击跨域获取数据按钮,打开浏览器控制台查看请求结果,在控制台会出现如下结果:
控制台提示我们跨域请求被阻止,同时提示CORS头部信息确实,所以我们可以通过去WebAPI配置CORS来让其支持跨域访问。
那现在我们在WebAPI项目中通过Nuget添加Microsoft.AspNet.WebApi.Cors ,然后在WebApiConfig.cs文件中配置HttpConfiguration的EnableCors方法即可。具体操作如下:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Net.Http.Formatting;
using
System.Web.Http;
using
System.Web.Http.Cors;
namespace
CrossDomainAccess.WebAPI
{
public
static
class
WebApiConfig
{
public
static
void
Register(HttpConfiguration config)
{
// Web API 配置和服务
EnableCrossSiteRequests(config);
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name:
"DefaultApi"
,
routeTemplate:
"api/{controller}/{action}/{id}"
,
defaults:
new
{ id = RouteParameter.Optional }
);
//清除所有序列化格式
config.Formatters.Clear();
//添加Json格式的序列化器
config.Formatters.Add(
new
JsonMediaTypeFormatter());
}
/// <summary>
/// 允许跨域调用
/// </summary>
/// <param name="config"></param>
private
static
void
EnableCrossSiteRequests(HttpConfiguration config)
{
//对所有的请求来源没有任何限制
var cors =
new
EnableCorsAttribute(
origins:
"*"
,
headers:
"*"
,
methods:
"*"
);
config.EnableCors(cors);
}
}
}
|
现在,我们再重新生成WebAPI项目并运行,接着在页面http://localhost:31521/Index.aspx中点击按钮“跨域获取数据”,通过firebug的控制台,我们可以看到数据跨域加载成功了,如下: