Welche Optionen gibt es für die Serialisierung, wenn Instanzen von benutzerdefinierten Klassen von einem WebService zurückgegeben werden?Wie kann die benutzerdefinierte JSON-Serialisierung vom ASP.NET-Webdienst implementiert werden?
Wir haben einige Klassen mit einer Reihe von untergeordneten Auflistungsklasseneigenschaften sowie anderen Eigenschaften, die abhängig von der Verwendung festgelegt werden können oder nicht. Diese Objekte werden von einem ASP.NET .asmx WebService zurückgegeben, der mit dem ScriptService-Attribut versehen ist. Sie werden also über die JSON-Serialisierung serialisiert, wenn sie von den verschiedenen WebMethods zurückgegeben werden.
Das Problem ist, dass die Out-of-the-Box-Serialisierung alle öffentlichen Eigenschaften zurückgibt, unabhängig davon, ob sie verwendet werden oder nicht, und Klassenname und andere Informationen in einer ausführlicheren Weise zurückgeben, als gewünscht wäre Beschränken Sie die Menge des Verkehrs.
Derzeit für die Klassen zurückgegeben werden wir benutzerdefinierte Javascript-Wandler hinzugefügt, die die JSON serializtion handhaben, und fügte sie wie unten an der web.config:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="CustomClassConverter" type="Namespace.CustomClassConverter" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
Dies erfordert jedoch einen benutzerdefinierten Konverter für jede Klasse . Gibt es eine andere Möglichkeit, die Out of the Box-JSON-Serialisierung zu ändern, entweder durch Erweitern des Service, Erstellen eines benutzerdefinierten Serializers oder dergleichen?
Follow Up
@marxidad:
Wir sind mit dem DataContractJsonSerializer Klasse in anderen Anwendungen, aber ich habe es nicht gelungen, herauszufinden, wie es um diese Dienste anzuwenden. Hier ist ein Beispiel dafür, wie die Dienste Aufstellmaße:
[ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public CustomClass GetCustomClassMethod
{
return new customClass();
}
}
webMethods durch JavaScript aufgerufen werden und gibt Daten in JSON serialisiert. Die einzige Methode, die wir in der Lage waren, die Serialisierung zu ändern, besteht darin, die oben genannten JavaScript-Konverter zu verwenden?
Gibt es eine Möglichkeit, dem WebService mitzuteilen, einen benutzerdefinierten DataContractJsonSerializer zu verwenden? Sei es durch web.config Konfiguration, dekorieren des Dienstes mit Attributen, etc.?
aktualisieren
Nun, wir finden konnten jede mögliche Weise, nicht wie oben die aus der Box JavaScriptSerializer außer für die Erstellung von individuellen JavaScriptConverters zu wechseln.
Was wir an diesem Ende getan haben, um zu verhindern, dass wir einen separaten Konverter erstellen mussten, war ein generischer JavaScriptConverter. Wir haben eine leere Schnittstelle zu den Klassen, die wir behandelt wollten und die SupportedTypes, die auf Web-Service-Start-up genannt wird verwendet Reflektion alle Typen zu finden, die die Schnittstelle der Art wie diese umzusetzen:
public override IEnumerable<Type> SupportedTypes
{
get
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
AssemblyBuilder dynamicAssemblyCheck = assembly as AssemblyBuilder;
if (dynamicAssemblyCheck == null)
{
foreach (Type type in assembly.GetExportedTypes())
{
if (typeof(ICustomClass).IsAssignableFrom(type))
{
yield return type;
}
}
}
}
}
}
Die eigentliche Implementierung ist ein bisschen anders, so dass der Typ zwischengespeichert wird, und wir werden es wahrscheinlich umgestalten, um benutzerdefinierte Attribute anstelle einer leeren Schnittstelle zu verwenden.
Allerdings traten wir mit einem etwas anderen Problem beim Umgang mit benutzerdefinierten Sammlungen. Diese erweitern normalerweise nur eine generische Liste, aber die benutzerdefinierten Klassen werden anstelle der Liste <> selbst verwendet, da es in den Auflistungsklassen im Allgemeinen benutzerdefinierte Logik, Sortierung usw. gibt.
Das Problem ist, dass die Serialize-Methode für einen JavaScriptConverter ein Wörterbuch zurückgibt, das als Name-Wert-Paare mit dem zugeordneten Typ in JSON serialisiert wird, während eine Liste als ein Array zurückgegeben wird. Daher konnten die Sammlungsklassen nicht einfach mit dem Konverter serialisiert werden. Die Lösung hierfür bestand darin, diese Typen nicht einfach in die SupportedTypes des Konverters aufzunehmen und sie als Listen perfekt zu serialisieren.
So funktioniert Serialisierung, aber wenn Sie versuchen, diese Objekte als Parameter für einen Webdienstaufruf übergeben, die Deserialisierung bricht, da sie nicht die Eingabe als eine Liste von Zeichenfolge/Objekt behandelt werden kann Wörterbücher, die nicht in eine Liste der benutzerdefinierten Klasse der Sammlung konvertiert werden können. Der einzige Weg, den wir finden könnten, besteht darin, eine generische Klasse zu erstellen, die eine Liste von String/Objekt-Dictionaries darstellt, die die Liste in die entsprechende benutzerdefinierte Collection-Klasse konvertiert und dann alle Web-Service-Parameter so ändert, dass stattdessen die generische Klasse verwendet wird .
Ich bin sicher, es gibt Tonnen von Problemen und Verstöße gegen "Best Practices" hier, aber es macht den Job für uns erledigt, ohne eine Tonne von benutzerdefinierten Konverter-Klassen zu erstellen.
Der WebService ist mit dem ScriptService-Attribut ausgestattet, so dass JSON standardmäßig zurückgegeben wird, sodass das ScriptMethod-Attribut nicht erforderlich ist. –