ASP.NET Core

时间:2017-05-10 14:32:05

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

使用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在调用我的控制器之前进行验证,从而保持控制器的整洁。

5 个答案:

答案 0 :(得分:17)

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

根据此处的文件: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

答案 1 :(得分:2)

让框架为您完成工作。这是一个解决方案,因为看起来有很多方法可以在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() };
    }        
}

答案 2 :(得分:1)

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

[Route("api/[controller]")]
public class ValuesController : Controller
{
    [HttpGet("{A}")]
    public IEnumerable<string> Get(int A, int B)
    {
       return new [] { A.ToString(), B.ToString() };
    }
}

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

答案 3 :(得分:1)

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

Account.AccountNumber

有关此的更多信息 https://andrewlock.net/coming-in-asp-net-core-2-1-top-level-mvc-parameter-validation/

答案 4 :(得分:-3)

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