在现代Web开发中,跨域资源共享(CORS)是一个常见的问题。随着Web应用的复杂性增加,前端和后端分离的架构越来越普遍,这就需要在不同域之间进行数据交换。然而,浏览器出于安全考虑,限制了跨域请求。本文将介绍一种在不改变现有代码的情况下,通过jQuery和ASP.NET实现跨域请求的解决方案。
在项目OneTrueError
中,通过使用纯REST服务在WebApi中将UI与后端分离。这要求UI能够使用Ajax请求跨不同子域。遗憾的是,Internet Explorer 9及以下版本不支持这一点。为了避免重新编码所有的knockout视图模型,采用了另一种替代方案。
通过在jQuery管道中注入逻辑来检查浏览器版本,然后在Ajax请求之前修改URI以调用CORS代理。这样,即使在IE9及以下版本中,也能够实现跨域请求。
首先,安装NuGet包CorsProxy.aspnet
到前端项目中,并在RouteConfig
中添加以下代码:
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.EnableCorsProxy();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
这样,CORS代理会将所有请求头和内容从请求复制到代理请求中,并将所有信息从代理响应复制到ASP.NET响应中。这意味着可以添加自定义请求头,使用任何HTTP方法或内容。代理将处理这些。
在客户端,需要添加JavaScript代码,将代理注入到jQuery的ajax处理中。打开BundleConfig
并添加jquery.corsproxy.js
到jQuery捆绑包中:
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js", "~/Scripts/jquery-corsproxy-{version}.js"));
// [...]
}
}
完成这些步骤后,jQuery应该能够在IE9或以下版本中优雅地降级为代理CORS请求。
在服务器端,创建了一个自定义的IHttpHandler
。IHttpHandler
的好处是它定义在System.Web
中,因此将与所有ASP.NET方言兼容。缺点是与IHttpModule
相比,需要一些额外的配置才能激活。
CorsProxyHttpHandler
类处理错误响应。X-CorsProxy-InternalFailure
头指示是CORS代理本身失败还是调用的服务器失败。