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

时间:2014-06-04 06:45:11

标签: json rest post servicestack

使用带有Route anotation的RequestClass来调用Json-Client POST方法。 现在,虽然参数的结构类似于

public class GetTicketRequest: IReturn<JsonObject>
{
    public string CartId {
        get;
        set;
    }
    public string PriceId {
        get;
        set;
    }
}

BackendAPI需要它们在json请求的“data”中生成,所以更像是

{
   "data":[
   {"cartid":123,
   "priceId":11}]
}

在调用

之前,有没有办法转换身体的请求对象?
JsonServiceClient _restClient = new JsonServiceClient(baseUrl);
JsonObject oneResponse = _restClient.Post(options);

2 个答案:

答案 0 :(得分:5)

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

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

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

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

用法:

所以给这个DTO:

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

您只需添加转换器:

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

答案 1 :(得分:0)

我使用类型化数据属性解决了这个问题

public class GetTicketRequest: IReturn<JsonObject>
{
    public class TicketCreateData
    {            
        public int priceId {
            get;
            set;
        }
    }

    public string CartId {
      get;
      set;
    }
    public string PriceId {
      get;
      set;
    }

    public List<TicketCreateData> data {
        get {
            var list = new List<TicketCreateData>();
            list.Add(new TicketCreateData {
                priceId = this.PriceId.ToInt()
            });
            return list;
        }
        set {
            data = value;
        }
    }
}

关于此事的说明:

  • if neede,使用DataContract / DataMember(Name =&#34;&#34;)重命名字段或仅进行部分序列化
  • 永远不会使用结构,就像在这种情况下一样,数据类 - 它们根本不可序列化
  • 在我的spefici案例中数据甚至需要是一个数组,这就是为什么我使用列表