我有一个实现 REST API 的 ASP.NET MVC4 网站,我从客户端应用程序使用该网站。我的 ApiController 方法接受并返回 XML 形式的复杂对象。
我最近发现了 RestSharp,并开始将我的客户项目转移到该项目上。但是,我确实遇到了问题。看来almost工作——它是如此接近,我几乎可以尝到成功的滋味——但我就是无法让它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 对象作为参数。HoweverExample 对象的属性值与我传递给 Execute 方法的属性值不同!在一种情况下,IsActive 成员为 false 而不是 true,尽管我也看到过一种情况,其中 Name 成员本应具有值,但为 null。
我使用 Fiddler 做了一些调查,看来正确的值are在 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 版本有以下差异:
- 字段的顺序不同
- RestSharp 不包含额外的命名空间 XMLSchema-instance 命名空间
- 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 声明开头,我想这是would造成问题。没有办法关闭它,因为 RestSharp 派生类没有提供这样做的方法。另外,没有命名空间 - 无论我如何尝试在 RestSharp 中设置命名空间(在 DotNetXmlSerializer 的构造函数中,通过设置命名空间成员,或通过将命名空间传递给添加主体)。在我看来,这门课只不过是一个陷阱。
看起来我唯一的选择是创建自己的序列化器类并在内部使用 DataContractSerializer。是这样吗,还是我错过了什么?
(顺便说一句,我可以将请求的 RequestFormat 设置为 JSON,它就可以工作 - 但我仍然想知道如何使用 XML 来实现它)。