Проблема десериализации ASP.NET ScriptService с производными типами - PullRequest
7 голосов
/ 29 сентября 2010

У меня есть ScriptService веб-метод (.NET 3.5), который принимает один параметр абстрактного базового типа:

[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;
}
}

Обычно, когдаметод вызывается, item будет Group, который содержит Instance и / или Group объекты.Я звоню в этот сервис из jQuery;Я не использую клиентскую среду Microsoft.Вызовы других методов работают нормально.

Проблема: Когда я выполняю вызов, перед вызовом моего метода выдается исключение.Например, если мой вызов:

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"}

Если я уроню элемент __type объекта JSON или изменимдля Namespace.Item (и удаления модификатора abstract из Item), исключение исчезает, но полученный десериализованный объект, очевидно, является бесполезным.

Чего мне не хватает?

Ответы [ 2 ]

15 голосов
/ 29 сентября 2010

Ах, ха!Нажав на соответствующие ссылки в правой части этого вопроса, я нашел ответ , который помог мне решить эту проблему.

Атрибут GenerateScriptType должен быть применен к классу веб-службы:

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

Без этих атрибутов десериализатор не знает о моих производных типах.

0 голосов
/ 23 ноября 2018

Я мог бы решить эту проблему, используя Newtonsofts JsonConvert, как показано ниже.

[System.Web.Services.WebMethod]      
public static void MyAjaxCallingMethod(object inputs)
    {           
    string stingDataFromAjaxCall = JsonConvert.SerializeObject(inputs);
            MyObject myObj = JsonConvert.DeserializeObject<MyObject>(stingDataFromAjaxCall);
            ....}
...