我有一个实现 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 的版本有以下区别:
- 字段的顺序不同
- RestSharp 不包含额外的命名空间 XMLSchema-instance 命名空间
- DataContractSerializer 不包含任何空格或换行符(为了便于阅读,我在上面添加了这些)
我很惊讶其中任何一个都会产生很大的不同,但显然它们确实如此。另请注意,在我在 AddBody 调用中添加显式命名空间之前,生成的 XML 中缺少该命名空间(显然),并且传递给我的 ApiController 的 Example 对象是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 来实现它)。