首页 > 解决方案 > 使用 DataContractJsonSerializer 序列化时出现 InvalidDataContractException

问题描述

我将以下 Json 存储为动态环境变量:

{
"LogLevel": 3,
"ServiceEndpointId": "11111111-2222-3333-4444-555555555555",
"ServiceEndpointType": 1
}

检索配置时得到的结果如下:

在“QuickWatch”中看到:

快速观看

格式化后看起来像这样:

快速观看格式化

到目前为止,一切都很好。但是当我序列化结果时,出现以下错误:

'System.Runtime.Serialization.InvalidDataContractException: Type 'Common.Logging.LogConfigCurrent' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types.
   at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)
   at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
   at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.get_RootContract()
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalIsStartObject(XmlReaderDelegator reader)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader)
   at Common.Serializer.JsonSerializer.GetObjectsFromJson[T](String json)
   at Common.Logging.LogConfig.InitLoggerConfig(IOrganizationService orgService, ITracingService tracer)'
   at Common.Logging.LoggingConfig..ctor(IOrganizationService orgService, ITracingService tracer)
   at Common.Logging..ctor(IOrganizationService orgService, IServiceEndpointNotificationService serviceEndpointNotificationService, IExecutionContext context, ITracingService traceService)'

我这样序列化:

更新:添加 DataContractAttribute 没有帮助。我删除了例外中的建议,因为几天前它没有问题。

var logSettings = JsonSerializer.GetObjectsFromJson<LogConfigCurrent>(result.Entities[0].GetAttributeValue<string>("value"));

以及来自命名空间“Common.Serializer”的相应方法:

public static T GetObjectsFromJson<T>(string json) where T : class
        {
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                var ser = new DataContractJsonSerializer(typeof(T));
                var rootObject = ser.ReadObject(ms) as T;
                ms.Close();
                return rootObject;
            }
        } 

和类:

using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using System;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel.Dispatcher;
using System.Text.RegularExpressions;
using Common.Serializer;

namespace Common.Logging
{
    public sealed class LogConfigCurrent
    {
        public int LogLevel { get; set; }
        public string ServiceEndpointId { get; set; }
        public int ServiceEndpointType { get; set; }
    }

    public sealed class LoggingConfig
    {
        public TraceLevel LogLevel { get; private set; } = TraceLevel.Info;

        public Guid ServiceEndpointId { get; private set; }

        public ServiceEndpointType EndpointType { get; private set; }

        public LoggingConfig(IOrganizationService orgService, ITracingService tracer)
        {
            try
            {
                InitLoggerConfig(orgService, tracer);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

         private void InitLoggerConfig(IOrganizationService orgService, ITracingService tracer)
        {
            try
            {
                var fetchXml = "<fetch>" +
                                   "<entity name='environmentvariablevalue'>" +
                                    "<attribute name='value'/>" +
                                     "<link-entity name='environmentvariabledefinition' from='environmentvariabledefinitionid' to='environmentvariabledefinitionid' link-type='inner' alias='ah'>" +
                                      "<filter type='and'>" +
                                        "<condition attribute='schemaname' operator='eq' value='configuration' />" +
                                      "</filter>" +
                                     "</link-entity>" +
                                   "</entity>" +
                                  "</fetch>";

                var conversionRequest = new FetchXmlToQueryExpressionRequest
                {
                    FetchXml = fetchXml
                };

                var conversionResponse = (FetchXmlToQueryExpressionResponse)orgService.Execute(conversionRequest);

                var queryExpression = conversionResponse.Query;

                var result = orgService.RetrieveMultiple(queryExpression);

                if (result.Entities.Any())
                {
                    var logSettings = JsonSerializer.GetObjectsFromJson<LogConfigCurrent>(result.Entities[0].GetAttributeValue<string>("value"));
                    EndpointType = (ServiceEndpointType)logSettings.ServiceEndpointType;
                    ServiceEndpointId = new Guid(logSettings.ServiceEndpointId);
                    LogLevel = (TraceLevel)logSettings.LogLevel;
                }
                else
                {
                    EndpointType = ServiceEndpointType.ServiceEndpoint;
                    ServiceEndpointId = Guid.Empty;
                    LogLevel = TraceLevel.Off;
                    tracer.Trace($"No Configuration found! LogLevel was set to {TraceLevel.Off}");
                }
            }
            catch(Exception ex)
            {
                throw new Exception($"Configuration could not be loaded: Error '{ex.ToString()}'");
            }
        }
    }
}

这可能是逃避的一个可能问题,还是我在这里错过了一些重要的事情?任何人都可以给我一个提示吗?

标签: c#serializationmicrosoft-dynamicsdatacontractjsonserializer

解决方案


我想分享的更新:

我已经找到了解决这个问题的方法,但我不明白为什么会发生这种情况。

上面提到的JsonSerializer的代码

JsonSerializer.GetObjectsFromJson<....>(....);

序列化/反序列化最初是在我开发的自定义 nuget 中实现的。然后在主项目中引用并使用了这个 nuget。

所以我尝试从 nuget 中删除 Serializer-Class 并直接在项目中添加完全相同的类。之后不再抛出异常,并且数据被反序列化而没有问题。

插件程序集和 nuget 具有相同的 .net 版本。

有没有人知道为什么在 nuget 中包含这样的代码而不是在项目本身中包含这样的代码时会导致这样的问题?

任何提示都非常感谢!


推荐阅读