2010-09-29 13 views
6

I tienen un método ScriptService web (.NET 3.5), que tiene un solo parámetro de un resumen tipo base:problema deserialización ASP.NET ScriptService con tipos derivados

[WebMethod(EnableSession=true)] 
[ScriptMethod()] 
public bool Test(Item item) { ... } 

Y:

namespace Namespace { 
public abstract class Item 
{ 
    public int id; 
} 

public class Group : Item 
{ 
    public Item[] items; 
} 

public class Instance : Item 
{ 
    public string whatever; 
} 
} 

Por lo general, cuando se llama al método, item será un Group que contiene Instance y/o Group objetos. Estoy llamando a este servicio desde jQuery; No estoy usando el marco del lado del cliente de Microsoft. Las llamadas a otros métodos funcionan bien.

Problema: Cuando realizo la llamada, se lanza una excepción incluso antes de invocar mi método. Por ejemplo, si mi llamada es:

POST /WebService.asmx/Test HTTP/1.1 
Content-Type: application/json; charset=UTF-8 
Accept: application/json, text/javascript, */* 

{"item":{"id":0,"__type":"Namespace.Group","items":[]}} 

... me sale un InvalidOperationException:

{"Message":"Operation is not valid due to the current state of the object.","StackTrace":" at System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary`2 dictionary, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"} 

Si me cae el __type miembro del objeto JSON o cambiarlo a Namespace.Item (y eliminar la abstract modificador desde Item), la excepción desaparece, pero el objeto deserializado resultante es obviamente inútil.

¿Qué me estoy perdiendo?

+0

Me salió un error así, pero mi problema era completamente diferente. Convertí un servicio WCF en un servicio ASMX. Cada uno usa un formato diferente para la propiedad '__type'. La actualización de '__type' para usar el formato ASMX resolvió completamente el problema para mí. – sparebytes

Respuesta

14

¡Ah, ja! Al hacer clic en los enlaces relacionados en el lado derecho de esta pregunta, encontré an answer que me ayudó a resolver este problema.

El atributo GenerateScriptType se debe aplicar a la clase de servicio web:

[WebService(...)] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[ScriptService] 
[GenerateScriptType(typeof(Group))] 
[GenerateScriptType(typeof(Instance))] 
public class WebService : System.Web.Services.WebService 
{ 
    [WebMethod(EnableSession=true)] 
    [ScriptMethod()] 
    public bool Test(Item item) { ... } 
} 

Sin estos atributos, el deserializer no sabe nada de mis tipos derivados.

Cuestiones relacionadas