Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ASP.NET核心中是否可能有多个仅随参数变化的GET?_C#_Asp.net Core_.net Core_Asp.net Core Routing - Fatal编程技术网

C# 在ASP.NET核心中是否可能有多个仅随参数变化的GET?

C# 在ASP.NET核心中是否可能有多个仅随参数变化的GET?,c#,asp.net-core,.net-core,asp.net-core-routing,C#,Asp.net Core,.net Core,Asp.net Core Routing,我想构建真正的RESTful web服务,因此不想利用RPC样式,因此目前有以下内容: [HttpGet] [ActionName(nameof(GetByParticipant))] public async Task<IActionResult> GetByParticipant([FromQuery]string participantId, [FromQuery]string participantType, [FromQuery]string programName) {

我想构建真正的RESTful web服务,因此不想利用RPC样式,因此目前有以下内容:

[HttpGet]
[ActionName(nameof(GetByParticipant))]
public async Task<IActionResult> GetByParticipant([FromQuery]string participantId, [FromQuery]string participantType, [FromQuery]string programName)
{
}

[HttpGet]
[ActionName(nameof(GetByProgram))]
public async Task<IActionResult> GetByProgram([FromQuery]string programName)
{
}
[HttpGet]
[ActionName(nameof(GetByParticipant))]
公共异步任务GetByParticipant([FromQuery]string participantId,[FromQuery]string participantType,[FromQuery]string programName)
{
}
[HttpGet]
[ActionName(nameof(GetByProgram))]
公共异步任务GetByProgram([FromQuery]字符串程序名)
{
}
我相信这在ASP.NETWebAPI中是可行的。但我有个例外:

AmbiguousActionException:匹配了多个操作。以下操作与路线数据匹配,并满足所有约束条件:

TermsController.GetByParticipant(ParticipantTerms.Api)

TermsController.GetByProgram(ParticipantTerms.Api)

这两个属性实际上都没有帮助:

  • [HttpGet]
  • [ActionName]
  • [FromQuery]

使用from查询时,您需要唯一地区分操作的路径,否则您将得到不明确的操作异常。原因是
api/action?participantId=1和participantType=2
api/action?programName=x

建议:

public class ParticipantQuery {
    public string participantId { get; set; } 
    public string participantType { get; set; }
    public string programName { get; set; }
}

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

    [HttpGet("participants")]  //GET api/terms/participants?participantId=123&....
    [ActionName(nameof(GetByParticipant))]
    public async Task<IActionResult> GetByParticipant([FromQuery]ParticipantQuery model) {
        //...
    }

    [HttpGet("programs/{programName}")]//GET api/terms/programs/name
    [ActionName(nameof(GetByProgram))]
    public async Task<IActionResult> GetByProgram(string programName) {
        //...
    }
}
公共类参与者查询{
公共字符串participantId{get;set;}
公共字符串participantType{get;set;}
公共字符串程序名{get;set;}
}
[路由(“api/[控制器]”)]
公共类术语控制器:控制器{
[HttpGet(“参与者”)]//获取api/terms/participants?participantId=123&。。。。
[ActionName(nameof(GetByParticipant))]
公共异步任务GetByParticipant([FromQuery]ParticipantQuery模型){
//...
}
[HttpGet(“programs/{programName}”)]///GET-api/terms/programs/name
[ActionName(nameof(GetByProgram))]
公共异步任务GetByProgram(字符串程序名){
//...
}
}
或者,可以使用一个动作封装可用参数,并根据提供的成员对结果进行分支

public class GetTermsQuery {
    public string participantId { get; set; } 
    public string participantType { get; set; }
    public string programName { get; set; }
}

[Route("api/[controller]")]
public class TermsController : Controller {    
    [HttpGet]  //GET api/terms?participantId=123&....
    public async Task<IActionResult> Get([FromQuery]GetTermsQuery model) {
        //...
    }
}
公共类GetTermsQuery{
公共字符串participantId{get;set;}
公共字符串participantType{get;set;}
公共字符串程序名{get;set;}
}
[路由(“api/[控制器]”)]
公共类TermsController:控制器{
[HttpGet]//获取api/术语?participantId=123&。。。。
公共异步任务Get([FromQuery]GetTermsQuery模型){
//...
}
}

您可以使用IActionConstraint执行此操作

以下是一个例子:

public class ExactQueryParamAttribute : Attribute, IActionConstraint
{
    private readonly string[] keys;

    public ExactQueryParamAttribute(params string[] keys)
    {
        this.keys = keys;
    }

    public int Order => 0;

    public bool Accept(ActionConstraintContext context)
    {
        var query = context.RouteContext.HttpContext.Request.Query;
        return query.Count == keys.Length && keys.All(key => query.ContainsKey(key));
    }
}

[HttpGet]
[ActionName(nameof(GetByParticipant))]
[ExactQueryParam("participantId", "participantType", "programName")]
public async Task<IActionResult> GetByParticipant([FromQuery]string participantId, [FromQuery]string participantType, [FromQuery]string programName)
{
}

[HttpGet]
[ActionName(nameof(GetByProgram))]
[ExactQueryParam("programName")]
public async Task<IActionResult> GetByProgram([FromQuery]string programName)
{
}
公共类ExactQueryParamAttribute:属性,IActionConstraint
{
私有只读字符串[]键;
公共ExactQueryParamAttribute(参数字符串[]键)
{
this.keys=keys;
}
公共整数顺序=>0;
公共bool Accept(ActionConstraintContext上下文)
{
var query=context.RouteContext.HttpContext.Request.query;
返回query.Count==keys.Length&&keys.All(key=>query.ContainsKey(key));
}
}
[HttpGet]
[ActionName(nameof(GetByParticipant))]
[ExactQueryParam(“participantId”、“participantType”、“programName”)]
公共异步任务GetByParticipant([FromQuery]string participantId,[FromQuery]string participantType,[FromQuery]string programName)
{
}
[HttpGet]
[ActionName(nameof(GetByProgram))]
[ExactQueryParam(“程序名”)]
公共异步任务GetByProgram([FromQuery]字符串程序名)
{
}

我花了一整天的时间来尝试这个和Andrew Radford的解决方案,这太完美了

[HttpGet]
[ExactQueryParam("active")]
public IEnumerable<UserSelectAllSprocResult.DataRow> GetAll(
  [FromQuery] bool active)
{
  return ...
}

[HttpGet]
[ExactQueryParam("active", "companyId")]
public IEnumerable<UserSelectAllByCompanySprocResult.DataRow> GetByCompanyId(
  [FromQuery] bool active, [FromQuery] int companyId)
{
  return ...;
}
[HttpGet]
[ExactQueryParam(“活动”)]
公共IEnumerable GetAll(
[FromQuery]布尔激活)
{
返回。。。
}
[HttpGet]
[ExactQueryParam(“活动”、“公司ID”)]
公共IEnumerable GetByCompanyId(
[FromQuery]布尔激活,[FromQuery]公司ID)
{
返回。。。;
}

使用from查询时,您需要唯一区分操作的路径,否则您将得到不明确的操作异常。原因是
api/action?participantId=1和participantType=2
api/action?programName=x
是相同的,区分操作是我在这里可以找到的常见建议。但我觉得这不是一个基于资源的适当休息,例如,
GET-api/terms/?cond=a
GET-api/terms?cond=b
其中
api/terms
是术语资源。想知道是否有办法定制ASP.NET核心以模仿以前的Web apibehavior@abatishchev在提供的更新中,您的想法是什么。@abatishchev关键是两个操作都使用了相同的
programName
,否则您可以尝试
[FromRoute]
属性。在上也询问了此问题