rest - 多部分/表单数据请求中 JSON 内容的 ServiceStack 反序列化

标签 rest servicestack multipartform-data

我正在使用 ServiceStack 创建一个 RESTful 服务,该服务应该使用包含多部分/表单数据内容的 POST。内容为 JSON 格式,但当我发送 POST 时,对象未正确反序列化(所有属性均为 null/默认值)。如果我尝试将该对象作为常规 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() 之外,还有其他解决方法吗?

谢谢!

日元

此外,为了以防万一,这里是相关的请求和数据对象:

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; }
}

最佳答案

您是否尝试过使用“ApiMember”属性设置请求对象的属性?特别是“ParameterType”属性。

/// <summary>
/// Create and upload a new video.
/// </summary>
[Api("Create and upload a new video.")]
[Route("/videos", "POST", Summary = @"Create and upload a new video.",
    Notes = "Video file / attachment must be uploaded using POST and 'multipart/form-data' encoding.")]
public class CreateVideo : OperationBase<IVideo>
{
    /// <summary>
    /// Gets or sets the video title.
    /// </summary>
    [ApiMember(Name = "Title",
        AllowMultiple = false,
        DataType = "string",
        Description = "Video title. Required, between 8 and 128 characters.",
        IsRequired = true,
        ParameterType = "form")]
    public string Title { get; set; }

    /// <summary>
    /// Gets or sets the video description.
    /// </summary>
    [ApiMember(Name = "Description",
        AllowMultiple = false,
        DataType = "string",
        Description = "Video description.",
        ParameterType = "form")]
    public string Description { get; set; }

    /// <summary>
    /// Gets or sets the publish date.
    /// </summary>
    /// <remarks>
    /// If blank, the video will be published immediately.
    /// </remarks>
    [ApiMember(Name = "PublishDate",
        AllowMultiple = false,
        DataType = "date",
        Description = "Publish date. If blank, the video will be published immediately.",
        ParameterType = "form")]
    public DateTime? PublishDate { get; set; }
}

关于rest - 多部分/表单数据请求中 JSON 内容的 ServiceStack 反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18154494/

相关文章:

java - 从 servlet 调用 servlet

php - 虚拟主机 : php_value enable_post_data_reading Off : for ONE webpage

javascript - 何时将更新推送到 REST 后端

java - 在 JSON 中包含文本文件

java - 无法处理来自 Jar 的 jar 条目

java - RESTful 层次结构以及 JAX RS 类

redis - 在 RedisTypedClient (ServiceStack Redis) 中使用复杂类型

asp.net-core - Webpack 中间件热模块替换为 ServiceStack(无 MVC)

authentication - ServiceStack - 防止未经授权访问静态文件

java - 使用 Apache FileItem 从复选框获取 boolean 值的优雅方法