【问题标题】:HttpResponseMessage can't serialize contentHttpResponseMessage 无法序列化内容
【发布时间】:2016-07-17 09:36:53
【问题描述】:

我有空的 .net rest api,它只接受 XML。 如果控制器方法直接返回我要序列化的类,是没有问题的。但我想使用响应包装器,以便所有控制器方法返回HttpResponseMessage

所以这行得通: FooController.cs:

public FooResponse PostFoo(FooRequest foo)
{
  var fooVal = fooBll.GetFoo();
  return new FooResponse { Foo = fooVal;};
}

但这不是: FooController.cs:

public HttpResponseMessage PostFoo(FooRequest foo)
{
  var fooVal = fooBll.GetFoo();
  HttpResponseMesage response;
  response = fooBll.GetSuccessResponse(Url, new FooResponse {Foo = foovVal;});
  return response ;
}

ResponseBLL.cs:

public HttpResponseMessage GetSuccessResponse(UrlHelper Url, object obj)
{
    this.requestMsg = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage;
    this.responseMsg = this.requestMsg.CreateResponse(HttpStatusCode.OK, obj);
    this.responseMsg.Headers.Location = HttpContext.Current.Request.Url;
    return this.responseMsg;
}

FooBLL 继承了 ResponseBLL,所以我可以调用 fooBll.GetSuccessResponse

在 WebApiConfig.cs 我有:

config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.Formatters.Remove(config.Formatters.JsonFormatter);

我得到的错误是

类型 FooResponse 不是预期的。使用 XmlInclude 或 SoapInclude 属性指定静态未知的类型。

现在我知道这个问题已经有很多问题了,相信我,我已经解决了所有问题,但都没有成功。我已经尝试了[DataContract], [DataMember], [Serializable][XmlInclude] 属性在我能想到的所有可能的组合中。 [XmlInclude(typeof(FooResponse))] FooBLL 类,[XmlInclude(typeof(FooBLL))] ResponseBLL 等等。

我希望你能帮助我。

【问题讨论】:

  • 使用动作过滤器做这个浓缩之王会干净得多
  • @AlekseyL。谢谢,我会调查的。基本上我想要这个包装器的原因是因为这样控制器可以返回不同类型的内容,例如还有GetFailResponse 方法,它代替内容将返回有关错误的信息。没有它,据我所知,我无法做到,我必须返回FooResponse,别无其他。
  • 这可以通过异常过滤器或异常处理程序来处理

标签: c# .net xml xml-serialization xmlserializer


【解决方案1】:

HttpRequestMessageExtensions.CreateResponse<T>() 是一个通用方法。 T Value 参数必须正确键入,而不是声明为 object,例如:

public HttpResponseMessage GetSuccessResponse<T>(UrlHelper Url, T obj)
{
    this.requestMsg = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage;
    this.responseMsg = this.requestMsg.CreateResponse(HttpStatusCode.OK, obj);
    this.responseMsg.Headers.Location = HttpContext.Current.Request.Url;
    return this.responseMsg;
}

此解决方案有效,因为XmlMediaTypeFormatter 使用typeof(T) 而不是value.GetType() 构造其XmlSerializer。来自source code

    protected internal virtual object GetSerializer(Type type, object value, HttpContent content)
    {
        return GetSerializerForType(type);
    }

我们可以看到只有type(作为typeof(T)ObjectContent&lt;T&gt;传入WriteToStreamAsync())用于序列化程序的构造。 object value 不是。 Microsoft 可能已经选择使用value.GetType(),但没有。然后序列化程序抛出异常,因为进入的根对象的实际类型(在这种情况下为typeof(Foo))与用于构造序列化程序的类型(typeof(object))或object 的已知类型之一不同.

【讨论】:

  • 谢谢!不能说我完全理解它为什么以这种方式工作(xml 中的 noobie),但它做到了!但我想我必须朝着@Alleksey L. 指出的方向前进。同时会用到这个。
猜你喜欢
  • 1970-01-01
  • 2021-02-17
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多