【问题标题】:Validating and passing controller-level parameters with ASP.NET MVC attribute routing使用 ASP.NET MVC 属性路由验证和传递控制器级参数
【发布时间】:2019-10-02 20:08:12
【问题描述】:

我有一个 ASP.NET 控制器,其中每个方法都有一个共享参数。通过属性路由,我可以在控制器的路由中添加这个参数。

但是,我仍然需要在每个方法中添加该参数以及验证属性。有没有办法让我在一个地方进行验证或避免将其传递给每个方法?

这是当前的工作代码:

[ApiController]
[Route("[controller]/{name}")]
public class ExampleController : ControllerBase
{
    [HttpGet]
    public string Sample([StringLength(10)][FromRoute]string name)
    {
    }

    [HttpGet]
    [Route("defaults")]
    public string GetDefaults([StringLength(10)][FromRoute]string name)
    {
    }

    [HttpGet]
    [Route("objects/{id}")]
    public string Sample([StringLength(10)][FromRoute]string name, [FromRoute]string id)
    {
    }
}

有可能得到接近这个的东西吗? (我知道控制器上的验证参数无效,但我只想应用一次)

[ApiController]
[StringLength(10)]
[Route("[controller]/{name}")]
public class ExampleController : ControllerBase
{
    [HttpGet]
    public string Sample()
    {
    }

    [HttpGet]
    [Route("defaults")]
    public string GetDefaults()
    {
    }

    [HttpGet]
    [Route("objects/{id}")]
    public string Sample([FromRoute]string id)
    {
    }
}

【问题讨论】:

  • 所以我认为模型绑定只适用于POST请求体和GET请求中的查询参数。您可以将模型绑定到 GET 请求中的路由参数吗?我的路线大多看起来像 /basePath/{category}/resourceType/{uid},没有查询字符串。

标签: c# asp.net-mvc asp.net-core asp.net-web-api


【解决方案1】:

您可以使用自定义操作过滤器来验证名称参数:

public class ValidateNameParameterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionParameters.ContainsKey(name))
        {
            // the trick is to get the parameter from filter context
            string name = filterContext.ActionParameters[name] as string;

            // validate name

            if (/*name is not valid*/)
            {
                // you may want to redirect user to error page when input parameter is not valid
                filterContext.Result = new RedirectResult(/*urlToRedirectForError*/);
            }

            base.OnActionExecuted(filterContext);
        }
    }
}

现在您可以将过滤器应用于您的控制器或特定操作:

[ApiController]
[Route("[controller]/{name}")]
[ValidateNameParameter] // <-- execute this for all actions in the controller
public class ExampleController : ControllerBase
{
    [HttpGet]
    public string Sample([StringLength(10)][FromRoute]string name)
    {
    }

    [HttpGet]
    [Route("defaults")]
    public string GetDefaults([StringLength(10)][FromRoute]string name)
    {
    }

    [HttpGet]
    [Route("objects/{id}")]
    // [ValidateNameParameter] // <-- execute for this specific action
    public string Sample([StringLength(10)][FromRoute]string name, [FromRoute]string id)
    {
    }
}

更多信息请参见this tutorial

【讨论】:

    【解决方案2】:

    正如 Hooman Bahreini 所说,您可以自定义一个继承 ActionFilterAttribute 的操作过滤器并将其用作控制器上的属性。在 Asp.net 核心中,ActionArguments 替换 ActionParameters

    public class ValidateNameParameterAttribute: ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.ActionArguments.ContainsKey("name"))
            {
                string name = filterContext.ActionArguments["name"] as string;
    
                if(name!=null && name.Length>10)
                {
                    filterContext.Result = new BadRequestObjectResult("The length of name must not exceed 10");
                }
            }
        }
    }
    

    更多关于 ASP.NET Core 中过滤器的详细信息,您可以参考here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 2023-01-25
      • 1970-01-01
      相关资源
      最近更新 更多