.net 使用 DataContractSerializer 的“非预期类型” - 但它只是一个简单的类,没有有趣的东西?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8794594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 16:10:32  来源:igfitidea点击:

"Type not expected", using DataContractSerializer - but it's just a simple class, no funny stuff?

.netxmlserializationxml-serializationdatacontractserializer

提问by Julian

I'm refactoring my XML-serialization, and figured I'd try the DataContractSerializer. Everything runs smoothly, until it needs to serialize this class:

我正在重构我的 XML 序列化,并认为我会尝试 DataContractSerializer。一切运行顺利,直到它需要序列化这个类:

using System;
using System.Runtime.Serialization;

namespace VDB_Sync.Model
{
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
{
    [DataMember]
    private MySqlDbType mydataType;
    [DataMember]
    private object value;

    public Konstant(string navn, MySqlDbType dataType, object value)
        : base(navn, dataType, "*Konstant", false, false)
    {
        //this.navn = navn;
        this.mydataType = dataType;
        this.value = value;

        if (navn.Contains("*L?benummer"))
        {
            navn = "*Konstant: " + Convert.ToString(value);
        }
    }

    public object Value
    {
        get
        {
            return value;
        }
    }

}
}

It give's me this:

它给了我这个:

Type 'VDB_Sync.Model.Konstant' with data contract name 'Konstant:http://schemas.datacontract.org/2004/07/VDB_Sync.Model' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

不应使用数据合同名称“Konstant:http://schemas.datacontract.org/2004/07/VDB_Sync.Model”键入“VDB_Sync.Model.Konstant”。考虑使用 DataContractResolver 或将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用 KnownTypeAttribute 属性或将它们添加到传递给 DataContractSerializer 的已知类型列表中。

*The help I've found so far points to collections and Types. I do have an enum (MySqlDbType) in my class - but get this: I even get the same error when i have no DataMembers declared at all :-x So - what's going on here? What am I missing?

*到目前为止我发现的帮助指向集合和类型。我的班级中有一个 enum (MySqlDbType) - 但是得到这个:当我根本没有声明 DataMembers 时,我什至得到同样的错误:-x 那么 - 这里发生了什么?我错过了什么?

for reference, this is how i serialized it, VDB_SessionController being the root:*

作为参考,这是我序列化它的方式,VDB_SessionController 是根:*

    public void GemKonfig(VDB_SessionController session)
    {
        var settings = new XmlWriterSettings()
        {
            Indent = true,
            IndentChars = "\t"
        };

        var writer = XmlWriter.Create(defaultFile, settings);
        DataContractSerializer ser =
            new DataContractSerializer(typeof(VDB_SessionController));

        ser.WriteObject(writer, session);
        writer.Close();
    }

回答by competent_tech

The exception that is being reported is for VDB_Sync.Model.Konstant. This means that somewhere further up the chain, this class is being pulled into another class and that class is the one being serialized.

正在报告的例外是 VDB_Sync.Model.Konstant。这意味着在链上的某个地方,这个类被拉入另一个类,而那个类是被序列化的类。

The issue is that depending on how Konstant is embedded in this class (for example, if it is in a collection or a generic list), the DataContractSerializer may not be prepared for its appearance during deserialization.

问题在于,根据 Konstant 在此类中的嵌入方式(例如,如果它位于集合或通用列表中),DataContractSerializer 在反序列化期间可能未准备好出现。

To resolve this, you need to apply the known-type attribute to the class that contains Konstant. Based on your serialization code, I suspect that this is VDB_SessionController.

要解决此问题,您需要将 known-type 属性应用于包含 Konstant 的类。根据您的序列化代码,我怀疑这是VDB_SessionController.

So, try decorating this class with the KnownType attribute:

因此,尝试使用KnownType 属性装饰这个类:

[KnownType(typeof(VDB_Sync.Model.Konstant)]
public class VDB_SessionController

回答by fenix2222

Add this to WebApiConfig.cs

将此添加到 WebApiConfig.cs

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

var json = config.Formatters.JsonFormatter;

json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

Reference: http://www.datazx.cn/Forums/en-US/a5adf07b-e622-4a12-872d-40c753417645/action?threadDisplayName=web-api-error-the-objectcontent1-type-failed-to-serialize-the-response-body-for-content&forum=wcf

参考:http: //www.datazx.cn/Forums/en-US/a5adf07b-e622-4a12-872d-40c753417645/action?threadDisplayName= web-api-error-the-objectcontent1-type-failed-to-serialize- the-response-body-for-content&forum=wcf

回答by dcastro

You can also combine [KnownType]and reflection to make your code more resistant to future changes.

您还可以结合[KnownType]和反射使您的代码更能抵抗未来的变化。

[DataContract]
[KnownType("GetKnownPersonTypes")]
internal class Person
{
    private static IEnumerable<Type> _personTypes;

    private static IEnumerable<Type> GetKnownTypes()
    {
        if (_personTypes == null)
            _personTypes = Assembly.GetExecutingAssembly()
                                    .GetTypes()
                                    .Where(t => typeof (Person).IsAssignableFrom(t))
                                    .ToList();
        return _personTypes;
    }
}

Now a DataContractSerializer/ DataContractJsonSerializer/ XmlSerializerconfigured to work with Person, will also work with anytype derived from Person(as long as it's declared within the same assembly).

现在DataContractSerializer/ DataContractJsonSerializer/XmlSerializer配置工作与Person,也将与工作的任何衍生类型Person(只要它是在同一组件内声明的)。

回答by gethomast

回答by fluidguid

The problem for me was that I was returning the Interface (IIndividual) from my WebAPI controller. When I changed that return type to the Class (Individual) type, this error went away.

我的问题是我从我的 WebAPI 控制器返回接口(IIndividual)。当我将该返回类型更改为 Class (Individual) 类型时,此错误消失了。

Not working:

不工作:

    [HttpGet]
    [Route("api/v1/Individual/Get/{id}")]
    public IIndividual Get([FromUri]int id)
    {
        return _individualService.Get(id);
    }

Working:

在职的:

    [HttpGet]
    [Route("api/v1/Individual/Get/{id}")]
    public Individual Get([FromUri]int id)
    {
        IIndividual individual = _individualService.Get(id);
        return individual as Individual;
    }

回答by Sohayb Hassoun

It is like as @Leon suggested but with the fix from @Bryan, the 'KnownTypeAttribute' should be on the base class, so it should be like this:

就像@Leon 建议的那样,但是通过@Bryan 的修复,'KnownTypeAttribute' 应该在基类上,所以它应该是这样的:

[DataContract(Name="DataFelt")]
[KnownType(typeof(somenamespace.Konstant))]
public class DataFelt

and in the Subclass:

在子类中:

[DataContract(Name="Konstant")]
public class Konstant : DataFelt

回答by Leon

Change this:

改变这个:

[DataContract(Name="Konstant")]
public class Konstant : DataFelt

to this:

对此:

[DataContract(Name="Konstant")]
[KnownTypes(typeof(somenamespace.DataFelt))]
public class Konstant : DataFelt