1

I'm looking for a best practice implementation for the following...

I've got a JQuery script that calls an .asmx web service, but it fails to load when called outside of the domain, which I understand is what will happen when I move my html over to PhoneGap.

Is the best/only solution to use JSONP?

I'm not stuck on .asmx or jquery, etc. Open to any ideas that you've used that works well.

Just need to be able to call methods at the server from html5. (and the html5 app wont run offline).

thanks!

localman
  • 497
  • 4
  • 14

4 Answers4

0

Yes JSONP is the answer for your problem. JSONP or "JSON with padding" is a JSON extension wherein a prefix is specified as an input argument of the call itself and simply trick to overcome XMLHttpRequest same domain policy.

Read more, Read more

These two links should help you out. If you have any issue let me know.

Community
  • 1
  • 1
Techie
  • 44,706
  • 42
  • 157
  • 243
0

To know more about JSONP, click here.

Simply JSONP can be defined as (this is an extract from Remy Sharp's blog)

JSONP is script tag injection, passing the response from the server in to a user specified function

This link also may help you in finding solution for your problem.

Melvin Joseph Mani
  • 1,494
  • 15
  • 25
0

If you are using Phonegap, it loads the local html files using the file:// protocol. Your loading fail has probably something to do with the same origin policy, and that does not apply to the file:// protocol. So using the file:// protocol to load your html, you're able to make cross-browser calls. Check this article to read more about it. Also check Phonegap's docs about Domain whitelisting.

Good luck!

weerd2
  • 690
  • 1
  • 5
  • 18
0

I'm gonna say that JSONP is definitely the best way to go here, and if you need to allow for the OPTIONS method in your server side code, you can implement code similar to this. (note: this example is technically for MVC, but can be adapted.)

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);
}

side note: here's the JsonpResult that I'm using. Works awesome.

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 };
        }
    }
}
Chase Florell
  • 46,378
  • 57
  • 186
  • 376