ASP.NET Core 中必需的查询字符串参数

Posted

技术标签:

【中文标题】ASP.NET Core 中必需的查询字符串参数【英文标题】:Required query string parameter in ASP.NET Core 【发布时间】:2017-05-10 14:32:04 【问题描述】:

使用 ASP.NET Core 1.1 和 VS2015 (sdk 1.0.0-preview2-003131),我有以下控制器:

public class QueryParameters

    public int A  get; set; 
    public int B  get; set; 


[Route("api/[controller]")]
public class ValuesController : Controller

    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get([FromQuery]QueryParameters parameters)
    
        return new []  parameters.A.ToString(), parameters.B.ToString() ;
            

如您所见,我有两个查询参数。我想要的是需要其中之一(例如:A)。也就是说,我想用一个属性(如果可能的话)说这个属性是必需的。然后,我希望 ASP.NET 在调用我的控制器之前进行此验证。

我本来希望使用 Newtonsoft RequiredAttribute 来使用我已经用来验证 PUT/POST 内容中所需属性的相同属性,但由于 url 不是 JSON 字符串,显然没有使用.

有什么建议让 ASP.NET Core 自动检查所需的查询参数吗?

请注意,我知道我可以使用可为空的查询参数自己编写检查代码,但这超出了让 ASP.NET 在调用我的控制器之前进行验证的目的,从而保持我的控制器整洁。

【问题讨论】:

【参考方案1】:

在 ASP.NET Core 2.1 及更高版本中,您可以使用***参数验证。 您可以将属性放在参数上

    [HttpGet]
    public IActionResult GetDices([BindRequired, Range(1, 6)]int number)
    
        if (!ModelState.IsValid)
        
            return BadRequest("Invalid number");
        

            return Ok(_diceRepo.GetDices(number));
    

更多关于这个 https://programmingcsharp.com/asp-net-parameter-validation/#Top-level_node_validation

【讨论】:

using Microsoft.AspNetCore.Mvc.ModelBinding; 是我用来引用属性的,BindRequired【参考方案2】:

可以考虑使用框架的模型绑定功能

根据此处的文档:Customize model binding behavior with attributes

MVC 包含几个属性,您可以使用它们来指示其默认值 模型绑定行为到不同的源。例如,您可以 指定属性是否需要绑定,或者是否应该 使用[BindRequired][BindNever] 永远不会发生 属性。

所以我建议你在模型属性中添加一个BindRequiredAttribute

public class QueryParameters

    [BindRequired]
    public int A  get; set; 
    public int B  get; set; 

从那里框架应该能够处理绑定和更新模型状态,以便您可以在操作中检查模型的状态

[Route("api/[controller]")]
public class ValuesController : Controller

    // GET api/values
    [HttpGet]
    public IActionResult Get([FromQuery]QueryParameters parameters)
        
        if (ModelState.IsValid)
        
            return Ok(new []  parameters.A.ToString(), parameters.B.ToString() );
        
        return BadRequest();
            

另一种选择是创建一个自定义模型绑定器,如果所需的查询字符串不存在,它将导致操作出错。

参考:Custom Model Binding

【讨论】:

如果您希望属性具有不同的名称怎么办。在您拥有 [FromQuery(Name = "$A")] 之前【参考方案3】:

让框架为您完成工作。这是一种解决方案,因为在 ASP.NET Core 中似乎有多种方法可以完成相同的事情。但这对我有用,而且非常简单。这似乎是已经给出的一些答案的组合。

public class QueryParameters

    [Required]
    public int A  get; set; 

    public int B  get; set; 


[Route("api/[controller]")]
public class ValuesController : Controller

    // GET api/values
    // [HttpGet] isn't needed as it is the default method, but ok to leave in
    // QueryParameters is injected here, the framework takes what is in your query string and does its best to match any parameters the action is looking for. In the case of QueryParameters, you have A and B properties, so those get matched up with the a and b query string parameters
    public IEnumerable<string> Get(QueryParameters parameters)
    
        if (!ModelState.IsValid)
        
            return BadRequest(); // or whatever you want to do
        

        return new []  parameters.a.ToString(), parameters.b.ToString() ;
            

【讨论】:

【参考方案4】:

使用属性路由并在函数的 HttpGet 属性中列出每个必需的参数。

[Route("api/[controller]")]
public class ValuesController : Controller

    [HttpGet("A")]
    public IEnumerable<string> Get(int A, int B)
    
       return new []  A.ToString(), B.ToString() ;
    

这将需要 /5 并允许 /5?B=6 查询 url 参数。

【讨论】:

OP 询问如何要求查询参数,而不是 URL 参数。【参考方案5】:

使用模型验证。您可以定义 ViewModel 并使用 DataAnnotations 将属性 A 标记为 [必需]。然后在您的操作中检查是否 ModelState.IsValid。您也可以使用本文所示的操作过滤器轻松完成此操作: https://msdn.microsoft.com/en-us/magazine/mt767699.aspx

【讨论】:

以上是关于ASP.NET Core 中必需的查询字符串参数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ASP.NET Core 将查询字符串参数转换为看起来像目录部分?

如何使用 ASP.NET Core 从查询字符串中读取值?

在 ASP.NET Core Web Api 中有多个带有多个查询字符串参数的 get 方法

根据 ASP.NET Core 和 Entity Framework Core 中的条件禁用 [必需] 属性

强制在 ASP.NET Core 中具有查询参数的所有 Url

Asp.net core MVC post 参数始终为空