ProtoContract 打破了 XmlMediaTypeFormatter 的行为
ProtoContract breaks XmlMediaTypeFormatter behavior
我有一个 ASP.NET 网络应用程序需要以 JSON、XML 和 ProtoBuf 的形式接收请求。为了让 ProtoBuf 工作,我需要用 [ProtoContract] 注释 DTO,但是一旦我这样做,XML 就会停止工作。
我可以将问题归结为 [ProtoContract]。我做了这个小测试应用程序:
class Program
{
static void Main(string[] args)
{
var ser = new XmlMediaTypeFormatter();
ser.UseXmlSerializer = true;
Console.WriteLine($"With ProtoContract: {ser.CanReadType(typeof(Foo))}");
Console.WriteLine($"Without ProtoContract: {ser.CanReadType(typeof(Foo1))}");
}
}
[ProtoContract]
public class Foo
{
[ProtoMember(0)]
public string Bar { get; set; }
}
public class Foo1
{
public string Bar1 { get; set; }
}
输出为:
With ProtoContract: False
Without ProtoContract: True
观察很清楚,一旦添加了属性,XmlSerializer 就无法再读取对象。有人经历过类似的行为吗?关于如何解决这个问题的任何想法?
这很有趣 - 我不知道它是怎么做到的,但今晚我会在反射器中查看!
但是,在这种情况下修复很简单:
[ProtoMember(1)]
public string Bar { get; set; }
奇怪的是,我知道要检查这个的原因是 0
在 protobuf 中从来不是合法的标签,但我很感兴趣 XmlMediaTypeFormatter
会 care.
更新:原因是因为XmlSerializer
如何访问对象上的属性,但是吞下异常意味着"nope, can't do that"。它成为您实际问题的牺牲品;尝试:
new XmlSerializer(typeof(Foo));
你应该看到:
Unhandled Exception: System.InvalidOperationException: There was an error reflecting type 'Foo'. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: tag
at ProtoBuf.ProtoMemberAttribute..ctor(Int32 tag) in c:\Dev\protobuf-net\protobuf-net\ProtoMemberAttribute.cs:line 47
at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
at System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
等等,这只是ProtoMembmerAttribute
抱怨非法标签。
我有一个 ASP.NET 网络应用程序需要以 JSON、XML 和 ProtoBuf 的形式接收请求。为了让 ProtoBuf 工作,我需要用 [ProtoContract] 注释 DTO,但是一旦我这样做,XML 就会停止工作。
我可以将问题归结为 [ProtoContract]。我做了这个小测试应用程序:
class Program
{
static void Main(string[] args)
{
var ser = new XmlMediaTypeFormatter();
ser.UseXmlSerializer = true;
Console.WriteLine($"With ProtoContract: {ser.CanReadType(typeof(Foo))}");
Console.WriteLine($"Without ProtoContract: {ser.CanReadType(typeof(Foo1))}");
}
}
[ProtoContract]
public class Foo
{
[ProtoMember(0)]
public string Bar { get; set; }
}
public class Foo1
{
public string Bar1 { get; set; }
}
输出为:
With ProtoContract: False
Without ProtoContract: True
观察很清楚,一旦添加了属性,XmlSerializer 就无法再读取对象。有人经历过类似的行为吗?关于如何解决这个问题的任何想法?
这很有趣 - 我不知道它是怎么做到的,但今晚我会在反射器中查看!
但是,在这种情况下修复很简单:
[ProtoMember(1)]
public string Bar { get; set; }
奇怪的是,我知道要检查这个的原因是 0
在 protobuf 中从来不是合法的标签,但我很感兴趣 XmlMediaTypeFormatter
会 care.
更新:原因是因为XmlSerializer
如何访问对象上的属性,但是吞下异常意味着"nope, can't do that"。它成为您实际问题的牺牲品;尝试:
new XmlSerializer(typeof(Foo));
你应该看到:
Unhandled Exception: System.InvalidOperationException: There was an error reflecting type 'Foo'. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: tag
at ProtoBuf.ProtoMemberAttribute..ctor(Int32 tag) in c:\Dev\protobuf-net\protobuf-net\ProtoMemberAttribute.cs:line 47
at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
at System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
等等,这只是ProtoMembmerAttribute
抱怨非法标签。