[英]Complex array in ServiceStack request
I am sending the following request parameters to my service; 我正在将以下请求参数发送到我的服务; among which, is the filter
parameter which is a multidimensional array: 其中是filter
参数,它是一个多维数组:
filter[0][field]:homeCountry
filter[0][data][type]:string
filter[0][data][value]:united s
page:2
start:200
limit:200
sort:homeCountry
dir:ASC
The querystring is encoded like so: 查询字符串的编码如下:
paymentratetrip.json?filter%5B0%5D%5Bfield%5D=homeCountry&filter%5B0%5D%5Bdata%5D%5Btype%5D=string&filter%5B0%5D%5Bdata%5D%5Bvalue%5D=united%20s&page=2&start=200&limit=200&sort=homeCountry&dir=AS
Currently, my C# request object looks like this: 当前,我的C#请求对象如下所示:
public class PaymentRateTripRequest
{
public int start { get; set; }
public int limit { get; set; }
public string sort { get; set; }
public string dir { get; set; }
}
How can I modify my request object to receive the filter
parameter which could be a multidimensional array? 如何修改我的请求对象以接收可能是多维数组的filter
参数?
Note: I am using ServiceStack. 注意:我正在使用ServiceStack。
The only way I can think is to send the entire request object as a parameter to my method like so: 我能想到的唯一方法是将整个请求对象作为参数发送给我的方法,如下所示:
public object Get(PaymentRateTripRequest req)
{
return _repository.GetAllRates(req.start, req.limit, req.sort, req.dir, this.Request.OriginalRequest);
}
But, this doesn't seem like the best solution. 但是,这似乎不是最好的解决方案。
Edit: this.Request.QueryString 编辑: this.Request.QueryString
this.Request.QueryString
{filter%5b0%5d%5bfield%5d=homeCountry&filter%5b0%5d%5bdata%5d%5btype%5d=string&filter%5b0%5d%5bdata%5d%5bvalue%5d=united+s&page=2&start=200&limit=200&sort=homeCountry&dir=ASC}
[System.Web.HttpValueCollection]: {filter%5b0%5d%5bfield%5d=homeCountry&filter%5b0%5d%5bdata%5d%5btype%5d=string&filter%5b0%5d%5bdata%5d%5bvalue%5d=united+s&page=2&start=200&limit=200&sort=homeCountry&dir=ASC}
base {System.Collections.Specialized.NameObjectCollectionBase}: {filter%5b0%5d%5bfield%5d=homeCountry&filter%5b0%5d%5bdata%5d%5btype%5d=string&filter%5b0%5d%5bdata%5d%5bvalue%5d=united+s&page=2&start=200&limit=200&sort=homeCountry&dir=ASC}
_all: null
_allKeys: {string[8]}
AllKeys: {string[8]}
Edit: filter
is still empty. 编辑: filter
仍为空。
You should add a property with the filter to your DTO, such as below: 您应将带有过滤器的属性添加到DTO,例如:
public class PaymentRateTripRequest
{
public int page { get; set; }
public int start { get; set; }
public int limit { get; set; }
public string sort { get; set; }
public string dir { get; set; }
public FilterField[] filter { get; set; }
}
public class FilterField
{
public string field { get; set; }
public Dictionary<string,object> data { get; set; }
}
This will allow you to add any number of fields to filter by, and by making the data
property of the FilterField
a Dictionary<string, object>
you can add as many data properties as needed. 这将允许您添加任意数量的字段以进行过滤,并且通过将FilterField
的data
属性设置为Dictionary<string, object>
,可以根据需要添加任意多个数据属性。
Then you can populate the filter
parameter in your PaymentRateTripRequest
using JSV format. 然后,您可以使用JSV格式在您的PaymentRateTripRequest
填充filter
参数。 You can learn about JSV format here . 您可以在这里了解JSV格式 。 JSV Format (ie JSON-like Separated Values) is a JSON inspired format that uses CSV-style escaping for the least overhead and optimal performance. JSV格式(即类似JSON的分隔值)是受JSON启发的格式,它使用CSV样式的转义以最小化开销并获得最佳性能。
paymentratetrip.json?filter=[{field:homeCountry,data:{type:string,value:"united s"}},{field:other,data:{type:int,value:34,special:true}}]&page=2&start=200&limit=200&sort=homeCountry&dir=ASC paymentratetrip.json?filter = [{field:homeCountry,data:{type:string,value:“ united s”}}},{field:other,data:{type:int,value:34,special:true}}] &页= 2&开始= 200&限= 200&排序= homeCountry&DIR = ASC
Then you can access the filter as a regular property on your request. 然后,您可以根据请求将过滤器作为常规属性进行访问。
Hope this helps. 希望这可以帮助。
This is an alternative solution that requires no changes to your client and therefore will accept the query string in the format you have currently: 这是一种替代解决方案,不需要更改您的客户端,因此将接受您当前具有的格式的查询字符串:
paymentratetrip.json?filter%5B0%5D%5Bfield%5D=homeCountry&filter%5B0%5D%5Bdata%5D%5Btype%5D=string&filter%5B0%5D%5Bdata%5D%5Bvalue%5D=united%20s&page=2&start=200&limit=200&sort=homeCountry&dir=AS paymentratetrip.json?过滤%5B0%5D%5Bfield%5D = homeCountry及过滤%5B0%5D%5Bdata%5D%5Btype%5D =串过滤%5B0%5D%5Bdata%5D%5Bvalue%5D =团结%20S&页= 2&开始= 200&限= 200排序= homeCountry&DIR = AS
The disadvantage of this method is that it's more code to maintain. 这种方法的缺点是需要维护更多的代码。 The JSV method is simpler. JSV方法更简单。
We can use a ServiceStack filter to intercept the query string before it reaches the action method. 我们可以使用ServiceStack筛选器在查询字符串到达操作方法之前对其进行拦截。 It can then parse the custom filter format and populate the filter object of the DTO. 然后,它可以解析自定义过滤器格式并填充DTO的过滤器对象。
public class FilterAttribute : Attribute, IHasRequestFilter
{
IHasRequestFilter IHasRequestFilter.Copy()
{
return this;
}
public int Priority { get { return int.MinValue; } }
FilterField CreateOrUpdateField(ref Dictionary<string, FilterField> filter, string id)
{
if(filter.ContainsKey(id))
return filter[id];
var field = new FilterField { Data = new Dictionary<string, object>() };
filter.Add(id, field);
return field;
}
public void RequestFilter(IRequest req, IResponse res, object requestDto)
{
var filteredDto = requestDto as IFilter;
if(filteredDto == null)
return;
const string fieldPattern = @"filter\[([A-Za-z0-9]+)\]\[field\]";
const string dataPattern = @"filter\[([A-Za-z0-9]+)\]\[data\]\[([A-Za-z0-9]+)\]";
Dictionary<string, FilterField> filter = new Dictionary<string, FilterField>();
foreach(var property in req.QueryString.AllKeys)
{
Match match = Regex.Match(property, fieldPattern, RegexOptions.IgnoreCase);
if(match.Success)
{
// Field
var id = match.Groups[1].Value;
var field = CreateOrUpdateField(ref filter, id);
field.Field = req.QueryString[property];
} else {
match = Regex.Match(property, dataPattern, RegexOptions.IgnoreCase);
if(match.Success)
{
// Data value
var id = match.Groups[1].Value;
var keyName = match.Groups[2].Value;
var field = CreateOrUpdateField(ref filter, id);
if(!field.Data.ContainsKey(keyName))
field.Data.Add(keyName, req.QueryString[property]);
}
}
}
filteredDto.Filter = filter.Values.ToArray();
}
}
You will also need to add this interface and FilterField
class: 您还需要添加此接口和FilterField
类:
public class FilterField
{
public string Field { get; set; }
public Dictionary<string,object> Data { get; set; }
}
public interface IFilter
{
FilterField[] filter { get; set; }
}
Then you simply need to update your DTO so it looks like this: 然后,您只需要更新DTO,使其看起来像这样:
[Route("/paymentratetrip", "GET"]
[Filter]
public class PaymentRateTripRequest : IFilter
{
public int page { get; set; }
public int start { get; set; }
public int limit { get; set; }
public string sort { get; set; }
public string dir { get; set; }
public FilterField[] filter { get; set; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.