`
黄继华
  • 浏览: 46542 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

MVC4 Web Api 与 Ajax交互存在的跨域问题总结

 
阅读更多

最近项目中要用到mvc4的webapi,其实就是类似webservers wcf的东东( 虽然我都没用过,但是功能和用处还是知道的)作为接口使用,webapi有个好处就是可以把实现IEnumberable接口的数据能根据请求的返回数据类型(xml或者json)自动序列化成这样结构的数据,默认情况下chrome返回的是xml,IE返回的是Json。

既然是Api肯定是要让其他程序去调用的,webapi只能通过http协议去调用,在我们的项目中是静态页面中通过Ajax去调用的。那么问题就出来了 既然是在静态页面中,肯定是用在其他项目中或者在本地了,这样的话去调用webapi就是跨域访问了,要跨域当然我们会想到jQuery的几个跨域访问的方法,例如:$.get() $.getJSON() $.getScript() $.ajax() 其实这几个在jQuery内部调用的都是$.ajax()。实验了一下才知道用这些方法实现跨域访问必须要在url后面加一个callback=?(?也不能省,jQuery会给我们添上该是什么的,每一次都不一样,为了回调的时候知道是哪个请求发出的。当然在$.ajax()方法中也可指定jsoncallback参数,发出请求后就是?的值)才行,并且返回的时候也要加在返回值得前面。例如webapi的url是www.asss.com/api/values 那么就是www.asss.com/api/values?callback=? 后台返回json格式之前要加callback的值 如:jsoncallback+"("+json+")"" jsoncallback是callback传过去的值 json是json内容 只有这样才能跨域请求成功,否则将会有jQuery报的异常 内容为.....is not called,就是返回来的时候传过去的callback方法没有被执行。造成返回的json字符串也取不到。 虽然说前后都加callback可以跨域成功,但是webapi貌似做个很多处理,要是返回json字符串在chrome浏览器中看到的返回值竟然被加了”“在最外边,在一般的处理程序返回json就不会加引号,这样的话要在前面加上callback也不会被认出来,想到会不会有在response的时候可以处理的可继承的方法,但是没找到 好像有request时候的。

还好msdn上有个大牛给了个解决方案,链接为http://code.msdn.microsoft.com/windowsdesktop/Implementing-CORS-support-a677ab5d还有源码下载挺好,大致意思是在跨域的ajax请求中,在request的头部加个Origin什么之类的。具体做法是建个继承 DelegatingHandler类的子类,重写SendAsync方法

该类内容如下:

c#代码
01 usingSystem;
02 usingSystem.Collections.Generic;
03 usingSystem.Linq;
04 usingSystem.Web;
05 usingSystem.Net.Http;
06 usingSystem.Threading;
07 usingSystem.Threading.Tasks;
08 usingSystem.Net;
09
10
11 namespaceMvc4WebApiTest
12 {
13 publicclassMessageHandler : System.Net.Http.DelegatingHandler
14 {
15
16 conststringOrigin ="Origin";
17 conststringAccessControlRequestMethod ="Access-Control-Request-Method";
18 conststringAccessControlRequestHeaders ="Access-Control-Request-Headers";
19 conststringAccessControlAllowOrigin ="Access-Control-Allow-Origin";
20 conststringAccessControlAllowMethods ="Access-Control-Allow-Methods";
21 conststringAccessControlAllowHeaders ="Access-Control-Allow-Headers";
22
23
24 protectedoverrideTask<httpresponsemessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
25 {
26 boolisCorsRequest = request.Headers.Contains(Origin);
27 boolisPreflightRequest = request.Method == HttpMethod.Options;
28 if(isCorsRequest)
29 {
30 if(isPreflightRequest)
31 {
32 returnTask.Factory.StartNew<httpresponsemessage>(() =>
33 {
34 HttpResponseMessage response =newHttpResponseMessage(HttpStatusCode.OK);
35 response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
36
37
38 stringaccessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
39 if(accessControlRequestMethod !=null)
40 {
41 response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
42 }
43
44
45 stringrequestedHeaders =string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
46 if(!string.IsNullOrEmpty(requestedHeaders))
47 {
48 response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
49 }
50
51
52 returnresponse;
53 }, cancellationToken);
54 }
55 else
56 {
57 returnbase.SendAsync(request, cancellationToken).ContinueWith<httpresponsemessage>(t =>
58 {
59 HttpResponseMessage resp = t.Result;
60 resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
61 returnresp;
62 });
63 }
64 }
65 else
66 {
67 returnbase.SendAsync(request, cancellationToken);
68 }
69 }
70 }
71 }</httpresponsemessage></httpresponsemessage></httpresponsemessage>

然后再GlobalApplication_Start的时候注册一下就行了

GlobalConfiguration.Configuration.MessageHandlers.Add(newMessageHandler());

测试成功! 前台调用就是普通的ajax请求地址就行了。


但是页面测试时发现IE浏览器8,9在Jquery ajax与后台通信管道中Handler类的前提下,跨域问题还是存在,Jquery抛出异常“No Transport” js前加上“jQuery.support.cors = true;”后浏览器报错“Error:拒绝访问”,查找资料,有两种办法

1.设置IE的安全性,当然不可取(这样的话每个用户都要设置)。

2.IE8 9可通过XDomainRequest对象(http://msdn.microsoft.com/zh-cn/library/dd573303(v=vs.85).aspx)发出跨域请求 但是只能发生get请求。 综合考虑:先继续寻找XDomainRequest发生post等的方法,否则只能在IE8 9种都设置发送get。

javascript代码
01 if($.browser.msie && parseInt($.browser.version, 10) >= 6 && window.XDomainRequest) {//IE8 IE9
02 varxdr =newXDomainRequest();
03 alert(xdr.responseText);
04 vardata = $.parseJSON(xdr.responseText);
05 if(data ==null||typeof(data) =='undefined') {
06 data = $.parseJSON(data.firstChild.textContent);
07 }
08 //需要手动处理json数据
09 };
10 xdr.onsuccess =function() { };
11 xdr.onerror =function(e) {
12 alert(xdr.responseText); alert(e);
13 }
14
15 xdr.onload =function(e) {
16
17 xdr.open("post", url);
18 xdr.send("dd:dd&ss:ss");
19 }
20 else{
21 varxhr = jQuery.ajax({
22 url: url,
23 type:'post',
24 dataType:'json',
25 crossDomain:true,
26 data:{SystemName: myModel.systemname(), SystemIp: myModel.systemip(), ContactPerson: myModel.contactperson() },
27 success:function(msg) { alert(msg);varjsonmsg = eval("("+ msg +")"); alert(jsonmsg.state); },
28 complete:function() { },
29 error:function(a, b, c) { alert("shibai"+ a +"-"+ b +"-"+ c); alert(c); }
30 });
31 }
32 }

测试得知XDomainRequest只能发送get和post的请求,并且由于post请求报文头中一定要有“Content-Type:application/x-www-form-urlencoded” (非提交文件时,有file标签时好像是application/..form-file)因为XDomainRequest的Content-Type是只读的‘text/plain’所以post不能提交数据,否则就会出错或者后台取不到数据。要想用就只能用get了。 而我最后 放弃web api 改用普通mvc 前台jsonp请求。(jsonp介绍请移步http://www.dnetzj.com/Content/198.html

jquery的ajax也很简单:

javascript代码
1 jQuery.ajax({
2 url: url,
3 dataType:'jsonp',
4 jsonpCallback:'callback',//指定后台返回的方法是callback 服务端返回格式:callback('json字符串..')
5 data: data,
6 success:function(msg){}
7 });

以上写的比较乱还是总结一下吧, 如果要在页面跨域访问还是用jsonp方便一点,但因jsonp是以增加script文件,执行完再删除的形式所以jsonp只能发送get请求,所以如果要提交文件就用uploadify插件(flash上传)(参见:回头再说:Uploadify跨域上传原理),要提交的内容长度比较多时就用ajaxcdr.js(flash请求)(参见:jsonp请求url长度过长的替代(ajaxcdr的使用)

分享到:
评论

相关推荐

    MVC+WebAPI跨域调用.rar

    在IT领域,Web应用程序开发经常会遇到跨域问题,特别是在客户端(如浏览器)使用JavaScript与服务端API进行交互时。这个“MVC+WebAPI跨域调用.rar”压缩包文件提供了一个简单的示例,用于演示如何使用jQuery在MVC...

    WebApi 跨域问题解决方案:CORS

    WebApi 跨域问题主要源于浏览器的同源策略,这是一种安全机制,限制JavaScript或Cookie只能访问同一源(协议+域名+端口)下的内容。在实际开发中,当WebApi作为一个独立的服务,例如数据服务层,而MVC项目作为前端...

    demo跨域ajax_DEMO_ajax跨域_

    在Web开发中,跨域(Cross-Origin)是一个常见的问题,特别是在使用Ajax进行异步数据交互时。本示例“demo跨域ajax_DEMO_ajax跨域”着重解决C#后端与JavaScript前端之间的跨域限制。这里我们将深入探讨什么是跨域、...

    ajax跨域post(java例子)

    在Web开发中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的异步更新,使得用户在不刷新整个页面的情况下与服务器进行交互。然而,由于浏览器的同源策略限制,Ajax请求通常只能发送到与当前页面...

    asp.net MVC4 Web编程

    ASP.NET MVC4是一种基于模型-视图-控制器(Model-View-Controller)设计模式的Web应用程序开发框架,由微软提供,旨在提供更加灵活、可测试和可维护的Web应用程序开发方式。在MVC4中,开发者可以将业务逻辑、用户...

    Ajax与Java交互

    总结,Ajax与Java的交互是现代Web开发中不可或缺的一部分,它极大地提升了用户体验,使得Web应用更加互动和高效。通过熟练掌握Ajax的基本原理和实践技巧,开发者能够构建出更强大的动态Web应用。

    webapi跨域使用session的方法示例

    在讨论webapi跨域使用session的方法之前,我们先要了解几个关键概念,包括跨域、session和CORS(跨源资源共享)。跨域问题通常出现在浏览器的同源策略限制下,当一个域的网页尝试访问另一个域的资源时就会遇到这个...

    signalR跨域及解决方案

    对于需要复杂交互的情况,可以在目标域上创建一个 IFrame,并通过 `window.postMessage` API 与外部窗口通信。不过,这种方法实现起来较为复杂,通常不是首选。 5. **WebSockets 协议:** 当 SignalR 使用 ...

    MVCAJAX用JQUERY调用实例例子

    这通常在Web应用开发中用于实现无刷新的数据交互,提高用户体验。 首先,让我们理解MVC模式。MVC是一种软件设计模式,它将应用程序分为三个主要组件:模型(Model)负责数据处理和业务逻辑,视图(View)显示数据,...

    ASP.NET MVC框架开发系列课程(19):jQuery与AJAX

    在实际开发中,我们还可能遇到跨域问题、异步操作的同步处理、AJAX请求的取消等复杂情况,需要灵活运用jQuery和ASP.NET MVC提供的工具和特性来解决。 通过结合使用jQuery和AJAX,ASP.NET MVC开发者可以构建更加互动...

    ajax跨域访问WCP搜索,返回JSON数据

    标题中的“ajax跨域访问WCP搜索,返回JSON数据”涉及到的是Web开发中关于AJAX、跨域资源共享(CORS)以及JSON数据格式的应用。在Web应用中,AJAX(Asynchronous JavaScript and XML)是一种在无需刷新整个页面的情况...

    ASP.NET MVC中设置跨域访问问题

    在ASP.NET MVC框架中,跨域访问问题是一个常见的开发挑战,主要是由于浏览器的同源策略所限制。同源策略规定,JavaScript只能与相同协议、主机和端口的资源进行交互,以防止恶意脚本跨站执行。然而,在实际应用中,...

    bboss mvc 通过jsonp实现跨站跨域远程访问

    标题 "bboss mvc 通过jsonp实现跨站跨域远程访问" 涉及到的主要知识点是关于Web开发中的跨域通信技术,特别是利用JSONP(JSON with Padding)来解决AJAX请求时遇到的同源策略限制。在互联网应用中,浏览器的安全策略...

    MVC的JavaScript Web富应用开发(完整版)

    讲解远程数据加载、第二代Ajax以及跨域请求 利用WebSockets和Node构建实时应用 拖拽上传文件以及上传进度提示 讲解主流的库和框架,包括jQuery、JavaScriptMVC以及Backbone 编写测试用例,并使用控制台工具来...

    java Web开发AJAX ppt课件.zip

    **Java Web开发与AJAX** 在Java Web开发中,AJAX(Asynchronous JavaScript and XML)是一种核心技术,用于创建动态、交互式的网页应用。通过使用AJAX,开发者可以在不重新加载整个页面的情况下,从服务器获取数据...

    spring_mvc_ajax.zip_SpringMVC ajax_SpringMVC+ajax_spring ajax_sp

    通过“spring_mvc_ajax.zip”中的资源,你可以深入学习和实践SpringMVC与Ajax的集成,了解如何创建一个有效的异步数据交互系统。这个压缩包可能包含了相关的Java代码、HTML模板、JavaScript脚本以及配置文件,供你...

    征服Ajax Web 2.0

    **Ajax(Asynchronous JavaScript and XML)技术是Web 2.0的核心组成部分,它极大地提升了网页的用户体验,通过异步方式与服务器进行数据交互,无需刷新整个页面即可更新局部内容。本资源提供了学习Ajax以及Web 2.0...

    基于javaweb 的 AJAX最全面的实例源码

    10. **AJAX与Spring MVC**:在JavaWeb环境中,AJAX常与MVC框架如Spring MVC结合,用于处理后台控制器的请求,返回JSON数据供前端解析。 11. **Error Handling**:良好的错误处理是必不可少的,包括网络故障、服务器...

Global site tag (gtag.js) - Google Analytics