ASP.NET Script Deserialisierung Problem mit abgeleiteten Typen
-
26-09-2019 - |
Frage
Ich habe eine ScriptService
Web-Methode (.NET 3.5), die einen einzelnen Parameter einer abstrakten Basistyp nimmt:
[WebMethod(EnableSession=true)]
[ScriptMethod()]
public bool Test(Item item) { ... }
Und:
namespace Namespace {
public abstract class Item
{
public int id;
}
public class Group : Item
{
public Item[] items;
}
public class Instance : Item
{
public string whatever;
}
}
Normalerweise, wenn die Methode aufgerufen wird, wird item
ein Group
sein, die Instance
und / oder Group
Objekte enthält. Ich rufe diesen Service von jQuery; Ich bin nicht mit dem Microsoft-Client-Seite Rahmen. Anrufe zu anderen Methoden funktionieren.
Das Problem: Wenn ich den Anruf zu tätigen, wird eine Ausnahme ausgelöst, bevor meine Methode auch aufgerufen wird. Zum Beispiel, wenn mein Aufruf:
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":[]}}
... ich eine InvalidOperationException
bekommen:
{"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"}
Wenn ich das __type
Mitglied des JSON-Objekt fallen und vermeiden Sie Namespace.Item
ändern (und entfernen Sie den abstract
Modifikator von Item
), die Ausnahme geht weg, aber die resultierende deserialisiert Objekt ist offensichtlich irgendwie nutzlos.
Was bin ich?
Lösung
Ah ha! Durch Anklicken um die entsprechenden Links auf der rechten Seite dieser Frage fand ich eine Antwort , die mir geholfen, dieses Problem zu lösen.
Das GenerateScriptType
Attribut muss auf die Web-Service-Klasse angewandt werden:
[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) { ... }
}
Ohne diese Attribute, wird der Deserializer nicht über meine abgeleiteten Typen kennen.
Andere Tipps
Ich kann dies mit Newtonsofts JsonConvert
lösen, wie unten.
[System.Web.Services.WebMethod]
public static void MyAjaxCallingMethod(object inputs)
{
string stingDataFromAjaxCall = JsonConvert.SerializeObject(inputs);
MyObject myObj = JsonConvert.DeserializeObject<MyObject>(stingDataFromAjaxCall);
....}