-
-
Save lurumad/410e05154cc7e9f2f3eb to your computer and use it in GitHub Desktop.
public class TempDataDocument | |
{ | |
[BsonRepresentation(BsonType.ObjectId)] | |
public string Id { get; set; } | |
[BsonElement("key")] | |
public string Key { get; set; } | |
[BsonElement("value")] | |
[BsonSerializer(typeof(CustomSerializer))] | |
public object Value { get; set; } | |
} | |
public class CustomSerializer : IBsonSerializer | |
{ | |
#region Implementation of IBsonSerializer | |
public object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) | |
{ | |
return Deserialize(bsonReader, nominalType, null, options); | |
} | |
public object Deserialize( | |
MongoDB.Bson.IO.BsonReader bsonReader, | |
Type nominalType, | |
Type actualType, | |
IBsonSerializationOptions options) | |
{ | |
if (bsonReader.GetCurrentBsonType() != BsonType.Document) | |
{ | |
throw new Exception("Not document"); | |
} | |
var bsonDocument = BsonSerializer.Deserialize(bsonReader, typeof(BsonDocument), options) as BsonDocument; | |
var cleanJson = Regex.Replace(bsonDocument.ToJson(), @"ObjectId\((.[a-f0-9]{24}.)\)", (m) => m.Groups[1].Value); | |
return JsonConvert.DeserializeObject<object>(cleanJson); | |
} | |
public IBsonSerializationOptions GetDefaultSerializationOptions() | |
{ | |
return new DocumentSerializationOptions(); | |
} | |
public void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) | |
{ | |
var json = (value == null) ? "{}": JsonConvert.SerializeObject(value); | |
BsonDocument document = BsonDocument.Parse(json); | |
BsonSerializer.Serialize(bsonWriter, typeof(BsonDocument), document,options); | |
} | |
#endregion | |
} | |
void Main() | |
{ | |
var client = new MongoClient("mongodb://localhost:27017"); | |
var server = client.GetServer(); | |
var database = server.GetDatabase("mvc"); | |
var collection = database.GetCollection("tempdata"); | |
var document = new TempDataDocument() | |
{ | |
Key = "key1", | |
Value = new | |
{ | |
Nombre = "Sergio", | |
Twitter = "@panicoenlaxbox" | |
} | |
}; | |
collection.Insert(document); | |
var data = collection.FindAs<TempDataDocument>(Query.EQ("key", "key1")); | |
Console.WriteLine(data); | |
} |
Lo he actualizado ;)
Gran trabajo, probado y funcionando!!
De todas formas, tengo alguna duda (seguro fruto de mi inexperiencia con MongoDB) He visto en http://docs.mongodb.org/ecosystem/tutorial/serialize-documents-with-the-csharp-driver/#write-a-custom-serializer que supuestamente lo único que hay que hacer es implementar IBsonSerializer, a excepción de este párrafo que podemos obviarlo porque no nos gusta LINQ sobre MongoDB :) "However, there are some extension interfaces that will enable further use in other parts of the api such as saving a class or LINQ"
Para mí algo falla porque no es verdad que sólo haya que hacer eso, por ejemplo con tu código todo funciona a la primera, pero fíjate en que no se está grabando el campo _id en la base de datos. De esta forma, si ejecutas el código una segunda vez te lanza el siguiente error "An unhandled exception of type 'MongoDB.Driver.MongoDuplicateKeyException' occurred in MongoDB.Driver.dll" y yo me pregunto: Si sólo estás decorando la propiedad Value (no la clase entera) ¿Por qué no se graba el _id?
Luego investigaré más en casa, gracias por preocuparte por esto, actualizaré el post seguro luego con todo lo que saquemos, de hecho yo lo estoy utilizando en producción así que estoy muy interesado :)
Yo si que tengo el Id:
/* 0 */
{
"_id" : ObjectId("537b23be3814fe25e8119e01"),
"key" : "key1",
"value" : {
"Nombre" : "Sergio",
"Twitter" : "@panicoenlaxbox"
}
}
/* 1 */
{
"_id" : ObjectId("537b4e733814fe181cd96417"),
"key" : "key1",
"value" : {
"Nombre" : "Sergio",
"Twitter" : "@panicoenlaxbox"
}
}
/* 2 */
{
"_id" : ObjectId("537b4e753814fe181cd96418"),
"key" : "key1",
"value" : {
"Nombre" : "Sergio",
"Twitter" : "@panicoenlaxbox"
}
}
Y no me salta ninguna excepción :(
Pues llevas razón, error mío, luego actualizo el post con una super-mención para un tal lurumad :)
Gracias
Hola Luis,
Que conste que soy un completo beginner con MongoDB, pero creo que el problema está cuando intentas deserializar sin un tipo destino, luego debería deserializar a un tipo anónimo, pero parece que no está soportado. En tu caso, no hay problema, porque lo que está guardado e intentas deserializar encaja perfectamente en el tipo destino. De hecho, el problema no está en guardar (MongoDB parece tragarse todo), el problema está al deserializar.
He creado este otro gist para que veas el error "in situ" https://gist.github.com/panicoenlaxbox/5c6784e2be1171eed003
En el caso del proveedor de TempData fíjate que yo puedo guardar cualquier cosa y podría no tener siempre un tipo destino válido para deserializar. Es por ello que intento atajar el problema antes de que ocurra, por eso no dejo guardar tipos anónimos (que insisto no habría problema, el problema sería después al intentar deserializarlos).
En el caso de la implementación de TempData basada en cookies no hay ningún problema porque serializa/deserializa Json.NET que sí sabe trabajar con tipos anónimos.