Pregunta

Tengo un servicio web ASP.net que estoy usando para una aplicación web que me devuelve datos XML o JSON, dependiendo de la función que llame. Esto ha estado funcionando bien hasta ahora, pero me he encontrado con un problema. Quiero crear una "exportación" enlace en mi página que descargará un archivo JSON. El enlace tiene un formato muy simple:

<a href="mywebserviceaddress/ExportFunc?itemId=2">Export This Item</a>

Como se puede imaginar, esto debería exportar el artículo 2. Hasta ahora todo bien, ¿sí?

El problema es que, dado que no solicito específicamente que el tipo de contenido aceptado sea JSON, ASP.net se niega absolutamente a enviar cualquier cosa que no sea XML, lo cual no es apropiado para esta situación. El código es esencialmente como sigue:

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public Item ExportItem(int itemId)
    {
        Context.Response.AddHeader("content-disposition", "attachment; filename=export.json"); //Makes it a download

        return GetExportItem(itemId);
    }

A pesar de que especifico el ResponseFormat como JSON, siempre obtengo XML a menos que solicite este método a través de AJAX (usando Google Web Toolkit, BTW):

    RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, "mywebserviceaddress/ExportFunc");
    builder.setHeader("Content-type","application/json; charset=utf-8");
    builder.setHeader("Accepts","application/json");
    builder.sendRequest("{\"itemId\":2}", new RequestCallback(){...});

Eso es genial, pero AJAX no me da un cuadro de diálogo de descarga. ¿Hay alguna forma de obligar a ASP.net a devolverme JSON, independientemente de cómo se soliciten los datos? Me parece que no tener una anulación manual para este comportamiento es una grave supervisión de diseño.


RESPUESTA RÁPIDA:

En primer lugar, permítanme decir que creo que la respuesta de womp es probablemente la mejor manera de ir a largo plazo (Convertir a WCF), pero el deostroll me llevó a la respuesta que usaré para el futuro inmediato. Además, debe tenerse en cuenta que esto parece funcionar principalmente porque solo quería una descarga, puede que no funcione tan bien en todas las situaciones. En cualquier caso, aquí está el código que terminé usando para obtener el resultado que quería:

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public void ExportItem(int itemId)
    {
        Item item = GetExportItem(itemId);            

        JavaScriptSerializer js = new JavaScriptSerializer();
        string str = js.Serialize(item);

        Context.Response.Clear();
        Context.Response.ContentType = "application/json";
        Context.Response.AddHeader("content-disposition", "attachment; filename=export.json");
        Context.Response.AddHeader("content-length", str.Length.ToString());
        Context.Response.Flush();
        Context.Response.Write(str);
    }

Tenga en cuenta el tipo de retorno de vacío (lo que significa que su WDSL será inútil para esta función). Devolver cualquier cosa arruinará la respuesta que se está construyendo a mano.

¿Fue útil?

Solución

Aquí hay dos hilos de foros para su referencia:

http://forums.asp.net/t/1118828.aspx

http://forums.asp.net/p/1054378/2338982 .aspx # 2338982

No tengo una idea clara. Dicen sobre concentrarse en establecer el tipo de contenido en application / json. No he trabajado con wcf antes, pero creo que puedes hacer uso del objeto Response.

Establezca el tipo de contenido en el objeto de respuesta. Haga un response.write pasando sus datos json como una cadena y luego haga un response.end.

Otros consejos

Los servicios web Asp.net son servicios web basados ??en SOAP. Siempre devolverán XML. Llegaron las bibliotecas de Ajax y se introdujo el material ScriptMethod, pero no cambia el concepto subyacente de él.

Hay un par de cosas que puedes hacer.

Los WebMethods son casi obsoletos con la introducción de WCF. Puede considerar migrar sus servicios web a WCF , en el cual tener un control mucho mayor sobre el formato de salida.

Si no desea hacer eso, puede serializar manualmente el resultado de sus llamadas de servicio web a JSON, y el servicio lo ajustará en un encabezado SOAP. Entonces necesitarías quitar el material SOAP.

Solo pensé en tirar esto porque no se mencionó anteriormente ... si usa WebServices con ASP.NET 3.5, JSON es el formato de retorno predeterminado. También viene con el serializador JSON para que pueda dejar de usar JavascriptSerializer.

Este artículo en el blog de Rick Strahl habla sobre el fuerte- conversión mecanografiada que puede hacer entre clases del lado del servidor y objetos JSON desde el cliente.

Recientemente completé un proyecto usando este nuevo material JSON en .NET 3.5, y estoy extremadamente impresionado con el rendimiento. Tal vez vale la pena echarle un vistazo ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top