如何在 ASP.NET 内核中向一个 get 方法传递多个参数

如何在 MVC 6控制器中传入多个参数来获取方法。例如,我希望能够有如下的内容。

[Route("api/[controller]")]
public class PersonController : Controller
{
public string Get(int id)
{
}


public string Get(string firstName, string lastName)
{


}


public string Get(string firstName, string lastName, string address)
{


}
}

所以我可以问。

api/person?id=1
api/person?firstName=john&lastName=doe
api/person?firstName=john&lastName=doe&address=streetA
451946 次浏览

要解析 URL 中的搜索参数,您需要用 [FromQuery]注释控制器方法参数,例如:

[Route("api/person")]
public class PersonController : Controller
{
[HttpGet]
public string GetById([FromQuery]int id)
{


}


[HttpGet]
public string GetByName([FromQuery]string firstName, [FromQuery]string lastName)
{


}


[HttpGet]
public string GetByNameAndAddress([FromQuery]string firstName, [FromQuery]string lastName, [FromQuery]string address)
{


}
}

为什么不只使用一个控制器操作呢?

public string Get(int? id, string firstName, string lastName, string address)
{
if (id.HasValue)
GetById(id);
else if (string.IsNullOrEmpty(address))
GetByName(firstName, lastName);
else
GetByNameAddress(firstName, lastName, address);
}

另一种选择是使用属性路由,但是之后需要使用不同的 URL 格式:

//api/person/byId?id=1
[HttpGet("byId")]
public string Get(int id)
{
}


//api/person/byName?firstName=a&lastName=b
[HttpGet("byName")]
public string Get(string firstName, string lastName, string address)
{
}

你也可以这样做:

// GET api/user/firstname/lastname/address
[HttpGet("{firstName}/{lastName}/{address}")]
public string GetQuery(string id, string firstName, string lastName, string address)
{
return $"{firstName}:{lastName}:{address}";
}

注意 : 请参考 metalheartMark Hughes的答案,找到可能更好的方法。

enter image description here

NB-我删除了 FromURI。我仍然可以从 URL 中传递值并得到结果。如果有人知道使用 from muri 的 benfits,请让我知道

为了增加一些关于重载的更多细节,这里是一个总结。ApiController中的注释显示了每个 GET查询将调用哪个操作:

public class ValuesController : ApiController
{
// EXPLANATION: See the view for the buttons which call these WebApi actions. For WebApi controllers,
//          there can only be one action for a given HTTP verb (GET, POST, etc) which has the same method signature, (even if the param names differ) so
//          you can't have Get(string height) and Get(string width), but you can have Get(int height) and Get(string width).
//          It isn't a particularly good idea to do that, but it is true. The key names in the query string must match the
//          parameter names in the action, and the match is NOT case sensitive. This demo app allows you to test each of these
//          rules, as follows:
//
// When you send an HTTP GET request with no parameters (/api/values) then the Get() action will be called.
// When you send an HTTP GET request with a height parameter (/api/values?height=5) then the Get(int height) action will be called.
// When you send an HTTP GET request with a width parameter (/api/values?width=8) then the Get(string width) action will be called.
// When you send an HTTP GET request with height and width parameters (/api/values?height=3&width=7) then the
//          Get(string height, string width) action will be called.
// When you send an HTTP GET request with a depth parameter (/api/values?depth=2) then the Get() action will be called
//          and the depth parameter will be obtained from Request.GetQueryNameValuePairs().
// When you send an HTTP GET request with height and depth parameters (/api/values?height=4&depth=5) then the Get(int height)
//          action will be called, and the depth parameter would need to be obtained from Request.GetQueryNameValuePairs().
// When you send an HTTP GET request with width and depth parameters (/api/values?width=3&depth=5) then the Get(string width)
//          action will be called, and the depth parameter would need to be obtained from Request.GetQueryNameValuePairs().
// When you send an HTTP GET request with height, width and depth parameters (/api/values?height=7&width=2&depth=9) then the
//          Get(string height, string width) action will be called, and the depth parameter would need to be obtained from
//          Request.GetQueryNameValuePairs().
// When you send an HTTP GET request with a width parameter, but with the first letter of the parameter capitalized (/api/values?Width=8)
//          then the Get(string width) action will be called because the case does NOT matter.
// NOTE: If you were to uncomment the Get(string height) action below, then you would get an error about there already being
//          a member named Get with the same parameter types. The same goes for Get(int id).
//
// ANOTHER NOTE: Using the nullable operator (e.g. string? paramName) you can make optional parameters. It would work better to
//          demonstrate this in another ApiController, since using nullable params and having a lot of signatures is a recipe
//          for confusion.


// GET api/values
public IEnumerable<string> Get()
{
return Request.GetQueryNameValuePairs().Select(pair => "Get() => " + pair.Key + ": " + pair.Value);
//return new string[] { "value1", "value2" };
}


//// GET api/values/5
//public IEnumerable<string> Get(int id)
//{
//    return new string[] { "Get(height) => height: " + id };
//}


// GET api/values?height=5
public IEnumerable<string> Get(int height) // int id)
{
return new string[] { "Get(height) => height: " + height };
}


// GET api/values?height=3
public IEnumerable<string> Get(string height)
{
return new string[] { "Get(height) => height: " + height };
}


//// GET api/values?width=3
//public IEnumerable<string> Get(string width)
//{
//    return new string[] { "Get(width) => width: " + width };
//}


// GET api/values?height=4&width=3
public IEnumerable<string> Get(string height, string width)
{
return new string[] { "Get(height, width) => height: " + height + ", width: " + width };
}
}

如果你想知道的话,你只需要一个单一的路线:

    config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

你可以用这个 MVC 视图或者类似的东西来测试它。是的,我知道你不应该把 JavaScript 和标记混在一起,我也没有像你通常那样使用 bootstrap,但是这只是演示的目的。

<div class="jumbotron">
<h1>Multiple parameters test</h1>
<p class="lead">Click a link below, which will send an HTTP GET request with parameters to a WebAPI controller.</p>
</div>
<script language="javascript">
function passNothing() {
$.get("/api/values", function (data) { alert(data); });
}


function passHeight(height) {
$.get("/api/values?height=" + height, function (data) { alert(data); });
}


function passWidth(width) {
$.get("/api/values?width=" + width, function (data) { alert(data); });
}


function passHeightAndWidth(height, width) {
$.get("/api/values?height=" + height + "&width=" + width, function (data) { alert(data); });
}


function passDepth(depth) {
$.get("/api/values?depth=" + depth, function (data) { alert(data); });
}


function passHeightAndDepth(height, depth) {
$.get("/api/values?height=" + height + "&depth=" + depth, function (data) { alert(data); });
}


function passWidthAndDepth(width, depth) {
$.get("/api/values?width=" + width + "&depth=" + depth, function (data) { alert(data); });
}


function passHeightWidthAndDepth(height, width, depth) {
$.get("/api/values?height=" + height + "&width=" + width + "&depth=" + depth, function (data) { alert(data); });
}


function passWidthWithPascalCase(width) {
$.get("/api/values?Width=" + width, function (data) { alert(data); });
}
</script>
<div class="row">
<button class="btn" onclick="passNothing();">Pass Nothing</button>
<button class="btn" onclick="passHeight(5);">Pass Height of 5</button>
<button class="btn" onclick="passWidth(8);">Pass Width of 8</button>
<button class="btn" onclick="passHeightAndWidth(3, 7);">Pass Height of 3 and Width of 7</button>
<button class="btn" onclick="passDepth(2);">Pass Depth of 2</button>
<button class="btn" onclick="passHeightAndDepth(4, 5);">Pass Height of 4 and Depth of 5</button>
<button class="btn" onclick="passWidthAndDepth(3, 5);">Pass Width of 3 and Depth of 5</button>
<button class="btn" onclick="passHeightWidthAndDepth(7, 2, 9);">Pass Height of 7, Width of 2 and Depth of 9</button>
<button class="btn" onclick="passHeightWidthAndDepth(7, 2, 9);">Pass Height of 7, Width of 2 and Depth of 9</button>
<button class="btn" onclick="passWidthWithPascalCase(8);">Pass Width of 8, but with Pascal case</button>
</div>
    public HttpResponseMessage Get(int id,string numb)
{


using (MarketEntities entities = new MarketEntities())
{
var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
if (ent != null)
{
return Request.CreateResponse(HttpStatusCode.OK, ent);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
}
}
}

我认为最简单的方法是使用 AttributeRouting

[Route("api/YOURCONTROLLER/{paramOne}/{paramTwo}")]
public string Get(int paramOne, int paramTwo)
{
return "The [Route] with multiple params worked";
}

你可以简单地做到以下几点:

    [HttpGet]
public async Task<IActionResult> GetAsync()
{
string queryString = Request.QueryString.ToString().ToLower();


return Ok(await DoMagic.GetAuthorizationTokenAsync(new Uri($"https://someurl.com/token-endpoint{queryString}")));
}

如果需要分别访问每个元素,只需参考 Request.Query

在 web api 核心中调用带有多个参数的 get

  [ApiController]
[Route("[controller]")]
public class testController : Controller
{
    

[HttpGet]
[Route("testaction/{id:int}/{startdate}/{enddate}")]
public IEnumerable<classname> test_action(int id, string startdate, string enddate)
{


return List_classobject;
}
    

}


In web browser
https://Yourdomain/test/testaction/3/2010-09-30/2012-05-01

方法应该是这样的:

[Route("api/[controller]")]
public class PersonsController : Controller
{
[HttpGet("{id}")]
public Person Get(int id)


[HttpGet]
public Person[] Get([FromQuery] string firstName, [FromQuery] string lastName, [FromQuery] string address)
}


请注意,第二个方法返回一个对象数组,控制器名称是复数(Person 而不是 Person)。

因此,如果你想通过 id 获取资源,它会是:

api/persons/1

如果你想通过一些搜索条件(如名字等)获取对象,你可以这样搜索:

api/persons?firstName=Name&...

接下来,如果你想接受那个人的订单(例如) ,应该是这样的:

api/persons/1/orders?skip=0&take=20

和同一控制器中的方法:

    [HttpGet("{personId}/orders")]
public Orders[] Get(int personId, int skip, int take, etc..)

我建议使用一个单独的 dto 对象作为参数:

[Route("api/[controller]")]
public class PersonController : Controller
{
public string Get([FromQuery] GetPersonQueryObject request)
{
// Your code goes here
}
}


public class GetPersonQueryObject
{
public int? Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Address { get; set; }
}

Dotnet 将把字段映射到对象。

这将使通过参数变得更加容易,并将产生更加清晰的代码。

最简单的方法,

总监:

[HttpGet("empId={empId}&startDate={startDate}&endDate={endDate}")]
public IEnumerable<Validate> Get(int empId, string startDate, string endDate){}

邮递员要求:

{router}/empId=1&startDate=2020-20-20&endDate=2020-20-20

学习要点: 请求精确的模式将被控制器接受。

这招对我管用

[HttpGet("{data}/{whereList}")]
public JsonResult GetFieldsData([FromQuery]  string data, [FromQuery]  string whereList)

如果你允许,我想自己回答(我使用.NET 5 + React)

总监:

namespace MyProject.Controllers
{
[Route("[controller]")]
public class ExampleController : Controller
{
public string Get(string param1, string param2, string param3)
{
//your code here
}
}
}

反应:

fetch(`example?param1=${val1}&param2=${val2}&param3=${val3}`)