C# 4.0 作为HttpError的一部分将数组序列化为XML时出现InvalidOperationException
当从包含集合的C# 4.0 作为HttpError的一部分将数组序列化为XML时出现InvalidOperationException,c#-4.0,asp.net-web-api,C# 4.0,Asp.net Web Api,当从包含集合的HttpError创建错误响应时,是否有办法绕过invalidoOperationException 只有当响应序列化为XML时,才会出现这种情况,序列化为JSON效果绝对不错 问题似乎与HttpError将要序列化的数据存储在字典中这一事实有关。如果我添加了一个自定义类的数组(FieldError),那么它就不能正确地将其序列化为XML。但是,当我直接用一个属性序列化一个类时,该属性是FieldError类的数组,该数组确实被正确地序列化为XML 有没有办法让集合也作为HTTP错
HttpError
创建错误响应时,是否有办法绕过invalidoOperationException
只有当响应序列化为XML时,才会出现这种情况,序列化为JSON效果绝对不错
问题似乎与HttpError将要序列化的数据存储在字典中这一事实有关。如果我添加了一个自定义类的数组(FieldError
),那么它就不能正确地将其序列化为XML。但是,当我直接用一个属性序列化一个类时,该属性是FieldError
类的数组,该数组确实被正确地序列化为XML
有没有办法让集合也作为HTTP错误的一部分进行序列化
引发异常时,我得到的完整响应是:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>The 'ObjectContent`1' type failed to serialize the response body for content type 'text/xml; charset=utf-8'.</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace />
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>Xml type 'xdt:untypedAtomic' does not support a conversion from Clr type 'FieldError' to Clr type 'String'.</ExceptionMessage>
<ExceptionType>System.InvalidCastException</ExceptionType>
<StackTrace>at System.Xml.Schema.XmlUntypedConverter.ChangeListType(Object value, Type destinationType, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlUntypedConverter.ChangeTypeWildcardDestination(Object value, Type destinationType, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlUntypedConverter.ToString(Object value, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlListConverter.ListAsString(IEnumerable list, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlListConverter.ChangeListType(Object value, Type destinationType, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlUntypedConverter.ChangeListType(Object value, Type destinationType, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlUntypedConverter.ChangeTypeWildcardDestination(Object value, Type destinationType, IXmlNamespaceResolver nsResolver)
at System.Xml.Schema.XmlUntypedConverter.ToString(Object value, IXmlNamespaceResolver nsResolver)
at System.Xml.XmlWriter.WriteValue(Object value)
at System.Web.Http.HttpError.System.Xml.Serialization.IXmlSerializable.WriteXml(XmlWriter writer)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteIXmlSerializable(XmlWriterDelegator xmlWriter, Object obj, XmlSerializableWriter xmlSerializableWriter)
at System.Runtime.Serialization.XmlDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)
at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)
at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()
</StackTrace>
</InnerException>
</Error>
我有一个ExceptionFilterAttribute
,它将API抛出的任何自定义异常转换为HttpError
,并返回错误响应:
public override void OnException(HttpActionExecutedContext context)
{
var apiException = context.Exception as ApiException;
if (apiException != null)
{
context.Response = context.Request.CreateErrorResponse((HttpStatusCode)apiException.ReasonCode, apiException.ToHttpError());
return;
}
base.OnException(context);
}
自定义API异常的基类转换为HttpErrors,如下所示:
internal virtual HttpError ToHttpError()
{
var httpError = new HttpError(this.Message) { { "ExceptionType", this.TypeName } };
var innerApiError = this.InnerException as ApiException;
if (innerApiError != null)
{
httpError.Add("InnerError", innerApiError.ToHttpError());
}
else if (this.InnerException != null)
{
httpError.Add("InnerError", new HttpError(this.InnerException.Message) { { "ExceptionType", this.InnerException.GetType().Name } });
}
return httpError;
}
然后,我有一个派生的异常类,它带有一个数组,该数组重载了到httperror
:
public FieldError[] Errors { get; private set; }
internal override HttpError ToHttpError()
{
var error = base.ToHttpError();
error.Add("Errors", this.Errors);
return error;
}
FieldErrors
属性是一个填充数组,FieldError
类声明为:
[DataContract(Namespace = "")]
public class FieldError
{
[DataMember]
public string Field
{
get;
set;
}
[DataMember]
public string Error
{
get;
set;
}
[IgnoreDataMember]
public ApiErrorTypes ErrorType
{
get;
set;
}
}
当我告诉API返回JSON时,得到的响应是:
{
"Message":"The supplied parameters are invalid.",
"ExceptionType":"InvalidRequestDataException",
"Errors":[
{
"Field":"CollectionDate",
"Error":"Collection date is not in a valid date format"
}
]
}
我发现解决这个问题的唯一方法是创建一个新类,该类使用DataContract
并调用context.Request.CreateResponse()
从中创建响应,而不是使用HttpError
和context.Request.CreateErrorResponse()
{
"Message":"The supplied parameters are invalid.",
"ExceptionType":"InvalidRequestDataException",
"Errors":[
{
"Field":"CollectionDate",
"Error":"Collection date is not in a valid date format"
}
]
}