【发布时间】:2017-10-13 23:10:13
【问题描述】:
我正在尝试从 dot net core 中的路由解析参数列表(在我的情况下为长)。所以我想要这样的东西
[HttpGet("{ids?}")]
public async Task<IActionResult> Get([FromRoute, Optional]long[] ids)
{
}
我知道默认情况下它不起作用,我也知道它通过查询字符串起作用。但是,为了保持一致性,我想将其保留为路由参数。
是否可以在 dot net core 中扩展 FromRoute 并实现此行为?
到目前为止,我设法创建了一个在技术上有效的操作过滤器,但它需要额外的属性,默认 FromRoute 仍在模型状态中创建错误(尤其是最后一部分显然是不可接受的)。
我当前的属性部分代码可能可重复用于正确的实现。
public class ArrayInputAttribute : ActionFilterAttribute
{
private readonly List<string> _ParameterNames;
public string Separator { get; set; }
public ArrayInputAttribute(params string[] parameterName)
{
_ParameterNames = parameterName.ToList();
Separator = ",";
}
public void ProcessArrayInput(ActionExecutingContext actionContext, string parameterName)
{
if (actionContext.ActionArguments.ContainsKey(parameterName))
{
var parameterDescriptor = actionContext.ActionDescriptor.Parameters.FirstOrDefault(p => p.Name == parameterName);
if (parameterDescriptor != null && parameterDescriptor.ParameterType.IsArray)
{
var type = parameterDescriptor.ParameterType.GetElementType();
var parameters = String.Empty;
if (actionContext.RouteData.Values.ContainsKey(parameterName))
{
parameters = (string)actionContext.RouteData.Values[parameterName];
}
else
{
var queryString = actionContext.HttpContext.Request.Query;
if (queryString[parameterName].Count > 0)
{
parameters = queryString[parameterName];
}
}
try
{
var values = parameters.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries)
.Select(TypeDescriptor.GetConverter(type).ConvertFromString).ToArray();
var typedValues = Array.CreateInstance(type, values.Length);
values.CopyTo(typedValues, 0);
actionContext.ActionArguments[parameterName] = typedValues;
}
catch (System.Exception)
{
(actionContext.Controller as Controller).ViewData.ModelState.AddModelError(parameterDescriptor.Name, "");
}
}
}
}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
_ParameterNames.ForEach(parameterName => ProcessArrayInput(actionContext, parameterName));
}
}
你可以这样使用它
[HttpGet("{ids?}")]
[ArrayInput("ids")]
[Produces(typeof(TestWebResponseDTO))]
public async Task<IActionResult> Get(long[] ids)
{
}
【问题讨论】:
-
它需要很长[] 还是自定义 DTO 可以工作?因为那时 CustomModelBinders 可能会为您执行此操作。
-
如果它的 ID 集合为什么你不使用
HttpPost.? URL 有字符限制 -
@MindingData 它应该是 long/int ,因为这是最有意义的。尽管自定义模型绑定器很有趣,但它不适用于数组或列表吗?
-
@LP13 绝对不能发帖。它得到了,我没有在服务器上创建任何数据,我只是根据 id 获取一些数据。
-
@MindingData 我找到了这个stevejgordon.co.uk/html-encode-string-aspnet-core-model-binding,这家伙实现了字符串的自定义绑定。也许我可以用 lists/arrays 做类似的事情。我明天去看看
标签: c# asp.net-core