服务堆栈POST请求正文格式/转换

emx*_*emx 2 rest post json servicestack

我使用带有Route anotation的RequestClass来调用Json-Client POST方法.现在,虽然参数的结构是这样的

public class GetTicketRequest: IReturn<JsonObject>
{
    public string CartId {
        get;
        set;
    }
    public string PriceId {
        get;
        set;
    }
}
Run Code Online (Sandbox Code Playgroud)

BackendAPI需要它们在json请求中的"data"中,所以更像是

{
   "data":[
   {"cartid":123,
   "priceId":11}]
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在调用之前转换为body的请求对象

JsonServiceClient _restClient = new JsonServiceClient(baseUrl);
JsonObject oneResponse = _restClient.Post(options);
Run Code Online (Sandbox Code Playgroud)

Sco*_*ott 5

此解决方案适用于需要包装和转换许多DTO并且可高度重复使用的情况,而不会对现有DTO进行任何更改.

您可以JsonServiceClient通过覆盖处理准备发送请求的方法来转换请求.这意味着实现您自己的扩展JsonServiceClient ,如下所示.

如果你想对所有动词执行此操作,那么你可以覆盖它的Send<TResponse>方法(否则,如果它只是为了POST取消注释已注释掉的代码,并删除Send方法).

public class MyJsonServiceClient : JsonServiceClient
{
    public Dictionary<Type, Func<object, object>> DtoConverters = new Dictionary<Type, Func<object, object>>();

    public MyJsonServiceClient() {}
    public MyJsonServiceClient(string baseUri) : base(baseUri) {}
    public MyJsonServiceClient(string syncReplyBaseUri, string asyncOneWayBaseUri) : base(syncReplyBaseUri, asyncOneWayBaseUri) {}

    public override TResponse Send<TResponse>(object request)
    {
        return base.Send<TResponse>(ConvertRequest(request));
    }

    public override TResponse Send<TResponse>(string httpMethod, string relativeOrAbsoluteUrl, object request)
    {
        return base.Send<TResponse>(httpMethod, relativeOrAbsoluteUrl, ConvertRequest(request));
    }

    /*
    public override TResponse Post<TResponse>(string relativeOrAbsoluteUrl, object requestDto)
    {
        return base.Post(relativeOrAbsoluteUrl, ConvertRequest(requestDto));
    }
    */

    object ConvertRequest(object request)
    {
        Type dtoType = request.GetType();
        return (DtoConverters.ContainsKey(dtoType)) ? DtoConverters[dtoType](request) : request;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

所以给这个DTO:

[Route("/test", "POST")]
public class TicketRequest : IReturnVoid
{
    public string CartId { get; set; }
    public string PriceId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您只需添加转换器:

var client = new MyJsonServiceClient("http://localhost:9000");

// Simple converter for TicketRequest
client.DtoConverters.Add(typeof(TicketRequest), dto => {
    var d = (TicketRequest)dto;
    return new { 
        data = new { 
            CartId = d.CartId.ToInt(), 
            PriceId = d.PriceId.ToInt() 
        } 
    };
});

client.Post(new TicketRequest { CartId = "123", PriceId = "456" });
Run Code Online (Sandbox Code Playgroud)