ServiceStack:我可以“展开”帖子主体的结构吗?

我有一个采用URL路径参数的POST端点,然后主体是提交的DTO列表。

所以现在请求DTO看起来像是:

[Route("/prefix/{Param1}", "POST")]
public class SomeRequest
{
    public string          Param1  { get; set; }
    public List<SomeEntry> Entries { get; set; }
}

public class SomeEntry
{
    public int    ID    { get; set; }
    public int    Type  { get; set; }
    public string Value { get; set; }
}

服务方法如下所示:

public class SomeService : Service
{
    public SomeResponse Post(SomeRequest request)
    {
    }
}

如果通过JSON编码,客户端将不得不通过这种方式编码POST主体:

{
    "Entries":
    [
        {
            "id":    1
            "type":  42
            "value": "Y"
        },
        ...
    ]
}

这是多余的,我希望客户端提交像这样的数据:

[
    {
        "id":    1
        "type":  42
        "value": "Y"
    },
    ...
]

如果我的请求DTO只是List<SomeEntry> ,情况就会List<SomeEntry>

我的问题是:有没有办法通过这种方式“扁平化”请求? 或者将请求的一个属性指定为消息主体的根? 即也许:

[Route("/prefix/{Param1}", "POST")]
public class SomeRequest
{
    public string          Param1  { get; set; }
    [MessageBody]
    public List<SomeEntry> Entries { get; set; }
}

这在ServiceStack中可以以任何方式进行操作吗?


我能够通过继承List<T>来完成这项工作:

[Route("/prefix/{Param1}", "POST")]
public class SomeRequest : List<SomeEntry>
{
    public string          Param1  { get; set; }
}

然后你可以发送这样的请求:

POST /prefix/someParameterValue
Content-Type: application/json
[ { "ID": 1, "Type": 2, "Value": "X" }, ... ]

但是如果你在设计中有任何选择,我不会推荐这个。 从以下几个原因开始:

  • 在运行时我发现至少有一个问题:发送一个空数组,如JSON中的[ ] ,会导致一个带有RequestBindingException400状态码
  • 它不够灵活。 如果您将来需要为请求添加其他顶级属性,该怎么办? 你会被困在他们的路径/查询参数。 拥有常规的包含列表的列表允许您在请求主体的顶层添加新的可选属性,并具有向后兼容性

  • 好的,我设法实现了这一点。 不是最漂亮的解决方案,但现在会做。

    我为JSON封装了内容类型过滤器:

    var serz   = ContentTypeFilters.GetResponseSerializer("application/json");
    var deserz = ContentTypeFilters.GetStreamDeserializer("application/json");
    ContentTypeFilters.Register("application/json", serz, (type, stream) => MessageBodyPropertyFilter(type, stream, deserz));
    

    然后,自定义解串器看起来像这样:

    private object MessageBodyPropertyFilter(Type type, Stream stream, StreamDeserializerDelegate original)
    {
        PropertyInfo prop;
        if (_messageBodyPropertyMap.TryGetValue(type, out prop))
        {
            var requestDto = type.CreateInstance();
            prop.SetValue(requestDto, original(prop.PropertyType, stream), null);
            return requestDto;
        }
        else
        {
            return original(type, stream);
        }
    }
    

    _messageBodyPropertyMap在初始化后通过扫描请求DTO并寻找特定属性来填充,如我原始问题中的示例。

    链接地址: http://www.djcxy.com/p/68707.html

    上一篇: ServiceStack: Can I "Flatten" the structure of the post body?

    下一篇: how to pass in paramters to a post request using the servicestack json client