2012-06-18 24 views
46

¿Por qué este servicio web simple se niega a devolver JSON al cliente?asp.net servicio web asmx que devuelve xml en lugar de json

Aquí está mi código de cliente:

 var params = { }; 
     $.ajax({ 
      url: "/Services/SessionServices.asmx/HelloWorld", 
      type: "POST", 
      contentType: "application/json; charset=utf-8", 
      dataType: "json", 
      timeout: 10000, 
      data: JSON.stringify(params), 
      success: function (response) { 
       console.log(response); 
      } 
     }); 

Y el servicio:

namespace myproject.frontend.Services 
{ 
    [WebService(Namespace = "http://tempuri.org/")] 
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
    [System.ComponentModel.ToolboxItem(false)] 
    [ScriptService] 
    public class SessionServices : System.Web.Services.WebService 
    { 
     [WebMethod] 
     [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 
     public string HelloWorld() 
     { 
      return "Hello World"; 
     } 
    } 
} 

web.config:

<configuration> 
    <system.web> 
     <compilation debug="true" targetFramework="4.0" /> 
    </system.web> 
</configuration> 

Y la respuesta:

<?xml version="1.0" encoding="utf-8"?> 
<string xmlns="http://tempuri.org/">Hello World</string> 

No importa lo que haga, la respuesta siempre vuelve como XML. ¿Cómo consigo que el servicio web devuelva a Json?

EDIT:

Aquí es la traza Fiddler HTTP:

REQUEST 
------- 
POST http://myproject.local/Services/SessionServices.asmx/HelloWorld HTTP/1.1 
Host: myproject.local 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1 
Accept: application/json, text/javascript, */*; q=0.01 
Accept-Language: en-gb,en;q=0.5 
Accept-Encoding: gzip, deflate 
Connection: keep-alive 
Content-Type: application/json; charset=utf-8 
X-Requested-With: XMLHttpRequest 
Referer: http://myproject.local/Pages/Test.aspx 
Content-Length: 2 
Cookie: ASP.NET_SessionId=5tvpx1ph1uiie2o1c5wzx0bz 
Pragma: no-cache 
Cache-Control: no-cache 

{} 

RESPONSE 
------- 
HTTP/1.1 200 OK 
Cache-Control: private, max-age=0 
Content-Type: text/xml; charset=utf-8 
Server: Microsoft-IIS/7.5 
X-AspNet-Version: 4.0.30319 
X-Powered-By: ASP.NET 
Date: Tue, 19 Jun 2012 16:33:40 GMT 
Content-Length: 96 

<?xml version="1.0" encoding="utf-8"?> 
<string xmlns="http://tempuri.org/">Hello World</string> 

He perdido la cuenta de la cantidad de artículos que he leído ahora tratar de solucionar este problema. Las instrucciones están incompletas o no resuelven mi problema por algún motivo. Algunos de los más relevantes incluyen (todas sin éxito):

Plus varios otros artículos generales.

+0

Veo la etiqueta del marco de destino establecida en 4.0, ¿en qué versión del marco está integrada su aplicación? – Terry

+0

En Propiedades del proyecto en la pestaña Aplicación, el Marco de destino es ".NET Framework 4". ¿Es suficiente, o tengo que configurarlo en otro lugar? Lo siento, soy relativamente nuevo en VS (más experiencia js) – njr101

+0

Tu código parece correcto. ¿Podría registrar su solicitud AJAX y la respuesta del servidor utilizando WireShark? Sería útil ver estos paquetes HTTP para entender lo que sucede. – kol

Respuesta

41

Finalmente lo descubrió.

El código de la aplicación es correcto según lo publicado. El problema es con la configuración. El web.config correcta es:

<configuration> 
    <system.web> 
     <compilation debug="true" targetFramework="4.0" /> 
    </system.web> 
    <system.webServer> 
     <handlers> 
      <add name="ScriptHandlerFactory" 
       verb="*" path="*.asmx" 
       type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
       resourceType="Unspecified" /> 
     </handlers> 
    </system.webServer> 
</configuration> 

De acuerdo con la documentación, el registro de la guía debería ser innecesario de .NET 4 hacia arriba, ya que ha sido movido a la machine.config. Por alguna razón, esto no funciona para mí. Pero al agregar el registro a web.config para mi aplicación, se resolvió el problema.

Muchos de los artículos sobre este problema indican agregar el controlador a la sección <system.web>. Esto NO funciona y causa una carga completa de otros problemas. Traté de agregar el controlador a ambas secciones y esto genera un conjunto de otros errores de migración que dirigieron por completo mi solución de problemas.

En caso de que ayuda a nadie más, si tuviera allí mismo problema de nuevo, aquí está la lista de verificación Me opinar:

  1. ¿Ha especificado type: "POST" en la solicitud Ajax?
  2. ¿Ha especificado contentType: "application/json; charset=utf-8" en la solicitud de ajax?
  3. ¿Ha especificado dataType: "json" en la solicitud de ajax?
  4. ¿Su servicio web .asmx incluye el atributo [ScriptService]?
  5. ¿Su método web incluye el atributo [ScriptMethod(ResponseFormat = ResponseFormat.Json)] ? (Mi código funciona incluso sin este atributo, pero muchos artículos dicen que es necesario)
  6. ¿Ha agregado el ScriptHandlerFactory al archivo web.config en <system.webServer><handlers>?
  7. ¿Ha eliminado todos los controladores del archivo web.config en <system.web><httpHandlers>?

Espero que esto ayude a cualquier persona con el mismo problema. y gracias a los carteles por sugerencias.

+1

He estado golpeando mi cabeza contra la pared por unas horas en esto y su publicación ha sido muy útil. He corrido los siete pasos y mi servicio aún devuelve xml en la respuesta. Estoy usando ASP.NET 3.5, ¿algún otro pensamiento? También estoy usando el complemento de formulario jQuery (no es necesario indicar explícitamente POST, json, etc.) – Daryl

+0

Si abre una nueva pregunta y agrega un comentario aquí enlazándola, puedo echarle un vistazo. Incluya un rastro de violín de la solicitud y la respuesta. Incluya su web.config completo. Y también incluye el código asp.net que incluye específicamente los atributos. Sugiero que pruebes usando un servicio similar de "Hola mundo" según mi ejemplo. – njr101

+0

Esta respuesta me ayudó mucho, especialmente los siete pasos que mencionó. –

0

Para mí trabaja con el código que tengo de este post:

How can I return json from my WCF rest service (.NET 4), using Json.Net, without it being a string, wrapped in quotes?

[WebInvoke(UriTemplate = "HelloWorld", Method = "GET"), OperationContract] 
public Message HelloWorld() 
{ 
    string jsonResponse = //Get JSON string here 
    return WebOperationContext.Current.CreateTextResponse(jsonResponse, "application/json; charset=utf-8", Encoding.UTF8); 
} 
+0

El atributo ScriptService debe ocuparse de esto automáticamente. Realmente no quiero manejar todas las cosas de serialización yo mismo. Tengo otros proyectos donde este código funciona bien. Pero están en otros servidores, lo que me hace pensar que hay algún tipo de problema de configuración. – njr101

19

Ningún éxito con la solución anterior, aquí cómo lo resolví.

poner esta línea en su servicio web y más bien volver tipo que acaba de escribir la cadena en el contexto de la respuesta

this.Context.Response.ContentType = "application/json; charset=utf-8"; 
this.Context.Response.Write(serial.Serialize(city)); 
+6

¡Lo hiciste! Esta es la mejor respuesta. Hice que mi función fuera un tipo de retorno "vacío" y usé su código, y la autocompletar de JQuery UI comienza a funcionar finalmente. – Dexter

+0

Muchas gracias ... ¡Funcionó para mí! –

+0

Eso es tosco y preocupante, pero brutalmente efectivo cuando la suciedad más complicada no parece resolver mi problema. Esto funciona. – philw

1

Tengo un servicio web .asmx (.NET 4.0) con un método que devuelve una cadena. La cadena es una lista serializada como la que ve en muchos de los ejemplos. Esto devolverá json que no está envuelto en XML. Sin cambios en web.config o necesidad de archivos DLL de terceros.

parte
var tmsd = new List<TmsData>(); 
foreach (DataRow dr in dt.Rows) 
{ 

m_firstname = dr["FirstName"].ToString(); 
m_lastname = dr["LastName"].ToString(); 

tmsd.Add(new TmsData() { FirstName = m_firstname, LastName = m_lastname}); 

} 

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); 
string m_json = serializer.Serialize(tmsd); 

return m_json; 

El cliente que utiliza el servicio es el siguiente:

$.ajax({ 
     type: 'POST', 
     contentType: "application/json; charset=utf-8", 
     dataType: 'json', 
     url: 'http://localhost:54253/TmsWebService.asmx/GetTombstoneDataJson', 
     data: "{'ObjectNumber':'105.1996'}", 
     success: function (data) { 
      alert(data.d); 
     }, 
     error: function (a) { 
      alert(a.responseText); 
     } 
    }); 
11

Si desea permanecer quedarse con Framework 3.5, es necesario hacer cambios en el código de la siguiente manera.

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[ScriptService] 
public class WebService : System.Web.Services.WebService 
{ 
    public WebService() 
    { 
    } 

    [WebMethod] 
    public void HelloWorld() // It's IMP to keep return type void. 
    { 
     string strResult = "Hello World"; 
     object objResultD = new { d = strResult }; // To make result similarly like ASP.Net Web Service in JSON form. You can skip if it's not needed in this form. 

     System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer(); 
     string strResponse = ser.Serialize(objResultD); 

     string strCallback = Context.Request.QueryString["callback"]; // Get callback method name. e.g. jQuery17019982320107502116_1378635607531 
     strResponse = strCallback + "(" + strResponse + ")"; // e.g. jQuery17019982320107502116_1378635607531(....) 

     Context.Response.Clear(); 
     Context.Response.ContentType = "application/json"; 
     Context.Response.AddHeader("content-length", strResponse.Length.ToString()); 
     Context.Response.Flush(); 

     Context.Response.Write(strResponse); 
    } 
} 
+0

Sería útil agregar a su respuesta lo que ha usado y posiblemente vincular a la documentación. De esta forma, es mucho más fácil para otra persona descubrir cómo funciona exactamente y cómo pueden usarlo en otra situación. – Sumurai8

+0

Esta respuesta funciona bien para ASMX + jQuery en Sharepoint 2010 y .NET Framework 3.5. Decidí usar 'JavaScriptSerializer' estándar en lugar de referencia al ensamblado de NewtonJson. ¡Gracias! – opewix

0

que han intentado todos los pasos anteriores (aunque la respuesta), pero no tuvo éxito, la configuración de mi sistema es Windows Server 2012 R2, IIS 8. El siguiente paso resuelto mi problema.

Cambió el grupo de aplicaciones, que tiene una tubería administrada = clásica.

6

Hay una manera mucho más fácil de devolver una cadena pura del servicio web. Lo llamo la función CROW (lo hace fácil de recordar).

[WebMethod] 
    public void Test() 
    { 
     Context.Response.Output.Write("and that's how it's done");  
    } 

Como se puede ver, el tipo de cambio es "vacío", pero la función CUERVO seguirá devolviendo el valor que desee.

+0

Esto funcionó perfectamente para mí. Cambié el retorno de secuencia a un vacío y usé el contexto.response.output.write para escupir el JSON que se serializó. – Josh

-1
response = await client.GetAsync(RequestUrl, HttpCompletionOption.ResponseContentRead); 
if (response.IsSuccessStatusCode) 
{ 
    _data = await response.Content.ReadAsStringAsync(); 
    try 
    { 
     XmlDocument _doc = new XmlDocument(); 
     _doc.LoadXml(_data); 
     return Request.CreateResponse(HttpStatusCode.OK, JObject.Parse(_doc.InnerText)); 
    } 
    catch (Exception jex) 
    { 
     return Request.CreateResponse(HttpStatusCode.BadRequest, jex.Message); 
    } 
} 
else 
    return Task.FromResult<HttpResponseMessage>(Request.CreateResponse(HttpStatusCode.NotFound)).Result; 
0

Sé que es una pregunta muy antigua, pero he tenido el mismo problema hoy y he estado buscando en todas partes para encontrar la respuesta pero sin resultado. Después de una larga investigación, he encontrado la manera de hacer que esto funcione.Para devolver JSON del servicio que ha proporcionado datos solicitados en el formato correcto, use JSON.stringify() para analizar los datos antes de la solicitud y no olvide contentType: "application/json; charset=utf-8", utilizando esto debería proporcionar el resultado esperado.

0

Espero que esto ayude, parece que todavía tiene que enviar algún objeto JSON en la solicitud, incluso si el Método que está llamando no tiene parámetros.

var params = {}; 
return $http({ 
     method: 'POST', 
     async: false, 
     url: 'service.asmx/ParameterlessMethod', 
     data: JSON.stringify(params), 
     contentType: 'application/json; charset=utf-8', 
     dataType: 'json' 

    }).then(function (response) { 
     var robj = JSON.parse(response.data.d); 
     return robj; 
    }); 
Cuestiones relacionadas