No Transport Error with Cross-Domain call

Topics: jQuery, Web Api
Dec 16, 2011 at 5:56 PM
Edited Dec 16, 2011 at 5:58 PM

Hi, I'm relatively new to WebApi, but I've got it to work with my data objects and the Test Client.  But when I create a scenario of cross-domain testing, I get a "No Transport" error message back.

I initially tried using the Telerik KendoUI components, and while there was no error, I didn't get any results back.  Then I tried building a simple GET request with jQuery similar to the ContactManager example and that's where I get the "No Transport" error.

I'm sure it's something I'm missing.  I do not have any formatters attached and I want to return json, but this message occurs with either "xml" or "json" and the 'dataType' in an $.ajax() call.

I guess my questions are:

  1. What am I doing wrong?
  2. Is there a best practice for cross-domain calls?

I intend for this service to be public (with credentials) that other services can call, similar to many other API's that are out there today.

Here's my HTML in the MVC application which is a different web application than my WebApi service.

URL: http://localhost:62421/home/moreblogs

 

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>MoreBlogs</title>
        <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
        <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js" type="text/javascript"></script>
</head>
<body>
    <div>
        <ul id="blogs"></ul>
    </div>

    <script type="text/javascript">
        $(function () {

            try {
//                $.getJSON("http://localhost:58016/blogs",null, function (data) {
//                    $.each(data, function (index, value) {
//                        $("#blog-template").tmpl(value).appendTo("#blogs");
//                    });
//                });

                $.ajax({
                    url: "http://localhost:58016/blogs",
                    dataType: "json",
                    type: "GET",
                    crossDomain: true,
                    success: function (data) {
                        $.each(data, function (index, value) {
                            $("#blog-template").tmpl(value).appendTo("#blogs");
                        });
                    },
                    error: function (xhr, status, error) {
                        alert(error + " - " + status);
                    }
                });

            } catch (e) {
                alert(e);
            }
        });
    </script>

    <script id="blog-template" type="text/html">
        <li>
            <h2>${ Title }</h2>
        </li>
    </script>
</body>
</html>

 

Here's my WebApi configuration, it's in an App_Start file from a Url of http://localhost:58016:

 

using System;
using System.Linq;
using System.ServiceModel.Activation;
using System.Web.Routing;
using Microsoft.ApplicationServer.Http.Activation;

[assembly: WebActivator.PreApplicationStartMethod(typeof(BlogApp6.WebApi.App_Start.WebApi), "Start")]

namespace BlogApp6.WebApi.App_Start {
    public static class WebApi {
        
        public static void Start()
        {            
            HttpServiceHostFactory _factory = null;

            var config = new NinjectWebApiConfiguration();
            _factory = new HttpServiceHostFactory() { Configuration = config };

            RouteTable.Routes.Add(new ServiceRoute("blogs/", _factory, typeof(BlogService)));
            RouteTable.Routes.Add(new ServiceRoute("cars/", _factory, typeof(CarService)));
        }
    }
}

 

This is my NinjectWebApiConfiguration() class:

 

using System;
using System.Linq;
using Microsoft.ApplicationServer.Http;
using Ninject;

namespace BlogApp6.WebApi
{
    public class NinjectWebApiConfiguration : WebApiConfiguration
    {
        private IKernel kernel = new StandardKernel(new NinjectLoader());

        public NinjectWebApiConfiguration()
        {
            CreateInstance = (serviceType, context, request) => kernel.Get(serviceType);
        }
    }
}

 

And this is my NinjectLoader() class that initializes the data objects for dependency injection:

 

using System;
using System.Linq;
using BlogApp6.DataObjects.Interfaces;
using BlogApp6.DataObjects.SQLServer;

namespace BlogApp6.WebApi
{
    public class NinjectLoader: Ninject.Modules.NinjectModule
    {
        public override void Load()
        {
            Bind<IBlogDao>().To<SQLServerBlogDao>();
        }
    }
}

 

Any help is appreciated.

Thanks.

Dec 17, 2011 at 1:28 AM

Ok, I figured it out.  With a little research I found out the you can't simply test cross-domain calls with localhost.  See this post

So I created a new web application in my local IIS 7.x and pointed it to my WebApi application and made sure it was working, then I simply launched my MVC application (via localhost:XXXX in Visual Studio) that had the HTML page with the $.ajax() jQuery call and changed a few things and it worked.

This is the new $.ajax() snippet.

                $.ajax({
                    url: "http://webapi/blogs",
                    dataType: "jsonp",
                    type: "GET",
                    crossDomain: true,
                    success: function (data) {
                        $.each(data, function (index, value) {
                            $("#blog-template").tmpl(value).appendTo("#blogs");
                        });
                    },
                    error: function (xhr, status, error) {
                        alert(error + " - " + status);
                    }
                });

 

The Url is pointing to the non-localhost website, and the dataType is now "jsonp".  Everything else stayed the same and it worked.  It now also works with Telerik's KendoUI components.

Very cool!