ASP.NET ScriptService反序列化的问题,派生类型类型、序列化、问题、ASP

2023-09-10 16:43:28 作者:半句话半首蝶恋花

我有一个 ScriptService Web方法(.NET 3.5),它接受一个抽象基类的单个参数:

I have a ScriptService web method (.NET 3.5) which takes a single parameter of an abstract base type:

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

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

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

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

通常,当调用该方法,项目将成为集团包含实例和/或集团的对象。我打电话从jQuery的这种服务;我没有使用微软客户端框架。调用其他方法的正常工作。

Usually, when the method is called, item will be a Group which contains Instance and/or Group objects. I'm calling this service from jQuery; I'm not using the Microsoft client-side framework. Calls to other methods work fine.

的问题::当我打这个电话,一个异常被抛出之前,我的方法是,即使调用。例如,如果我的电话是:

The problem: When I make the call, an exception is thrown before my method is even invoked. For example, if my call is:

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":[]}}

...我得到一个 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"}

如果我把JSON对象的 __类型成员或将其更改为 Namespace.Item (和删除摘要项目),异常消失,改性剂而产生的反序列化对象显然有点没用。

If I drop the __type member of the JSON object or change it to Namespace.Item (and remove the abstract modifier from Item), the exception goes away, but the resulting deserialized object is obviously kinda useless.

我在想什么?

推荐答案

啊哈!点击周围右边这个问题的相关链接,我发现an回答,帮助我解决这个问题。

Ah ha! Clicking around the related links on the right side of this question, I found an answer that helped me solve this problem.

GenerateScriptType 属性必须被应用到Web服务类:

The GenerateScriptType attribute must be applied to the web service class:

[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) { ... }
}

如果没有这些属性,解串器不知道我的派生类型。

Without these attributes, the deserializer doesn't know about my derived types.