2010-09-30 7 views
55

Estoy tratando de obtener algunos datos json de un sitio web "remoto". Ejecuto mi servicio web en el puerto 99000 y luego, lanzo mi sitio web en el puerto 99001 (http: // localhost: 99001/index.html).XMLHttpRequest no puede cargar una URL con jQuery

me sale el siguiente mensaje:

XMLHttpRequest cannot load http://localhost:99000/Services.svc/ReturnPersons. Origin http://localhost:99001 is not allowed by Access-Control-Allow-Origin. 

incluso si pongo en marcha mi página web como un archivo HTML, me sale esto:

XMLHttpRequest cannot load http://localhost:99000/Services.svc/ReturnPersons.Origin null is not allowed by Access-Control-Allow-Origin. 

Los datos devuelve el servicio Web. Trato de atrapar a los elementos de datos de esta manera:

var url = "http://localhost:99000/Services.svc/ReturnPersons"; 
$.getJSON(url, function (data) { 
success: readData(data) 
}); 
function readData(data) { 
    alert(data[0].FirstName); 
} 

Y yo estoy tratando de conseguir esta estructura:

[{"FirstName":"Foo","LastName":"Bar"},{"Hello":"Foo","LastName":"World"}] 

¿Conoce por qué estoy recibiendo este error?

Respuesta

39

No se puede hacer un crossdomain XMLHttpRequest, la única "opción" sería una técnica llamada JSONP, que se reduce a esto:

Para iniciar la solicitud: Añadir un nuevo <script> etiqueta con la dirección URL remota y luego asegúrese de que la URL remota devuelva un archivo javascript válido que llame a su función de devolución de llamada. Algunos servicios lo admiten (y le permiten nombrar su devolución de llamada en un parámetro GET).

La otra salida fácil sería crear un "proxy" en su servidor local, que obtiene la solicitud remota y luego simplemente "reenvía" la contraseña a su javascript.

editar/Además:

veo jQuery ha incorporado soporte para JSONP, comprobando si la URL contiene "? Devolución de llamada =" (donde jQuery reemplazará? con el método de devolución de llamada real). Pero aún tendría que procesar eso en el servidor remoto para generar una respuesta válida.

+9

He resuelto el problema agregando el "& callback =?" a la URL ¡Gracias! – Zakaria

+0

¿Debo especificar/implementar algo en el script del servidor en el servidor remoto? – j7nn7k

+0

Sí, donde su servidor normalmente devuelve una cadena JSON, p. '{" foo ":" bar "}' necesita envolver la cadena json en un método de devolución de llamada (función javascript) que maneja la respuesta json. p.ej. 'myFunction ({" foo ":" bar "}};' – CharlesLeaf

33

En nueva jQuery 1.5 que puede utilizar:

$.ajax({ 
    type: "GET", 
    url: "http://localhost:99000/Services.svc/ReturnPersons", 
    dataType: "jsonp", 
    success: readData(data), 
    error: function (xhr, ajaxOptions, thrownError) { 
     alert(xhr.status); 
     alert(thrownError); 
    } 
}) 
+4

¿No debería ser solo "success: readData"? –

+2

Recibí un error como SyntaxError: Token inesperado: –

+0

Supongo que es extra ":" en su respuesta. podrías pegar todo el mensaje? – Slavomir

19

Fiddle with 3 working solutions en acción.

Dado un JSON externo:

myurl = 'http://wikidata.org/w/api.php?action=wbgetentities&sites=frwiki&titles=France&languages=zh-hans|zh-hant|fr&props=sitelinks|labels|aliases|descriptions&format=json' 

Solución 1: $ .ajax() + jsonp:

$.ajax({ 
    dataType: "jsonp", 
    url: myurl , 
    }).done(function (data) { 
    // do my stuff 
}); 

Solución 2: $ .ajax() + JSON + & calback = ?:

$.ajax({ 
    dataType: "json", 
    url: myurl + '&callback=?', 
    }).done(function (data) { 
    // do my stuff 
}); 

Solución 3: $ .getJSON() + calback =?:

$.getJSON(myurl + '&callback=?', function(data) { 
    // do my stuff 
}); 

Documentación: http://api.jquery.com/jQuery.ajax/, http://api.jquery.com/jQuery.getJSON/

+0

JSfiddle solucionó los siguientes cambios de la API #wikidata, se realizó una mejora de jsfiddle, se realizó una mejora en la redacción. – Hugolpz

+0

No funciona en ** HTTPS. ** Haga clic en el enlace para ver https://jsfiddle.net/HNPyc/98/ –

+1

@TuhinPaul: cuando está en ** https ** violín no puede solicitar ** http * * wikidata u otros http, sería una violación de seguridad. Puede hacer http-http, https-https o http-https, no https-http. Esta es una característica de seguridad, no un problema de dominio cruzado. – Hugolpz

6

encontrado una posible solución alternativa que no creo que se ha mencionado.

Aquí es una buena descripción del problema: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Básicamente, siempre y cuando utiliza formularios// contenido de texto plano tipos de codificación URL que están bien.

$.ajax({ 
    type: "POST", 
    headers: { 
     'Accept': 'application/json', 
     'Content-Type': 'text/plain' 
    }, 
    dataType: "json", 
    url: "http://localhost/endpoint", 
    data: JSON.stringify({'DataToPost': 123}), 
    success: function (data) { 
     alert(JSON.stringify(data)); 
    } 
});  

Lo uso con ASP.NET WebAPI2. Así que en el otro extremo:

public static void RegisterWebApi(HttpConfiguration config) 
{ 
    config.MapHttpAttributeRoutes(); 

    config.Formatters.Clear(); 
    config.Formatters.Add(new JsonMediaTypeFormatter()); 

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain")); 
} 

De esta manera JSON formateador se acostumbra al analizar el tipo de contenido de texto sin formato.

Y no se olvide de Web.config:

<system.webServer> 
<httpProtocol> 
    <customHeaders> 
    <add name="Access-Control-Allow-Origin" value="*" /> 
    <add name="Access-Control-Allow-Methods" value="GET, POST" /> 
    </customHeaders> 
</httpProtocol>  

Espero que esto ayude.

0

Estoy usando WebAPI 3 y estaba enfrentando el mismo problema. El problema se resolvió cuando @Rytis agregó su solución. Y creo que en WebAPI 3, no necesitamos definir el método RegisterWebApi.

Mi cambio fue solo en el archivo web.config y está funcionando.

<httpProtocol> 
<customHeaders> 
<add name="Access-Control-Allow-Origin" value="*" /> 
<add name="Access-Control-Allow-Methods" value="GET, POST" /> 
</customHeaders> 
</httpProtocol> 

Gracias por su solución @Rytis!

Cuestiones relacionadas