在 .net 核心控制器中使用相同的路由处理 GET 和 POST 请求

Handle both GET and POST request with same route in .net core controller

我正在尝试在同一控制器中使用相同的路由处理 GET 和 POST,因为我有一些其他调用,数据可能使用 GET 或 POST 来调用相同的端点....

这适用于 GET:

[Produces("application/json")]
[ApiController]
public class AccountController : ControllerBase
{
    [HttpGet("GetAccount")]
    [Route("api/accounts/GetAccount")]
    public string GetAccount(string accountID)
    {
        return "echoing accountID: " + accountID;
    }
}

这适用于 POST:

[Produces("application/json")]
[ApiController]
public class AccountController : ControllerBase
{
    [HttpPost("GetAccount")]
    [Route("api/accounts/GetAccount")]
    public string GetAccount([FromForm] string accountID)
    {
        return "echoing accountID: " + accountID;
    }
}

但这不是 return 来自 POST 的值:

[Produces("application/json")]
[ApiController]
public class AccountController : ControllerBase
{
    [HttpPost("GetAccount"),HttpGet("GetAccount")]
    [Route("api/accounts/GetAccount")]
    public string GetAccount(string accountID)
    {
        // accountID is NULL when doing a POST, but is correct for a GET...
        return "echoing accountID: " + accountID;
    }
}

在上面的示例中,GET 请求工作正常,但是在执行 POST 时,参数 accountID 为 NULL,因为我已经删除了 [FromForm] 以使其与获取。

有什么方法可以将其组合成一条路线吗?

这是 .net core 5.0 站点....

我如何从 javascript 发布到端点的示例:

$.ajax({
   url: '/api/accounts/GetAccount',
   data: {
      accountID: 'abcdefg'
   },
   type: 'POST',
   dataType: 'JSON',
   contentType: "application/x-www-form-urlencoded; charset=UTF-8" 
})
   .done(function (result) {
      // verified that the result is NULL
      console.log(result);
   })
   .fail(function () {
      alert("ERROR");;
   })
   .always(function () {
      alert("DONE");
   });

这是我完整的启动文件(以防我没有正确注册的东西):

public class Startup
{
   public Startup(IConfiguration configuration)
   {
      Configuration = configuration;
   }

   public IConfiguration Configuration { get; }

   public void ConfigureServices(IServiceCollection services)
   {
      services.AddSession();
      services.AddHttpContextAccessor();
      services.AddRazorPages();
      services.AddControllers();
      services.AddControllers().AddNewtonsoftJson();
      services.AddControllersWithViews();
   }

   public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
   {
      app.UseSession();
      app.UseExceptionHandler("/Error");
      app.UseHsts();
      app.UseHttpsRedirection();
      app.UseStaticFiles();
      app.UseRouting();
      app.UseAuthentication();
      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
         endpoints.MapRazorPages();
         endpoints.MapControllers();
      });
    }
}

谢谢!

您可以尝试如下更改代码:

    [HttpPost("GetAccount"), HttpGet("GetAccount")]
    [Route("api/accounts/GetAccount")]
    public string GetAccount()        
    {
        if ("GET" == HttpContext.Request.Method)
        {
            //if your `accountID` is fromquery in your get method.
            string accountID = HttpContext.Request.Query["accountID"];
            return "echoing accountID: " + accountID;
        }

        else if ("POST" == HttpContext.Request.Method)
        {
            string accountID = HttpContext.Request.Form["accountID"];
            return "echoing accountID: " + accountID;
        }
        else
        {
            return "error";
        }
    }

另外,我觉得你的代码可能没有问题。发出 post 方法时,您应该检查您的 accountID 参数。

更新

api控制器的默认属性是[FromBody],所以你必须指定你不想指定的source.If为[FromForm],你可以通过querystring传递数据。

$.ajax({
            url: '/api/values/GetAccount?accountID=abcdefg',
            type: 'POST',
            dataType: 'JSON',
            contentType: "application/x-www-form-urlencoded; charset=UTF-8"
        })
            .done(function (result) {
                // verified that the result is NULL
                console.log(result.message);
            })
            .fail(function () {
                alert("ERROR");;
            })
            .always(function () {
                alert("DONE");
            });
    });

动作:

    [HttpPost("GetAccount"), HttpGet("GetAccount")]
    [Route("api/accounts/GetAccount")]
    public IActionResult GetAccount(string accountID)
    {
        string message = "echoing accountID: " + accountID;
        // accountID is NULL when doing a POST, but is correct for a GET...
        return new JsonResult(new { message = message });
    }

您是否尝试过创建两个单独的函数。一个用于 GET,另一个用于 POST? 您仍然可以将 Route 属性设置为相同,但它将是来自消费者的 HTTP 方法,它将确定将调用哪个方法。

此外,您需要使用 [FromBody] 属性来访问随请求发送的任何负载。

[Produces("application/json")]
[ApiController]
public class AccountController : ControllerBase
{
    [HttpGet]
    [Route("api/accounts/GetAccount")]
    public string GetAccount([FromBody] request)
    {
        return "echoing accountID: " + request.accountID;
    }

    [HttpPost]
    [Route("api/accounts/GetAccount")]
    public string CreateAccount([FromBody] request)
    {
        return "echoing accountID: " + request.accountID;
    }
}

编辑

您可能需要为您的 GET 端点使用 [FromQuery],为您的 POST 端点使用 [FromBody]

然后对于您的 GET,您的 URL 将使用查询参数而不是数据负载。 例如/api/accounts/GetAccount?accountID=12345

[Produces("application/json")]
[ApiController]
public class AccountController : ControllerBase
{
    [HttpGet]
    [Route("api/accounts/GetAccount")]
    public string GetAccount([FromQuery] request)
    {
        return "echoing accountID: " + request.accountID;
    }

    [HttpPost]
    [Route("api/accounts/GetAccount")]
    public string CreateAccount([FromBody] request)
    {
        return "echoing accountID: " + request.accountID;
    }
}