ASP.NET Core Web API Controller 可以有多个 ControllerRoute 吗?
Can an ASP.NET Core Web API Controller have more than one ControllerRoute?
我有一个控制器,针对 API 请求进行了以下设置:
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
这对 GET
请求非常有用,但对于 POST
请求,我的参数似乎没有任何值。在前端,在 JavaScript 中,我可以在有效载荷中看到我的参数,所以我知道它们在那里。但是,我的控制器不能正确设置以接受 POST
请求。
这是我的 GET
请求有效的,而我的 POST
请求无效。我相信我的问题是我将控制器路由设置为需要 ?
并获取参数。但是,我仍然需要做 post 个请求!
GET
请求:
public ActionResult Contacts([FromQuery] String DD_INPUT)
{
//We have parameters here just in case we want to use them
IEnumerable queryResult;
String query = "Exec dbo.storedprocedure2 @DD_INPUT";
using (var connection = new SqlConnection(connectionString))
{
queryResult = connection.Query(query, new { DD_INPUT = DD_INPUT });
}
return Ok(queryResult);
}
POST
请求:
[HttpPost]
public ActionResult AddFirm([FromBody] String FIRM_NAME)
{
String query = "exec dbo.storeprocedername @FIRM_NAME";
System.Diagnostics.Debug.WriteLine("value:" + FIRM_NAME);
using (var connection = new SqlConnection(connectionString))
{
var json = connection.QuerySingle<string>(query, new { FIRM_NAME = FIRM_NAME});
return Content(json, "application/json");
}
}
POST
请求 JavaScript
axios.post(window.location.origin + '/API/AddFirm', {
FIRM_NAME: this.FirmName
}).then(response => {
this.FirmsArray = response.data;
}).catch(error => {
console.log(error.response.data.error);
});
您的配置最上面是您的服务配置,您在其中配置所有控制器和控制器中的所有端点的格式为“{controller}/{action}/{id?}”。
您不仅可以像示例中那样在 API 级别配置路由构建方式,还可以在控制器和端点级别配置路由构建方式:
即
[ApiController]
[Route("{controller}s"}
public class FirmController : ControllerBase
{
[HttpGet]
[Route("/{firmId}/contacts/{contactId}"]
public ActionResult GetContacts([FromRoute] int firmId, [FromRoute] int contactId)
{
...
}
[HttpPost]
public ActionResult AddFirm([FromBody] string firmName)
{
...
}
}
或者更好的是,添加一个 FirmModel 以添加新公司。
还请 https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design 阅读以正确设计 API。
所以,最佳解决方案是这样的(更改在代码注释中解释):
[HttpPost]
public ActionResult AddFirm(string FIRM_NAME) // Can accept value from body AND query string. If you have more firm names then simply use List<string>/IEnumable<string> to represent it. If you have more parameters you want to pass, then simply write them like this: string FIRM_NAME, int NUM_OF_EMPLYEES and so on.
{
// Why are you using class String, when you can use the string keyword that does exactlly the same thing?
String query = "exec dbo.storeprocedername @FIRM_NAME";
System.Diagnostics.Debug.WriteLine("value:" + FIRM_NAME);
using (var connection = new SqlConnection(connectionString))
{
var json = connection.QuerySingle<string>(query, new { FIRM_NAME = FIRM_NAME});
return Content(json, "application/json"); // When sending JSON answear, be aware that every parameter from object will start with lowercased letter.
}
}
如果你坚持使用 [FromBody]
标签,那么很遗憾你不得不使用模型。
如果您想在操作中使用 [frombody],则必须将数据字符串化
const json = JSON.stringify(this.FirmName);
await axios.post(window.location.origin + '/API/AddFirm', json, {
headers: {
'Content-Type': 'application/json'
}
}).then(response => {
this.FirmsArray = response.data;
}).catch(error => {
console.log(error.response.data.error);
});
我只是不确定 url 您提供的服务。通常 Api 与调用它的应用程序有不同的 url。它通常看起来像“/MyController/MyAction”。很遗憾,您没有 post 您的控制器 header。
更新
如果您需要 post 使用 [frombody] 操作的多个属性,您也需要更改您的操作
创建视图模型
public class ViewModel
{
public string FirmName {get; set;}
public string Email {get; set;}
}
动作
[HttpPost]
public ActionResult AddFirm([FromBody] ViewModel viewModel)
ajax
data: JSON.stringify({FirmName: this.FirmName, Email: this.CurrentEmail}),
我有一个控制器,针对 API 请求进行了以下设置:
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
这对 GET
请求非常有用,但对于 POST
请求,我的参数似乎没有任何值。在前端,在 JavaScript 中,我可以在有效载荷中看到我的参数,所以我知道它们在那里。但是,我的控制器不能正确设置以接受 POST
请求。
这是我的 GET
请求有效的,而我的 POST
请求无效。我相信我的问题是我将控制器路由设置为需要 ?
并获取参数。但是,我仍然需要做 post 个请求!
GET
请求:
public ActionResult Contacts([FromQuery] String DD_INPUT)
{
//We have parameters here just in case we want to use them
IEnumerable queryResult;
String query = "Exec dbo.storedprocedure2 @DD_INPUT";
using (var connection = new SqlConnection(connectionString))
{
queryResult = connection.Query(query, new { DD_INPUT = DD_INPUT });
}
return Ok(queryResult);
}
POST
请求:
[HttpPost]
public ActionResult AddFirm([FromBody] String FIRM_NAME)
{
String query = "exec dbo.storeprocedername @FIRM_NAME";
System.Diagnostics.Debug.WriteLine("value:" + FIRM_NAME);
using (var connection = new SqlConnection(connectionString))
{
var json = connection.QuerySingle<string>(query, new { FIRM_NAME = FIRM_NAME});
return Content(json, "application/json");
}
}
POST
请求 JavaScript
axios.post(window.location.origin + '/API/AddFirm', {
FIRM_NAME: this.FirmName
}).then(response => {
this.FirmsArray = response.data;
}).catch(error => {
console.log(error.response.data.error);
});
您的配置最上面是您的服务配置,您在其中配置所有控制器和控制器中的所有端点的格式为“{controller}/{action}/{id?}”。
您不仅可以像示例中那样在 API 级别配置路由构建方式,还可以在控制器和端点级别配置路由构建方式:
即
[ApiController]
[Route("{controller}s"}
public class FirmController : ControllerBase
{
[HttpGet]
[Route("/{firmId}/contacts/{contactId}"]
public ActionResult GetContacts([FromRoute] int firmId, [FromRoute] int contactId)
{
...
}
[HttpPost]
public ActionResult AddFirm([FromBody] string firmName)
{
...
}
}
或者更好的是,添加一个 FirmModel 以添加新公司。
还请 https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design 阅读以正确设计 API。
所以,最佳解决方案是这样的(更改在代码注释中解释):
[HttpPost]
public ActionResult AddFirm(string FIRM_NAME) // Can accept value from body AND query string. If you have more firm names then simply use List<string>/IEnumable<string> to represent it. If you have more parameters you want to pass, then simply write them like this: string FIRM_NAME, int NUM_OF_EMPLYEES and so on.
{
// Why are you using class String, when you can use the string keyword that does exactlly the same thing?
String query = "exec dbo.storeprocedername @FIRM_NAME";
System.Diagnostics.Debug.WriteLine("value:" + FIRM_NAME);
using (var connection = new SqlConnection(connectionString))
{
var json = connection.QuerySingle<string>(query, new { FIRM_NAME = FIRM_NAME});
return Content(json, "application/json"); // When sending JSON answear, be aware that every parameter from object will start with lowercased letter.
}
}
如果你坚持使用 [FromBody]
标签,那么很遗憾你不得不使用模型。
如果您想在操作中使用 [frombody],则必须将数据字符串化
const json = JSON.stringify(this.FirmName);
await axios.post(window.location.origin + '/API/AddFirm', json, {
headers: {
'Content-Type': 'application/json'
}
}).then(response => {
this.FirmsArray = response.data;
}).catch(error => {
console.log(error.response.data.error);
});
我只是不确定 url 您提供的服务。通常 Api 与调用它的应用程序有不同的 url。它通常看起来像“/MyController/MyAction”。很遗憾,您没有 post 您的控制器 header。
更新 如果您需要 post 使用 [frombody] 操作的多个属性,您也需要更改您的操作
创建视图模型
public class ViewModel
{
public string FirmName {get; set;}
public string Email {get; set;}
}
动作
[HttpPost]
public ActionResult AddFirm([FromBody] ViewModel viewModel)
ajax
data: JSON.stringify({FirmName: this.FirmName, Email: this.CurrentEmail}),