Sto tentando di creare una funzione generica che quando viene fornito un tipo Enum restituirà un oggetto che, una volta serializzato da WebApi, fornirà un output di aspetto gradevole come XML/Json.Serializzare un tipo dinamico nell'API Web
Questo metodo funziona perfettamente quando serializzato come JSON, ma non riesco a farlo funzionare con XML. Se serializzo manualmente l'oggetto restituito con un XmlSerializer o DataContractSerializer, ottengo i risultati come previsto. Quando WebAPI si tenta di serializzare esso d'altra parte da un HttpRequest, ricevo errori come il seguente:
System.Runtime.Serialization.SerializationException
Tipo 'priorità' con il nome del contratto di dati 'prioritario : http: //schemas.datacontract.org/2004/07/ 'non è previsto. Considerare l'utilizzo di DataContractResolver o aggiungere staticamente i tipi non noti all'elenco dei tipi noti, ad esempio utilizzando l'attributo KnownTypeAttribute o aggiungendoli all'elenco dei tipi noti passati a DataContractSerializer.
Ho provato con GlobalConfiguration.Configuration.Formatters.XmlFormatter.SetSerializer per impostare il serializzatore per il tipo generato che conosco opere provenienti da punti di interruzione di impostazione, ma sembra solo di ignorarlo e getta la stessa eccezione. L'enumerazione sarà supportata da numeri interi e sarà garantito un valore univoco per ogni voce. Ecco il codice che sto usando per generare il tipo e restituirne un'istanza.
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 Metodo di controllo:
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));
}
Tutte le idee?
È possibile includere un metodo API Web che riproduce questo errore quando si restituisce XML? Penso di sapere qual è il problema, ma ho bisogno di vedere come stai cercando di restituire questo enum come contenuto. –
@AndrasZoltan Ho modificato la mia domanda originale con un metodo API Web di esempio – dherman
come sospetto, passando l'oggetto nel contenuto come un 'oggetto'. Posso vedere dall'accettazione che la soluzione che ho suggerito funzionava :) –