派生型に関する ASP.NET ScriptService の逆シリアル化の問題
-
26-09-2019 - |
質問
私は持っています ScriptService
Web メソッド (.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
)、例外は消えますが、結果として得られる逆シリアル化されたオブジェクトは明らかに役に立ちません。
私には何が欠けているのでしょうか?
解決
あはは!この質問の右側にある関連リンクをクリックすると、次のことがわかりました。 答え それがこの問題を解決するのに役立ちました。
の GenerateScriptType
属性は 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) { ... }
}
これらの属性がないと、デシリアライザーは派生型を認識できません。
他のヒント
これを使用してこれを解決できます Newtonsofts JsonConvert
以下のように。
[System.Web.Services.WebMethod]
public static void MyAjaxCallingMethod(object inputs)
{
string stingDataFromAjaxCall = JsonConvert.SerializeObject(inputs);
MyObject myObj = JsonConvert.DeserializeObject<MyObject>(stingDataFromAjaxCall);
....}
所属していません StackOverflow