2011-03-31 19 views
8

En un proyecto más grande, tengo problemas para obtener un método de servicio WCF para consumir un parámetro JSON. Así que produje un caso de prueba más pequeño y el comportamiento se repite. Si depuro el servicio, puedo ver que el valor del parámetro es nulo en la llamada de servicio. Fiddler confirma que el JSON se está enviando y JsonLint confirma que es válido.Consumir JSON en el método de servicio WCF

Indique a continuación con las anotaciones de la depuración.

[ServiceContract] 
public interface IWCFService 
{ 

    [OperationContract] 
    [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, 
      ResponseFormat = WebMessageFormat.Json, 
      UriTemplate = "getstring")] 

    string GetString(); 

    [OperationContract] 
    [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, 
     ResponseFormat = WebMessageFormat.Json, 
     UriTemplate = "getplayer")] 
    //[WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest, 
    // ResponseFormat = WebMessageFormat.Json, 
    // UriTemplate = "getplayers")] 
    Player GetPlayer(); 

    [OperationContract] 
    [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, 
     ResponseFormat = WebMessageFormat.Json, 
     UriTemplate = "getplayers")] 
    List<Player> GetPlayers(); 

    [OperationContract] 
    [WebInvoke(
     Method = "POST", 
     BodyStyle = WebMessageBodyStyle.Wrapped, 
     ResponseFormat = WebMessageFormat.Json, 
     RequestFormat = WebMessageFormat.Json, 
     UriTemplate = "totalscore")] 
    string TotalScore(Player player); 

} 

... y su aplicación

public class WCFService : IWCFService 
{ 
    public string GetString() 
    { 
     return "hello from GetString"; 
    } 

    public Player GetPlayer() 
    { 
     return new Player() 
       { 
        Name = "Simon", 
        Score = 1000, 
        Club = new Club() 
          { 
           Name = "Tigers", 
           Town = "Glenelg" 
          } 
       }; 
    } 

    public List<Player> GetPlayers() 
    { 
     return new List<Player>() 
      { 
       new Player() 
        { 
         Name = "Simon", 
         Score = 1000 , 
         Club=new Club() 
           { 
            Name="Tigers", 
            Town = "Glenelg" 
           } 
        }, 
       new Player() 
        { 
         Name = "Fred", Score = 50, 
         Club=new Club() 
           { 
            Name="Blues", 
            Town="Sturt" 
           } 
        } 
      }; 
    } 

    public string TotalScore(Player player) 
    { 
     return player.Score.ToString(); 
    } 
} 

llamando a cualquiera de los tres primeros métodos funciona correctamente (pero no hay parámetros que se le nota). Al llamar al último método (TotalScore) con este código de cliente ...

function SendPlayerForTotal() { 
     var json = '{ "player":{"Name":"' + $("#Name").val() + '"' 
      + ',"Score":"' + $("#Score").val() + '"' 
      + ',"Club":"' + $("#Club").val() + '"}}'; 

     $.ajax(
     { 
      type: "POST", 
      contentType: "application/json; charset=utf-8", 
      url: "http://localhost/wcfservice/wcfservice.svc/json/TotalScore", 
      data: json, 
      dataType: "json", 
      success: function (data) { alert(data); }, 
      error: function() { alert("Not Done"); } 
     }); 
    } 

... ... resultados en

Se ha producido un error al intentar deserializar parámetro http://tempuri.org/:player. El mensaje InnerException fue 'Esperando el' Elemento '. Encontró' Texto 'con el nombre' ', espacio de nombres' '. '.

He intentado enviar un regalo sin envolver versión del JSON ...

{ "name": "Simón", "puntuación": "100", "Club": "Rigby"}

pero en el servicio el parámetro es nulo y no hay excepciones de formateador.

Ésta es la rama de la system.serviceModel web.config del servicio:

<system.serviceModel> 
<services> 
    <service name="WCFService.WCFService" behaviorConfiguration="WCFService.DefaultBehavior"> 
     <endpoint address="json" binding="webHttpBinding" contract="WCFService.IWCFService" behaviorConfiguration="jsonBehavior"/> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
    </service> 
</services> 

<behaviors> 
    <serviceBehaviors> 
     <behavior name="WCFService.DefaultBehavior"> 
      <serviceMetadata httpGetEnabled="true"/> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
     </behavior> 
    </serviceBehaviors> 

    <endpointBehaviors> 
     <behavior name="jsonBehavior"> 
      <webHttp/> 
     </behavior>    
    </endpointBehaviors> 
</behaviors> 

Y aquí es el DataContract jugador.

[DataContract(Name = "Player")] 
    public class Player 
    { 
     private string _name; 
     private int _score; 
     private Club _club; 

     [DataMember] 
     public string Name { get { return _name; } set { _name = value; } } 

     [DataMember] 
     public int Score { get { return _score; } set { _score = value; } } 

     [DataMember] 
     public Club Club { get { return _club; } set { _club = value; } } 

    } 

Cualquier ayuda muy apreciada y si se requiere alguna otra información, por favor hágamelo saber.

Muchas gracias.

Respuesta

10

Codifica el parámetro de entrada player del método TotalScore de la manera incorrecta.

Te recomiendo que uses la función JSON.stringify desde json2.js para convertir cualquier objeto de JavaScript a JSON.

var myPlayer = { 
    Name: "Simon", 
    Score: 1000, 
    Club: { 
     Name: "Tigers", 
     Town: "Glenelg" 
    } 
}; 
$.ajax({ 
    type: "POST", 
    url: "/wcfservice/wcfservice.svc/json/TotalScore", 
    data: JSON.stringify({player:myPlayer}), // for BodyStyle equal to 
              // WebMessageBodyStyle.Wrapped or 
              // WebMessageBodyStyle.WrappedRequest 
    // data: JSON.stringify(myPlayer), // for no BodyStyle attribute 
             // or WebMessageBodyStyle.WrappedResponse 
    contentType: "application/json; charset=utf-8", 
    dataType: "json", 
    success: function(data, textStatus, xhr) { 
     alert(data.TotalScoreResult); // for BodyStyle = WebMessageBodyStyle.Wrapped 
             // or WebMessageBodyStyle.WrappedResponse 
     // alert(data); // for BodyStyle = WebMessageBodyStyle.WrappedRequest 
         // or for no BodyStyle attributes 
    }, 
    error: function (xhr, textStatus, ex) { 
     alert("Not Done"); 
    } 
}); 

Si cambia el atributo del método BodyStyle = WebMessageBodyStyle.WrappedTotalScore-BodyStyle = WebMessageBodyStyle.WrappedRequest puede cambiar el alert(data.TotalScoreResult) en el mango success-alert(data).

+1

Muchas gracias ... ese fue el problema. Al mirar el JSON en el violín, veo que el valor int no está citado. Tenía la impresión de que deberían estarlo. Muchas gracias. –

+0

@Simon Rigby: Sí, fue uno de los errores. La propiedad 'Club' que serializaste también en el estilo" Forma ", que también es incorrecta. Modifiqué mi respuesta adicionalmente para mostrar el significado del atributo 'BodyStyle'. Espero que también te ayude. – Oleg

+0

Muchas gracias. ¿Cómo funciona stringify ir con las fechas. Mi servicio WCF se está tropezando con ellos ya que no tiene el envoltorio/date() a su alrededor. Es algo que necesitaría abordar por separado. No estoy seguro de cómo me conectaría con eso ya que el objeto apareció en una sola llamada. Espero que eso haga sene. –

Cuestiones relacionadas