Después de de nuestra prolongada compilación de información dimos con la respuesta este atasco que suelen tener ciertos lectores. Te regalamos la respuesta y nuestro objetivo es resultarte de gran apoyo.
Solución:
Use BsonDocument cuando guarde en MongoDB
Después de probar varias configuraciones diferentes, la única forma en que pude guardar correctamente documentos verdaderamente dinámicos usando el conector fue analizar objetos como BsonDocument
s.
public ActionResult Post([FromBody]JObject resource)
var document = BsonDocument.Parse(resource.ToString(Formatting.None));
DbContext.Resources.InsertOne(document);
Registrarse BsonDocument
serializadores con JSON.Net
Inicialmente, el problema con el enfoque anterior era que al llamar ToJson()
los ISODate
y ObjectId
los objetos se serializarían en objetos, lo que no era deseable. Al momento de escribir, no parece haber ningún punto de extensibilidad para anular este comportamiento. La lógica está integrada en el MongoDB.Bson.IO.JsonWriter
clase, y no puede registrarse BsonSerializer
es para BsonValue
tipos:
MongoDB.Bson.BsonSerializationException: no se puede registrar un serializador para el tipo BsonObjectId porque es una subclase de BsonValue.
En el momento de escribir este artículo, la única solución que he encontrado es personalizar explícitamente los convertidores JSON.Net. El líder de C# de MongoDB, Robert Stam, ha creado una biblioteca no publicada para esto que el miembro de la comunidad Nathan Robinson ha portado a .net-core. He creado una bifurcación que serializa correctamente los campos ObjectId e ISODate.
Creé un paquete NuGet a partir de su trabajo. Para usarlo, incluya la siguiente referencia en su .csproj
expediente:
Luego, registre explícitamente los convertidores:
Inicio.cs
using MongoDB.Integrations.JsonDotNet.Converters;
public class Startup
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
services.AddMvc().AddJsonOptions(options =>
// Adds automatic json parsing to BsonDocuments.
options.SerializerSettings.Converters.Add(new BsonArrayConverter());
options.SerializerSettings.Converters.Add(new BsonMinKeyConverter());
options.SerializerSettings.Converters.Add(new BsonBinaryDataConverter());
options.SerializerSettings.Converters.Add(new BsonNullConverter());
options.SerializerSettings.Converters.Add(new BsonBooleanConverter());
options.SerializerSettings.Converters.Add(new BsonObjectIdConverter());
options.SerializerSettings.Converters.Add(new BsonDateTimeConverter());
options.SerializerSettings.Converters.Add(new BsonRegularExpressionConverter());
options.SerializerSettings.Converters.Add(new BsonDocumentConverter());
options.SerializerSettings.Converters.Add(new BsonStringConverter());
options.SerializerSettings.Converters.Add(new BsonDoubleConverter());
options.SerializerSettings.Converters.Add(new BsonSymbolConverter());
options.SerializerSettings.Converters.Add(new BsonInt32Converter());
options.SerializerSettings.Converters.Add(new BsonTimestampConverter());
options.SerializerSettings.Converters.Add(new BsonInt64Converter());
options.SerializerSettings.Converters.Add(new BsonUndefinedConverter());
options.SerializerSettings.Converters.Add(new BsonJavaScriptConverter());
options.SerializerSettings.Converters.Add(new BsonValueConverter());
options.SerializerSettings.Converters.Add(new BsonJavaScriptWithScopeConverter());
options.SerializerSettings.Converters.Add(new BsonMaxKeyConverter());
options.SerializerSettings.Converters.Add(new ObjectIdConverter());
);
Ahora, puede serializar utilizando el serializador predeterminado:
return Created($"resource/document["_id"].ToString()", document);
Puede hacer que su último intento funcione registrando personalizado ObjectIdConverter
con Newton Soft.
await resources = _database.GetCollection("resources")
.Find(Builders.Filter.Empty)
.ToListAsync();
return Ok(Newtonsoft.Json.JsonConvert.SerializeObject(resources, new ObjectIdConverter()));
Convertidor:
class ObjectIdConverter : JsonConverter
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
serializer.Serialize(writer, value.ToString());
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
throw new NotImplementedException();
public override bool CanConvert(Type objectType)
return typeof(ObjectId).IsAssignableFrom(objectType);
Nota: El convertidor anterior convierte de ObjectId
a la cadena después de la BSONSerailzers
han convertido el valor bson a ObjectId
.
Todavía necesitará usar parse para convertir string id a ObjectIds para consultas y registrar el ObjectIdConverter globalmente.
Referencia: https://stackoverflow.com/a/16693462/2683814
Si te ha resultado útil nuestro post, sería de mucha ayuda si lo compartes con otros juniors de este modo contrubuyes a extender este contenido.