【问题标题】:How can I POST (as XML) an object to my ApiController using RestSharp?如何使用 RestSharp 将对象发布(作为 XML)到我的 ApiController?
【发布时间】:2012-08-03 16:32:12
【问题描述】:

我有一个实现 REST API 的 ASP.NET MVC4 网站,我从客户端应用程序中使用它。我的 ApiController 方法接受和返回复杂对象,如 XML。

我最近发现了 RestSharp,并开始将我的客户项目转移到那里。但是,我遇到了真正的问题。它似乎几乎起作用了——它是如此接近以至于我几乎可以尝到成功的滋味——但我就是无法让它 100% 起作用。

我穿过电线的物体看起来像这样:

// The object I'm passing across the wire
public class Example
{
    bool IsActive { get; set; }
    string Name { get; set; }
}

我的 ApiController 方法如下所示:

// My ApiController method
public HttpResponseMessage PostExample(Example example)
{
    if (ModelState.IsValid)
    {
        db.Examples.Add(example);

        db.SaveChanges();

        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, example);

        return response;
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
}

当我尝试将对象发布到我的网站时会出现问题,如下所示:

var example = new Example () { IsActive = true, Name = "foo" };

var request = new RestSharp.RestRequest("/api/example", RestSharp.Method.POST);

request.AddBody(example, XmlNamespace);

var client = new RestClient();

client.BaseUrl = "foo.com";

var response = client.Execute<Example>(request);

上面的代码确实命中了我的 ApiController 中的 PostExample 方法,它有一个 Example 对象作为参数。 但是 Example 对象的属性值与我传递给 Execute 方法的值不一样!在一种情况下,IsActive 成员是 false 而不是 true,尽管我也看到了 Name 成员为 null 的情况,它应该有一个值。

我使用 Fiddler 进行了一些调查,似乎在 RestSharp 生成的 XML 中创建了正确的值 。但是,XML 与 Web 服务器在执行 GET 时发出的格式并不完全相同。差异是微妙的,但似乎在它工作和不工作之间有所不同。 Web 服务器端的框架似乎对这些格式差异很敏感,因此会误解 XML。

这是我从 RestSharp 获得的 XML:

<Example xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace">
  <Name>foo</Name>
  <IsActive>true</IsActive>
</Example>

这是我在网络服务器上执行 GET 时得到的(或使用 DataContractSerializer 进行序列化时,这是我之前所做的):

<Example xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace">
  <IsActive>true</IsActive>
  <Name>foo</Name>
</TagDto>

RestSharp 版本与 DataContractSerializer 的版本有以下区别:

  1. 字段的顺序不同
  2. RestSharp 不包含额外的命名空间 XMLSchema-instance 命名空间
  3. DataContractSerializer 不包含任何空格或换行符(为了便于阅读,我在上面添加了这些)

我很惊讶其中任何一个都会产生很大的不同,但显然它们确实如此。另请注意,在我在 AddBody 调用中添加显式命名空间之前,生成的 XML 中缺少该命名空间(显然),并且传递给我的 ApiController 的示例对象是 null

无论如何,我注意到 RestSharp 允许您覆盖序列化程序,并提供了一种使用 .NET XML 序列化程序的方法。我尝试使用它(无济于事)。

这是我在调用 AddBody 之前添加的:

request.XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer(XmlNamespace);

..这就是我得到的结果:

<?xml version="1.0" encoding="utf-8"?>
<Example>
  <Name>foo</Name>
  <IsActive>true</IsActive>
</Example>

这显然不好,尤其是因为它以 XML 声明开头,我想 导致问题。没有办法关闭它,因为 RestSharp 派生类没有提供这样做的方法。此外,没有命名空间 - 无论我如何尝试在 RestSharp 中设置命名空间(在 DotNetXmlSerializer 的构造函数中,通过设置命名空间成员或通过将命名空间传递给添加正文)。在我看来,这门课只不过是个陷阱。

看来我唯一的选择是创建自己的序列化程序类并在内部使用 DataContractSerializer。是这样吗,还是我错过了什么?

(顺便说一句,我可以将请求的 RequestFormat 设置为 JSON,它可以正常工作 - 但我仍然想知道如何使用 XML)。

【问题讨论】:

  • RestSharp 是不是一定要使用?
  • @CuongLe:哈!我最初是使用 DataContractSerializer 开始自己开发的,然后被同事说服使用 RestSharp。我可以切换到另一个解决方案,但我现在已经投入了大量时间来尝试让 RestSharp 工作,以至于我不愿意这样做。正如我在回答中暗示的那样,我最终改用 JSON 而不是 XML,所以这个问题仍然主要是为了他人的利益。
  • @Gary,我认为 JSON 是 RESTSharp 之类的库真正出类拔萃的地方,而且在性能方面您也会获得一点性能提升。

标签: serialization asp.net-web-api restsharp


【解决方案1】:

我遇到了一些关于 AddBody 调用未正确序列化 JSON 值的问题,因此可能与您的问题有一些相似之处。而不是 AddBody,您可以尝试:

request.AddParameter("text/xml", xmlAsString, ParameterType.RequestBody);

如果可行,您可以查看将第二个参数更改为 xml 对象并查看序列化程序是否执行您想要的操作。

另一个选项可能是XmlMediaTypeFormatter.ReadFromStreamAsync 没有正确选择正确的序列化程序;您可以尝试覆盖该函数。

【讨论】:

    【解决方案2】:

    上述问题是因为 WebAPI 正在使用 DataContractSerializer(而不是您所追求的 XmlSerializer)。要切换它,请按如下方式修改 Global.asax。

     var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
     xml.UseXmlSerializer = true;
    

    但是,我建议您对 WebAPI 使用 RESTSharp 格式化程序(而不是使用 .Net 格式化程序)。如果您的 DTO 有循环引用,这将特别有用(.net fx 序列化程序不能很好地处理这个问题)。

    在 Global.asax 中,通过输入修改格式化程序

    GlobalConfiguration.Configuration.Formatters.XmlFormatter = //RestSharp XML serializer here

    WebAPI 中序列化的快速概览is here and worth a browse

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 2019-12-06
      相关资源
      最近更新 更多