我正在使用 ServiceStack 创建一个 RESTful 服务,该服务应该使用带有 multipart/form-data 内容的 POST。内容是 JSON 格式,但是当我发送 POST 时,对象没有正确反序列化(所有属性都是空/默认值)。如果我尝试将该对象作为常规 POST 发送(没有 multipart/form-data),它反序列化就好了。
我在 ServiceStack 代码中四处寻找,试图弄清楚发生了什么,这是我目前的理解:
- HttpListenerRequestWrapper::LoadMultiPart() 正在加载多部分请求并将(非文件)部分保存到“FormData”,它将部分名称映射到其内容。但是,内容类型(在解析各个部分时正确写入 HttpMultiPart::Element )似乎丢失了,因为它没有存储在任何地方。
- 稍后在控制流中,EndpointHandlerBase::DeserializeHttpRequest() 使用 FormData 和要反序列化的类型调用 KeyValueDataContractDeserializer.Instance.Parse()。
- 如果这是第一次反序列化该类型的对象,则会为该类型创建一个 StringMapTypeDeserializer 并缓存到 typeStringMapSerializerMap。对于该类型的每个属性,我们调用 JsvReader.GetParseFn() 来获取 ParseStringDelegate 来解析该属性的反序列化。
- 然后使用创建/缓存的 StringMapTypeDeserializer 反序列化对象,使用前面设置的所有“ParseFn”......它们都将内容视为 JSV 格式。
我确认 JsvReader.ParseFnCache 里面有一堆类型,而 JsonReader.ParseFnCache 是空的。此外,如果我更改删除所有引号的请求(即将它从 JSON 转换为 JSV 格式),它会正确反序列化。一件奇怪的事情是我的对象的一个属性是一个字典,它可以正确反序列化,即使它是 JSON 格式;我假设这只是一个幸运的巧合(?!?)。
我对这里发生的事情的理解是否正确?这是 ServiceStack 中的一个已知限制吗?漏洞?除了将我的对象放在文件中并手动调用 JsonSerializer.DeserializeFromStream() 之外,还有其他方法可以解决它吗?
谢谢!
JP
此外,以防万一它有用,这里是相关的请求和数据对象:
POST /api/Task HTTP/1.1
Accept: application/json
Content-Type: multipart/form-data; boundary=Boundary_1_1161035867_1375890821794
MIME-Version: 1.0
Host: localhost:12345
Content-Length: 385
--Boundary_1_1161035867_1375890821794
Content-Type: application/json
Content-Disposition: form-data; name="MyMap"
{"myfile.dat":"ImportantFile"}
--Boundary_1_1161035867_1375890821794
Content-Disposition: form-data; name="MyThing"
Content-Type: application/json
{"Id":123,"Name":"myteststring"}
--Boundary_1_1161035867_1375890821794
Content-Type: application/octet-stream
Content-Disposition: form-data; filename="myfile.dat"
mydatagoeshere...
--Boundary_1_1161035867_1375890821794--
.
public class TestObj
{
public long Id { get; set; }
public string Name { get; set; }
}
[Route("/Task", "POST")]
public class TaskRequest : AuthenticatedRequest, IReturn<TaskResponse>
{
public TestObj MyThing { get; set; }
public Dictionary<string, string> MyMap { get; set; }
}