mvc JsonP 跨域访问实现

  MVC Controller 的action代码返回JsonResult的保持原样,还是返回JsonResult。为需要跨域访问的Controller action接口写一个基类Controller,名为 BaseController,然后跨域的Controller 继承该Controller。

  BaseController中 重写 OnActionExecuted 方法,将 filterContext.Result = new JsonpResult{......},且给自己定义的且继承自JsonpResult的相关属性赋值,则可以返回自己想要的JsonpResult。

1. BaseController 代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using CYP.Activity.Common;
using Microsoft.Practices.ServiceLocation;

namespace CYP.Activity.Web.Mvc
{
    public class BaseController : Controller
    {
        private readonly JsonRequestBehavior _allowGet = (BaseConfig.AllowGet)
          ? JsonRequestBehavior.AllowGet
          : JsonRequestBehavior.DenyGet;

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var incomingOrigin = HttpContext.Request.Headers.Get("Origin"); //判断来源的域 是否为 可访问的域,可访问则可以返回数据
            if ((!string.IsNullOrEmpty(incomingOrigin)) &&
                BaseConfig.DomainUrl.IndexOf(incomingOrigin, StringComparison.OrdinalIgnoreCase) > -1)
            {
                HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", incomingOrigin);
            }

            //if (HttpContext.Request.HttpMethod == "OPTIONS")
            //{
            //    HttpContext.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
            //    HttpContext.Response.AddHeader("Access-Control-Allow-Headers",
            //        "Content-Type, Authorization, Accept,X-Requested-With");
            //    HttpContext.Response.End();
            //}

        }

        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext == null)
                throw new ArgumentNullException("filterContext");

            // 查看是否包含 callback
            var callbackparam = filterContext.HttpContext.Request.QueryString["callbackparam"];
            var exceptionMsg = string.Empty;
            if ((_allowGet == JsonRequestBehavior.DenyGet) &&
                    String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET"))
            {
                exceptionMsg = "Deny Get Request.";
                //throw new InvalidOperationException("Deny Get Request");
            }

            var result = filterContext.Result as JsonResult;
            if ((!string.IsNullOrEmpty(callbackparam)) && callbackparam.Length > 0)
            {
                if (result == null)
                {
                    exceptionMsg = "Result is null.";
                    //throw new InvalidOperationException("Result is null.");
                }
            }

            filterContext.Result = new JsonpResult
            {
                ContentEncoding =
                    (result == null || (!string.IsNullOrEmpty(exceptionMsg)))
                        ? Encoding.UTF8
                        : result.ContentEncoding,
                ContentType = (result == null || (!string.IsNullOrEmpty(exceptionMsg))) ? "" : result.ContentType,
                Data = (result == null || (!string.IsNullOrEmpty(exceptionMsg))) ? exceptionMsg : result.Data,
                Callback = callbackparam
            };
        }
    }
}
View Code


2.JsonpResult  代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace CYP.Activity.Common
{
    public class JsonpResult : JsonResult
    {
        public string Callback { get; set; }

        //private readonly JsonRequestBehavior _allowGet = (BaseConfig.AllowGet)
        //    ? JsonRequestBehavior.AllowGet
        //    : JsonRequestBehavior.DenyGet;

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            //if ((_allowGet == JsonRequestBehavior.DenyGet) &&
            // String.Equals(context.HttpContext.Request.HttpMethod, "GET"))
            //{
            //    throw new InvalidOperationException();
            //}

            HttpResponseBase response = context.HttpContext.Response;
            if (!String.IsNullOrEmpty(ContentType))
                response.ContentType = ContentType;
            else
                response.ContentType = "application/javascript";

            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;

            if ((string.IsNullOrEmpty(Callback)) || Callback.Length == 0)
                Callback = context.HttpContext.Request.QueryString["callback"];

            if (Data != null)
            {
                var serializer = new JavaScriptSerializer();
                string ser = serializer.Serialize(Data);
                response.Write(Callback + "(" + ser + ");");
            }
        }
    }
}
View Code

 

3.Controller继承 BaseController 代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using System.Web.UI.WebControls;
using CYP.Activity.Common;
using CYP.Activity.Web.Mvc;
using CYP.ActivityOrder.Domain;
using Microsoft.Practices.ServiceLocation;
using CYP.ActivityOrder.Service;

namespace CYP.Activity.Web.Controllers
{
    public class ActiOrderController : BaseController
    {
        private readonly IActiOrderService _actiOrdersService;

        private readonly JsonRequestBehavior _allowGet = (BaseConfig.AllowGet)
            ? JsonRequestBehavior.AllowGet
            : JsonRequestBehavior.DenyGet;
        //private readonly JavaScriptSerializer _serializer = new JavaScriptSerializer();

        public ActiOrderController()
        {
            _actiOrdersService = ServiceLocator.Current.GetInstance<IActiOrderService>();
        }

        /// <summary>
        /// 获取数据库时间戳
        /// </summary>
        /// <returns></returns>
        [JsonException]
        public JsonResult GetDbTime(string callbackparam)
         {
             var result = _actiOrdersService.GetDbTime();
             return Json(new { Success = true, DbTime = result }, _allowGet);
         }

       
        /// <summary>
        /// 获取 总成交车辆数 / 总成交金额 / 上一小时成交量
        /// </summary>
        /// <returns></returns>
         [JsonException]
        public JsonResult GetTotalActivityOrder(string callbackparam, int previous = 0)
        {
            var result = _actiOrdersService.GetTotalActivityOrder(previous);
            return Json(new { Success = true, Data = result }, _allowGet);
        }

    }
}
View Code

 

4.继承自HandleErrorAttribute的JsonExceptionAttribute捕获异常的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using System.Web.UI.WebControls;

namespace CYP.Activity.Common
{
    [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class JsonExceptionAttribute : HandleErrorAttribute
    {
        private readonly CYPLog.TextLogger _globalErrorLog = CYPLog.TextLogManager.Create(typeof(JsonExceptionAttribute));

        public override void OnException(ExceptionContext filterContext)
        {
            //记录错误
            _globalErrorLog.Error(string.Format("在请求链接【{0}】时产生异常,异常原因:【{1}】", filterContext.HttpContext.Request.Url,
                filterContext.Exception.ToString()));

            var callbackparam = filterContext.HttpContext.Request.QueryString["callbackparam"];

            if (!filterContext.ExceptionHandled)
            {
                var result = filterContext.Result as JsonResult;

               if (result == null)
                {
                    throw new InvalidOperationException("JsonExceptionAttribute must be applied only " +
                                                        "on controllers and actions that return a JsonResult object.");
                }

                filterContext.Result = new JsonpResult
                {
                    ContentEncoding = result.ContentEncoding,
                    ContentType = result.ContentType,
                    Data = result.Data,
                    Callback = callbackparam
                };
            }

            filterContext.ExceptionHandled = true;
        }
    }
}
View Code

 

5.页面Js调用代码如下:

$.ajax({
            url: actPrefix + 'ActiOrder/GetDbTime',
            cache: false,
            type: "POST",
            dataType: "jsonp",
            jsonp: "callbackparam", //服务端用于接收callback调用的function名的参数
            jsonpCallback: "success_getTime", //callback的function名称
            success: function(data) {
                if (data != null && data.DbTime != null && data.Success) {
                    timeDif = new Date().getTime() - data.DbTime;
                }
            }
        });
View Code

 

 

So,EveryThing is oK!Come On!

 

posted on 2015-04-08 16:55  HappySmile  阅读(235)  评论(0编辑  收藏  举报

导航