用于根据参数的存在选择路线/动作的属性

时间:2019-07-07 22:14:34

标签: asp.net-mvc asp.net-core

我以为,但我不确定,可以使用内置的属性来装饰我们的动作,它们会根据参数或模型绑定变量的存在来选择/跳过动作。

我在想这样的事情:

/*   [Route("/Objectives"), MandatoryParam("CourseId")]
  Or [Route("/Objectives", Required("CourseId")]
  or something similar like below etc. */
[Route("/Objectives")]
[MandatoryParam("CourseId")]
public Action List<Objectives> FilteredByCourse(int courseId){
    ...
}

[Route("/Objectives")]
[MandatoryParam("CategoryId")]
public Action List<Objectives> FilteredByCategory(int categoryId){
    ...
}

理想的结果是/Objectives?courseId=5/Objectives?categoryId=15将路由到两个不同的动作。

我似乎找不到用于此目的的正确搜索词-它们以讨论模型绑定或基本路由的文章结尾,但没有特定于此场景的文章。这不存在吗?

1 个答案:

答案 0 :(得分:0)

您可以通过IActionConstraint扩展点来实现。创建自定义IActionConstraint

public class RequiredFromQueryActionConstraint : IActionConstraint
{
    private readonly string _parameter;

    public RequiredFromQueryActionConstraint(string parameter)
    {
        _parameter = parameter;
    }

    public int Order => 999;

    public bool Accept(ActionConstraintContext context)
    {
        if (!context.RouteContext.HttpContext.Request.Query.ContainsKey(_parameter))
        {
            return false;
        }

        return true;
    }
}

通过IParameterModelConvention将其缝在一起:

public class RequiredFromQueryAttribute : FromQueryAttribute, IParameterModelConvention
{
    public void Apply(ParameterModel parameter)
    {
        if (parameter.Action.Selectors != null && parameter.Action.Selectors.Any())
        {
            parameter.Action.Selectors.Last().ActionConstraints.Add(new RequiredFromQueryActionConstraint(parameter.BindingInfo?.BinderModelName ?? parameter.ParameterName));
        }
    }
}

然后将其应用于您的路线:

[Route("/Objectives")]
public IActionResult Action1([RequiredFromQueryAttribute] int courseId)
{
    return View();
}
[Route("/Objectives")]
public IActionResult Action2([RequiredFromQueryAttribute]int categoryId)
{
    return View();
}

源代码和文章来自here

结果:http://localhost:xxxx/Objectives?courseId=1将被重定向到Action1http://localhost:xxxx/Objectives?categoryId=1将被重定向到Action2http://localhost:xxxx/Objectives将得到404错误。