【问题标题】:RavenDB: How to prevent $type being saved to a dynamic typed property?RavenDB:如何防止 $type 被保存到动态类型属性?
【发布时间】:2020-08-14 23:16:53
【问题描述】:

当我保存动态类型值时,有没有办法防止添加 $type 属性?

当我保存这个时:

new Activity {
    Name = "FormFieldDeleted",
    Body =  new {
        MyDeletedFormField(),
        MyCompleteForm()
    }
}

我明白了

<>f__AnonymousType1`2[[MyProject.Domains.Forms.Models.FormField, MyProject.Domains.Forms],[MyProject.Domains.Forms.Entities.FormRegistration, MyProject.Domains.Forms]], MyProject.Api.Forms

但是当我尝试获取这个保存的实体时,它会崩溃并出现以下异常。我知道它缺少项目引用,但我真的不想添加该引用(我不想从控制台应用程序引用 API)。我最好只阻止$type 属性。

/usr/local/share/dotnet/dotnet path/MyProject/MyProject/src/MyProject.Tasks.MapActivities/bin/Debug/netcoreapp3.1/MyProject.Tasks.MapActivities.dll
Unhandled exception. System.InvalidOperationException: Could not convert document 31317d58-db9e-4f60-8dee-b8593f3e06c0 to entity of type MyProject.Domains.Core.Entities.Activity
 ---> Newtonsoft.Json.JsonSerializationException: Error resolving type specified in JSON '<>f__AnonymousType1`2[[MyProject.Domains.Forms.Models.FormField, MyProject.Domains.Forms],[MyProject.Domains.Forms.Entities.FormRegistration, MyProject.Domains.Forms]], MyProject.Api.Forms'. Path 'Body.$type'.
 ---> Newtonsoft.Json.JsonSerializationException: Could not load assembly 'MyProject.Api.Forms'
....

【问题讨论】:

    标签: c# dynamic ravendb ravendb4


    【解决方案1】:

    是的,有办法。
    您可以使用以下代码自定义序列化的工作方式:

    store.Conventions.CustomizeJsonSerializer = serializer =>
    {
       serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.None;
    };
    

    例如,看看这里的代码:https://dotnetfiddle.net/voJ7US

    如果你在dotnetfiddle处执行代码,你可以在这里看到结果:http://live-test.ravendb.net/studio/index.html#databases/documents?collection=Activities&database=UniqueTestDB

    【讨论】:

    • 啊太棒了!谢谢你的解决方案。你知道这有什么缺点吗?
    • 据我所知,通常使用“无” - 其他设置是外部接收数据的安全代码气味。见alphabot.com/security/blog/2017/net/…
    • 请注意,RavenDB 4.x $type 在服务器端根本不使用,因为在服务器上,json 使用自定义 json 序列化程序而不是 Newtonsoft.Json 进行反序列化(请参阅github.com/ravendb/ravendb/blob/v4.2/src/Sparrow/Json/… )
    • 感谢您的反馈,不胜感激!
    • 在继承时保存类型很有用,否则 Newtonsoft 将无法自动反序列化您的类型。
    【解决方案2】:

    对于 RavenDB 5 及更高版本,它发生了一些变化。

    var store = DocumentStore
    {
        Urls = new[] { "your-endpoint" },
        Conventions = new DocumentConventions
        {
            Serialization = new NewtonsoftJsonSerializationConventions
            {
                CustomizeJsonSerializer = serializer =>
                {
                    serializer.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.None;
                }
            }
        }
    }.Initialize();
    

    更多信息请参见https://ravendb.net/docs/article-page/5.0/file-header/migration/client-api/conventions

    【讨论】:

    • 这是一个比文档提供的更好的例子:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多