误差的WebAPI系列化 [英] Error with WebApi serialization

查看:254
本文介绍了误差的WebAPI系列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个控制器其中返回不同的结果的WebAPI。例如,一个控制器返回IEnumberable,另外一个酒吧,的IEnumberable等其他的IEnumberable,而我所要做的就是:

 返回OK(thething)

和一切工作得很好,即使是复杂的嵌套对象被序列化没有问题。

现在,客户要求将所有结果在包装退货:

 公共类包装
{
    公共BOOL成功{搞定;组; }
    公众诠释错误code {搞定;组; }
    公共字符串的ErrorMessage {搞定;组; }
    公共字符串的Referer {搞定;组; }
    公共对象有效负载{搞定;组; }
}

认为这将是微不足道的,但是当我尝试从控制器返回它:

 返回OK(新包装{成功=真,Referer的=我,有效载荷= thething)

我得到一个序列化错误。

异常消息是:


  

在'ObjectContent`1类型没有序列化反应机构
  内容类型应用程序/ xml的;字符集= UTF-8。


的内部异常消息是:


  

类型
  'System.Linq.Enumerable+WhereSelectListIterator<$c$c>2[[EPiServer.Find.Api.SearchHit1[[DGTNext.Api.Data.Entities.ProductSummary,
  DGTNext.Api.Entities,版本= 1.0.0.0,文化=中立,
  公钥=空],EPiServer.Find,版本= 9.6.0.3185,
  文化=中立,
  公钥= 8fe83dea738b45b7],[DGTNext.Api.Data.Entities.ProductSummary,
  DGTNext.Api.Entities,版本= 1.0.0.0,文化=中立,
  公钥=空]]'数据合同名称
  ArrayOfProductSummary: http://schemas.datacontract.org/2004/07/ DGTNext.Api.Data.Entities
  预计不会。试想,如果你使用的是DataContractResolver
  使用的DataContractSerializer或不添加静态已知的任何类型
  已知类型的列表 - 例如,通过使用KnownTypeAttribute
  属性或通过将其添加到传递到已知类型的列表
  串行器。


我是什么做错了吗?为什么确定()功能似乎是处理之前的任何对象,但现在有问题?

感谢。

编辑:按照要求,东西一个简单的例子导致错误:

 类Foo {
    公众诠释ANINT {搞定;组; }
}
公共IHttpActionResult获得(){
    返回OK(新包装{成功=真,Referer的=我,有效载荷=新的Foo {ANINT = 7}});
}

编辑:

好吧,我想出了一种解决方案,但它仍然提出了一些问题。

我做了我的包装的有效负载的类型通用的。

 公共类包装&LT; T&GT;
{
    公共BOOL成功{搞定;组; }
    公众诠释错误code {搞定;组; }
    公共字符串的ErrorMessage {搞定;组; }
    公共字符串的Referer {搞定;组; }
    公共ŧ载荷{搞定;组; }
}

所以,现在,这个作品:

 公共IHttpActionResult获得(){
    清单&LT;富&GT; FOOS =新的List&LT;富&GT;();
    foos.Add(新富{ANINT = 7});
    foos.Add(新富{ANINT = 8});
    返回OK(新包装&LT;&IEnumerable的LT;富&GT;&GT; {成功=真,Referer的=我,有效载荷= FOOS});
}

返回的是:

<$p$p><$c$c>{\"Success\":true,\"Error$c$c\":0,\"ErrorMessage\":null,\"Referer\":\"me\",\"Payload\":[{\"AnInt\":7},{\"AnInt\":8}]}

和我的真实的电话:

 公共IHttpActionResult获得(){
    IEnumerable的&LT; ProductSummary&GT;触头= db.getProductSummaries(shopId,文化,queryParams,分页);
    返回OK(新包装&LT;&IEnumerable的LT; ProductSummary&GT;&GT; {成功=真,Referer的=我,有效载荷=触头});
}

返回:

&LT; WrapperOfArrayOfProductSummaryzc2y5_Pnl&GT;
    &LT;错误code&GT; 0℃; /错误code&GT;
    &LT;的ErrorMessage我:无=真/&GT;
    &所述有效载荷GT;
        &LT; d2p1:ProductSummary&GT;
            &LT; d2p1:文化我:无=真/&GT;
            &LT; d2p1:GUID我:无=真/&GT;
            &LT; d2p1:ID&GT; 2'; / d2p1:ID&GT;
            &LT; d2p1:名称&gt; Letto亚洲和LT; / d2p1:名称&gt;
            &LT; d2p1:环境&GT;
                &LT; d2p1:ID&GT; 1073741838&LT; / d2p1:ID&GT;
                &LT; d2p1:名称&gt;&晚报LT; / d2p1:名称&gt;
            &LT; / d2p1:环境&GT;
    等等

所以不坏,但是这产生了两个问题:


  1. 要测试的WebAPI,我通过把一个URL在Firefox地址栏和寻找一个在浏览器中的结果调用它。为什么在世界上做第一次调用返回JSON,而第二个XML?据我知道,我只是使用默认的一切。


  2. 为什么XML现在加入该命名空间的所有元素名称?我可以prevent呢?当我刚回到同样的事情没有包装,这并没有发生。



解决方案

这code加入的Global.asax 下方的的Application_Start

从更新的结尾。可以忽略 .Serialize 。它必须工作。

<$p$p><$c$c>GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

或者你可以看看这个<一个href=\"http://stackoverflow.com/questions/23098191/failed-to-serialize-the-response-in-web-api-with-json\">answer

I have a WebApi with several controllers which return different results. For example, one controller returned an IEnumberable, another a Bar, another an IEnumberable of IEnumberable etc., and all I had to do was:

return Ok(thething)

and everything worked fine, even complicated nested objects were serialized with no problem.

Now, The client asked that all results be returned in a Wrapper:

public class Wrapper
{
    public bool Success { get; set; }
    public int ErrorCode { get; set; }
    public String ErrorMessage { get; set; }
    public String Referer { get; set; }
    public Object Payload { get; set; }
}

Thought it would be trivial, but when I try to return it from the controller:

return Ok( new Wrapper { Success=true, Referer="me", Payload=thething)

I get a serialization error.

The Exception message is:

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.

The Inner Exception message is:

Type 'System.Linq.Enumerable+WhereSelectListIterator2[[EPiServer.Find.Api.SearchHit1[[DGTNext.Api.Data.Entities.ProductSummary, DGTNext.Api.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], EPiServer.Find, Version=9.6.0.3185, Culture=neutral, PublicKeyToken=8fe83dea738b45b7],[DGTNext.Api.Data.Entities.ProductSummary, DGTNext.Api.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ArrayOfProductSummary:http://schemas.datacontract.org/2004/07/DGTNext.Api.Data.Entities' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer 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 the serializer.

What am I doing wrong? Why did the Ok() function seem to be handle any object before, but has problems now?

Thanks.

Edit: As requested, a simple example of something causing the error:

class Foo {
    public int AnInt { get; set; }
}


public IHttpActionResult Get() {
    return Ok(new Wrapper { Success=true, Referer="me", Payload= new Foo {AnInt = 7}});
}

Edit:

Well, I came up with kind of a solution, but it still raises some questions.

I made my Wrapper generic in the type of the Payload.

public class Wrapper<T>
{
    public bool Success { get; set; }
    public int ErrorCode { get; set; }
    public String ErrorMessage { get; set; }
    public String Referer { get; set; }
    public T Payload { get; set; }
}

So now, this works:

public IHttpActionResult Get() {
    List<Foo> foos = new List<Foo>();
    foos.Add(new Foo { AnInt = 7 });
    foos.Add(new Foo { AnInt = 8 });
    return Ok(new Wrapper<IEnumerable<Foo>> { Success=true, Referer="me", Payload= foos});
}

It returns:

{"Success":true,"ErrorCode":0,"ErrorMessage":null,"Referer":"me","Payload":[{"AnInt":7},{"AnInt":8}]}

And my "real" call:

public IHttpActionResult Get() {
    IEnumerable<ProductSummary> prods =  db.getProductSummaries(shopId, culture, queryParams, paging);
    return Ok(new Wrapper<IEnumerable<ProductSummary>> { Success = true, Referer = "me", Payload = prods });
}

returns:

<WrapperOfArrayOfProductSummaryzc2y5_Pnl>
    <ErrorCode>0</ErrorCode>
    <ErrorMessage i:nil="true"/>
    <Payload>
        <d2p1:ProductSummary>
            <d2p1:Culture i:nil="true"/>
            <d2p1:Guid i:nil="true"/>
            <d2p1:Id>2</d2p1:Id>
            <d2p1:Name>Letto Asia</d2p1:Name>
            <d2p1:ambient>
                <d2p1:Id>1073741838</d2p1:Id>
                <d2p1:Name>notte</d2p1:Name>
            </d2p1:ambient>  
    etc.

So not bad, but this raises two questions:

  1. To test the webapi, I'm calling it by putting an URL in the Firefox address bar and looking an the results in the browser. Why in the world does the first call return Json, and the second XML? As far as I know I'm just using default everything.

  2. Why is the XML now adding that namespace to all the element names? Can I prevent this? When I was just returning the same thing without the wrapper, this didn't happen.

解决方案

Add this code to global.asax below on Application_Start:

Update from .Ignore to .Serialize. It must work.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

or you may look at this answer

这篇关于误差的WebAPI系列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆