在我们的应用程序中,我们具有一个REST-Api,其中包含多个控制器,例如UsersController
或UserGroupsController
等。每个REST-Endpoint上的所有调用(获取,放置,推送,删除)始终返回HttpResponseMessage
,该对象始终是以下类型的对象:
public class ComRestResult<T> where T : class
{
public T Data { get; set; }
public ValidationItem[] ValidationItems { get; set; }
}
ValidationItem
类看起来像:
[DataContract]
[Serializable]
public class ValidationItem
{
[DataMember]
public string[] ErrorParameters { get; set; }
[DataMember]
public ValidationSeverity Severity { get; set; }
private ValidationId validationId;
[IgnoreDataMember]
[XmlIgnore]
public ValidationId ValidationId
{
get { return validationId; }
set
{
validationId = value;
if(validationId != ValidationId.UnresolvedError)
{
legacyValidationId = validationId.ToString();
}
}
}
private string legacyValidationId;
[DataMember(Name = "ValidationId")]
[XmlElement("ValidationId")]
public string LegacyValidationId
{
get { return legacyValidationId; }
set
{
legacyValidationId = value;
validationId = ValidationId.UnresolvedError;
ValidationId parsedValidationId;
if(!string.IsNullOrEmpty(legacyValidationId) && Enum.TryParse(legacyValidationId, out parsedValidationId))
{
validationId = parsedValidationId;
}
}
ValidationId
和Severity
是枚举。
UsersController的Get-Method例如:
[HttpGet]
[Route("")]
public HttpResponseMessage Get()
{
RequestHandler handler = new RequestHandler(Request);
HttpResponseMessage responseMessage = handler.ProcessRequest<User[]>(PersonsAccess.GetAllPersons);
return responseMessage;
}
RequestHandler构建所需的HttpResponseMessage
,并在其ProcessRequest-Method中使用Func<object, T>
。
HttpResponseMessage
是在ProcessRequest-Method内部用以下行创建的:
HttpResponseMessage httpResponseMessage = request.CreateResponse(httpStatusCode, restResult);
一切都很好。
如果我查看json中的响应,则它看起来像:
{"ValidationItems":[{"ValidationId":"UserIsNew","ErrorParameters":["foo","bar"],"Severity":0,}],"Data":[{"UserId":"ABC123","UserName":"John Smith","IsNew":true},{"UserId":"XYZ789","UserName":"Raimond Test","IsNew":true}]}
这看起来不错。现在,如果我将响应视为xml,则看起来像:
<ComRestResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Data xmlns:d2p1="http://schemas.datacontract.org/2004/07/Comp.Rest.Data.Persons">
<d2p1:User>
<d2p1:UserId>ABC123</d2p1:UserId>
<d2p1:UserName>John Smith</d2p1:UserName>
<d2p1:IsNew>true</d2p1:IsNew>
</d2p1:User>
<d2p1:User>
<d2p1:UserId>XYZ789</d2p1:UserId>
<d2p1:UserName>Raimond Test</d2p1:UserName>
<d2p1:IsNew>true</d2p1:IsNew>
</d2p1:User>
</Data>
<ValidationItems xmlns:d2p1="http://schemas.datacontract.org/2004/07/Comp.BaseInterface.Validation">
<d2p1:ValidationItem>
<d2p1:ValidationId>UserIsNew</d2p1:ValidationId>
<d2p1:ErrorParameters xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string>foo</d4p1:string>
<d4p1:string>bar</d4p1:string>
</d2p1:ErrorParameters>
<d2p1:Severity>Information</d2p1:Severity>
</d2p1:ValidationItem>
</ValidationItems>
</ComRestResult>
这看起来不好。尽管所有信息都存在,但xml命名空间存在问题。 d2p1
和所有其他
如果我在[DataContract]
类上应用[DataMember]
和User
属性,例如:
[DataContract(Name = "User", Namespace = "")]
public class User
{
[DataMember(Name = "UserId")]
public string UserId { get; set; }
[DataMember(Name = "UserName")]
public string UserName { get; set; }
[DataMember(Name = "IsNew")]
public bool IsNew { get; set; }
}
用户的response-xml如下:
<Data>
<User>
<IsNew>true</IsNew>
<UserId>ABC123</UserId>
<UserName>John Smith</UserName>
</User>
<User>
<IsNew>true</IsNew>
<UserId>XYZ789</UserId>
<UserName>Raimond Test</UserName>
</User>
</Data>
这就是我们所需要的。但是我们是否真的需要在每个类上应用属性,或者是否有可能在序列化时停用(或取消激活)名称空间?
另一个问题是string[]
类中的ValidationItem
。目前,它被序列化为:
<d2p1:ErrorParameters xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string>foo</d4p1:string>
<d4p1:string>bar</d4p1:string>
</d2p1:ErrorParameters>
我知道我可以将string[]
替换为以下类:
[CollectionDataContract(ItemName = "value", Namespace = "")]
public class StringArray : List<string>
{
}
但是不幸的是,此类很老,经常使用(约4000个引用),并且也用于SOAP序列化。因此,我们不能轻易更改它。
我们还需要类似不带名称空间的xml通用序列化。
答案 0 :(得分:0)
我自己解决了。
根据以下文章,可以使用XmlSerializer
代替DataContractSerializer
。这样就可以了。