【问题标题】:Handling cross-domain calls on phone gap处理电话间隙的跨域呼叫
【发布时间】:2012-12-04 04:40:14
【问题描述】:

我正在为以下内容寻找最佳实践实现...

我有一个调用 .asmx Web 服务的 JQuery 脚本,但在域外调用时无法加载,我知道当我将 html 移至 PhoneGap 时会发生这种情况。

是使用 JSONP 的最佳/唯一解决方案吗?

我不拘泥于 .asmx 或 jquery 等。欢迎您使用过的任何有效的想法。

只需要能够从 html5 调用服务器上的方法。 (而且 html5 应用程序不会离线运行)。

谢谢!

【问题讨论】:

    标签: jquery cordova cross-domain jsonp asmx


    【解决方案1】:

    我会说 JSONP 绝对是最好的方法,如果你需要在你的服务器端代码中允许 OPTIONS 方法,你可以实现类似的代码。 (注意:此示例在技术上适用于 MVC,但可以进行调整。)

    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();
    
            filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", "*");
    
            string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
            {
                filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                filterContext.RequestContext.HttpContext.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin, Content-Type");
            }
            base.OnActionExecuting(filterContext);
        }
    }
    
    [HttpGet]
    [AllowCrossSiteJsonAttribute]
    public JsonpResult CommunicateCard(CommunicateCardModel ccm)
    {
        return ModelState.IsValid
            ? this.ValidCommunicateCardBuilder(ccm)
            : this.InvalidFormSummary(ccm);
    }
    

    旁注:这是我正在使用的 JsonpResult。效果很棒。

    namespace System.Web.Mvc
    {
        #region usings
        using System;
    
        using WebService.Attributes;
        using WebService.Domain.Models;
        using WebService.Exceptions;
        using WebService.Models.ViewModels;
        using Extensions;
        using WebService.Utilities;
        #endregion
    
        public class JsonpResult : ActionResult
        {
            public Object Data { get; set; }
            public string JsonCallback { get; set; }
            public bool? Success { get; set; }
    
    
            public override void ExecuteResult(ControllerContext context)
            {
    
                // Create a JsonResponse that we can Send out
    
                // Check for the callback parameter
                this.JsonCallback = context.HttpContext.Request["callback"];
    
                // if the "callback" doesn't exist, we want to check for "jsoncallback"
                if (string.IsNullOrEmpty(this.JsonCallback))
                    this.JsonCallback = context.HttpContext.Request["jsoncallback"];
    
                // If we've made it this far, we know that the object sent is an
                // object that we can serialize and Send back as valid JSON. We now
                // need to wrap it in our JsonViewModel for consistancy. NOTE: We're
                // using the AsList() extension method to ensure that we're
                // returning an Array since our application (Sencha Touch) requires
                // all data to be in array format.
                if (!Data.GetType().IsGenericType)
                    Data = Data.AsList();
    
                // Until now we the data is either an ERROR, or null
                // if it's null, and the Data is not null, we set Success = true
                // If Success is false, it's because we set it to false when we threw an error
                // if that's the case, we keep it false for the client.
                if (Success == null) Success = true;
    
    
                var jsonViewModel = new JsonViewModel
                    {
                        results = this.Data,
                        // We know that Success is either True or False so we can
                        // safely cast the nullable bool to a bool.
                        success = (bool)this.Success
                    };
                WriteOut(jsonViewModel, context);
            }
    
            /// <summary>
            /// Write Out the JsonP Response to the Controller.
            /// </summary>
            /// <param name="jsonResponse">The unserialized object</param>
            /// <param name="context">Controller Context</param>
            private void WriteOut(JsonViewModel jsonResponse, ControllerContext context)
            {
                var response = context.HttpContext.Response;
                response.ContentType = "application/javascript";
                response.Write(JsonUtility.Serialize(jsonResponse, this.JsonCallback));
            }
        }
    
        /// <summary>
        /// extension methods for the controller to allow jsonp.
        /// </summary>
        public static class ContollerExtensions
        {
            public static JsonpResult Jsonp(this Controller controller, Object data)
            {
                return new JsonpResult { Data = data };
            }
    
            public static JsonpResult Jsonp(this Controller controller, Object data, bool success)
            {
                // We don't ever want to pass in a "true" success. We only want to 
                // know if it failed.
                if (success)
                {
                    return new JsonpResult { Data = data };
                }
    
                return new JsonpResult { Success = false, Data = data };
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      是的,JSONP 是您问题的答案。 JSONP 或“带填充的 JSON”是一种 JSON 扩展,其中前缀被指定为调用本身的输入参数,并简单地克服 XMLHttpRequest 相同的域策略。

      Read more, Read more

      这两个链接应该可以帮助您。如果您有任何问题,请告诉我。

      【讨论】:

        【解决方案3】:

        要了解有关 JSONP 的更多信息,请单击 here

        JSONP 可以简单地定义为(这是 Remy Sharp 博客的摘录)

        JSONP 是脚本标签注入,将来自服务器的响应传入 到用户指定的函数

        这个link 也可以帮助您找到解决问题的方法。

        【讨论】:

          【解决方案4】:

          如果您使用的是 Phonegap,它会使用 file:// 协议加载本地 html 文件。您的加载失败可能与 same origin policy 有关,并且不适用于 file:// 协议。因此,使用 file:// 协议加载您的 html,您就可以进行跨浏览器调用。检查this article 以了解更多信息。还要检查Phonegap's docs about Domain whitelisting

          祝你好运!

          【讨论】:

          • 听起来很有趣的信息。但是您的第三个链接不起作用
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多