Ich versuche, eine generische Funktion zu erstellen, die bei Angabe eines Enum-Typs ein Objekt zurückgibt, das bei der Serialisierung durch WebApi eine gut aussehende Ausgabe als XML/Json liefert.Serialisierung eines dynamischen Typs in der Web-API
Diese Methode funktioniert einwandfrei, wenn sie als JSON serialisiert wird, aber ich kann nicht mit XML arbeiten. Wenn ich das zurückgegebene Objekt manuell mit einem XmlSerializer oder einem DataContractSerializer serialisiert, erhalte ich die erwarteten Ergebnisse. Wenn WebAPI selbst versucht es auf der anderen Seite von einem Httprequest serialisiert werden, erhalte ich Fehler wie folgt aus:
System.Runtime.Serialization.SerializationException
Typ ‚Priorität‘ mit Datenvertragsnamen ‚Priorität : http: //schemas.datacontract.org/2004/07/ 'wird nicht erwartet. Erwägen Sie, einen DataContractResolver zu verwenden oder alle nicht bekannten Typen statisch zu der Liste der bekannten Typen hinzuzufügen, z. B. indem Sie das KnownTypeAttribute-Attribut verwenden oder sie der Liste bekannter Typen hinzufügen, die an DataContractSerializer übergeben werden.
Ich habe mit GlobalConfiguration.Configuration.Formatters.XmlFormatter.SetSerializer versucht, den Serializer für den erzeugten Typen festgelegt, dass ich Werke von Setzen von Breakpoints wissen, aber es scheint, nur um es zu ignorieren und wirft die gleiche Ausnahme. Die Enums werden durch Ganzzahlen unterstützt und garantieren für jeden Eintrag eindeutige Werte. Hier ist der Code, den ich verwende, um den Typ zu generieren und eine Instanz davon zurückzugeben.
public object GetSerializableEnumProxy(Type enumType) {
if (enumType == null) {
throw new ArgumentNullException("enumType");
}
if (!enumType.IsEnum) {
throw new InvalidOperationException();
}
AssemblyName assemblyName = new AssemblyName("DataBuilderAssembly");
AssemblyBuilder assemBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemBuilder.DefineDynamicModule("DataBuilderModule");
TypeBuilder typeBuilder = moduleBuilder.DefineType(enumType.Name, TypeAttributes.Class | TypeAttributes.Public);
// Add the [DataContract] attribute to our generated type
typeBuilder.SetCustomAttribute(
new CustomAttributeBuilder(typeof(DataContractAttribute).GetConstructor(Type.EmptyTypes), new object[] {})
);
CustomAttributeBuilder dataMemberAttributeBuilder = new CustomAttributeBuilder(
typeof(DataMemberAttribute).GetConstructor(Type.EmptyTypes), new object[] {}
);
// For each name in the enum, define a corresponding public int field
// with the [DataMember] attribute
foreach (var value in Enum.GetValues(enumType).Cast<int>()) {
var name = Enum.GetName(enumType, value);
var fb = typeBuilder.DefineField(name, typeof(int), FieldAttributes.Public);
// Add the [DataMember] attribute to the field
fb.SetCustomAttribute(dataMemberAttributeBuilder);
// Set the value of our field to be the corresponding value from the Enum
fb.SetConstant(value);
}
// Return an instance of our generated type
return Activator.CreateInstance(typeBuilder.CreateType());
}
Web Api-Controller-Methode:
private static IEnumerable<Type> RetrievableEnums = new Type[] {
typeof(Priority), typeof(Status)
};
[GET("enum/{enumName}")]
public HttpResponseMessage GetEnumInformation(string enumName) {
Type enumType = RetrievableEnums.SingleOrDefault(type =>
String.Equals(type.Name, enumName, StringComparison.InvariantCultureIgnoreCase));
if (enumType == null) {
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "The requested enum could not be retrieved");
}
return Request.CreateResponse(HttpStatusCode.OK, GetSerializableEnumProxy(enumType));
}
Irgendwelche Ideen?
Können Sie eine Web-API-Methode einbeziehen, die diesen Fehler bei der Rückgabe von XML reproduziert? Ich denke, ich weiß, was das Problem ist, aber ich muss sehen, wie Sie versuchen, dieses Enum als Inhalt zurückzugeben. –
@AndrasZoltan Bearbeitete meine ursprüngliche Frage mit einer Beispiel-Web-API-Methode – dherman
, wie ich vermutete - Übergabe des Objekts in den Inhalt als ein "Objekt" - ich kann aus der Akzeptanz sehen, dass die vorgeschlagene Lösung funktioniert :) –