Saltar al contenido

Controlador Mongo C# y formato de cadena ObjectID JSON en .NET Core

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 BsonDocuments.

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 BsonSerializeres 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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *