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}),