根据查询参数值将 HTTP 请求映射/路由到端点? asp.net核心3.x
Map / Route HTTP Request to endpoint based on query parameter value? asp.net core 3.x
我有一个客户端需要使用 rest HttpGet 调用为多个请求访问相同的基本端点 url,每个请求都具有唯一的查询参数和值。我需要为每个请求映射的函数将由 "request" 查询参数提供的值决定。是否可以在 app.UseEndpoints()、端点函数的属性或类似的简单解决方案中执行此操作?
我对这部分有点陌生,文档中没有这方面的示例。到目前为止我所拥有的(不起作用):
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "test1",
pattern: "serviceapi",
constraints: new { request = "test1" }, //map action if param "request" value is "test1"?
defaults: new { controller = "ServiceApi", action = "TestRequest1" }
);
endpoints.MapControllerRoute(
name: "test2",
pattern: "serviceapi",
constraints: new { request = "test2" }, //map action if param "request" value is "test2"?
defaults: new { controller = "ServiceApi", action = "TestRequest2" }
);
});
我想要的是当我使用邮递员向“{{url}}/api/serviceapi/?request=test1&uniqueparam1=foo", 它运行我的 ServiceApi.TestRequest1()
中的代码
[Route("api/[controller]")]
ServiceApiController.cs
[HttpGet]
public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
{
return Ok($"TestRequest1: {request} - {uniqueparam1}");
}
[HttpGet]
public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
{
return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
}
我目前使用此代码得到的错误是两个函数都是候选函数:"Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints."
谢谢!
------ 更新 ------
多亏了 Rena 的回答,我才能够正常工作:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class RequestValueConstraintAttribute : ActionMethodSelectorAttribute
{
public string RequestValue { get; private set; }
private readonly string _requestParam = "request";
public RequestValueConstraintAttribute(string requestValue)
{
RequestValue = requestValue;
}
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
{
return (string)routeContext.HttpContext.Request.Query[_requestParam] == RequestValue;
}
}
ServiceApiController.cs
[Route("api/[controller]")]
[ApiController]
public class ServiceApiController : ControllerBase
{
[RequestValueConstraint("test1")] //uses this endpoint function if param "request" value is "test1"
[HttpGet]
public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
{
return Ok($"TestRequest1: {request} - {uniqueparam1}");
}
[RequestValueConstraint("test2")] //uses this endpoint function if param "request" value is "test2"
[HttpGet]
public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
{
return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
}
}
您需要自定义 ActionMethodSelectorAttribute
:
1.QueryStringConstraintAttribute:
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
public class QueryStringConstraintAttribute : ActionMethodSelectorAttribute
{
public string ValueName { get; private set; }
public bool ValuePresent { get; private set; }
public QueryStringConstraintAttribute(string valueName,bool valuePresent)
{
this.ValueName = valueName;
this.ValuePresent = valuePresent;
}
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
{
var value = routeContext.HttpContext.Request.Query[this.ValueName];
if(this.ValuePresent)
{
return !StringValues.IsNullOrEmpty(value);
}
return StringValues.IsNullOrEmpty(value);
}
}
2.Controller:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : Controller
{
[QueryStringConstraint("uniqueparam1", true)]
[QueryStringConstraint("uniqueparam2", false)]
[HttpGet]
public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
{
return Ok($"TestRequest1: {request} - {uniqueparam1}");
}
[QueryStringConstraint("uniqueparam2", true)]
[QueryStringConstraint("uniqueparam1", false)]
[HttpGet]
public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
{
return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
}
}
3.Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
参考:
我有一个客户端需要使用 rest HttpGet 调用为多个请求访问相同的基本端点 url,每个请求都具有唯一的查询参数和值。我需要为每个请求映射的函数将由 "request" 查询参数提供的值决定。是否可以在 app.UseEndpoints()、端点函数的属性或类似的简单解决方案中执行此操作?
我对这部分有点陌生,文档中没有这方面的示例。到目前为止我所拥有的(不起作用):
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "test1",
pattern: "serviceapi",
constraints: new { request = "test1" }, //map action if param "request" value is "test1"?
defaults: new { controller = "ServiceApi", action = "TestRequest1" }
);
endpoints.MapControllerRoute(
name: "test2",
pattern: "serviceapi",
constraints: new { request = "test2" }, //map action if param "request" value is "test2"?
defaults: new { controller = "ServiceApi", action = "TestRequest2" }
);
});
我想要的是当我使用邮递员向“{{url}}/api/serviceapi/?request=test1&uniqueparam1=foo", 它运行我的 ServiceApi.TestRequest1()
中的代码[Route("api/[controller]")]
ServiceApiController.cs
[HttpGet]
public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
{
return Ok($"TestRequest1: {request} - {uniqueparam1}");
}
[HttpGet]
public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
{
return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
}
我目前使用此代码得到的错误是两个函数都是候选函数:"Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints."
谢谢!
------ 更新 ------
多亏了 Rena 的回答,我才能够正常工作:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class RequestValueConstraintAttribute : ActionMethodSelectorAttribute
{
public string RequestValue { get; private set; }
private readonly string _requestParam = "request";
public RequestValueConstraintAttribute(string requestValue)
{
RequestValue = requestValue;
}
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
{
return (string)routeContext.HttpContext.Request.Query[_requestParam] == RequestValue;
}
}
ServiceApiController.cs
[Route("api/[controller]")]
[ApiController]
public class ServiceApiController : ControllerBase
{
[RequestValueConstraint("test1")] //uses this endpoint function if param "request" value is "test1"
[HttpGet]
public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
{
return Ok($"TestRequest1: {request} - {uniqueparam1}");
}
[RequestValueConstraint("test2")] //uses this endpoint function if param "request" value is "test2"
[HttpGet]
public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
{
return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
}
}
您需要自定义 ActionMethodSelectorAttribute
:
1.QueryStringConstraintAttribute:
[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
public class QueryStringConstraintAttribute : ActionMethodSelectorAttribute
{
public string ValueName { get; private set; }
public bool ValuePresent { get; private set; }
public QueryStringConstraintAttribute(string valueName,bool valuePresent)
{
this.ValueName = valueName;
this.ValuePresent = valuePresent;
}
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
{
var value = routeContext.HttpContext.Request.Query[this.ValueName];
if(this.ValuePresent)
{
return !StringValues.IsNullOrEmpty(value);
}
return StringValues.IsNullOrEmpty(value);
}
}
2.Controller:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : Controller
{
[QueryStringConstraint("uniqueparam1", true)]
[QueryStringConstraint("uniqueparam2", false)]
[HttpGet]
public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
{
return Ok($"TestRequest1: {request} - {uniqueparam1}");
}
[QueryStringConstraint("uniqueparam2", true)]
[QueryStringConstraint("uniqueparam1", false)]
[HttpGet]
public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
{
return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
}
}
3.Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
参考: