简体   繁体   English

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

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

I am trying to handle both the GET and the POST in the same controller with the same route, as I have certain rest calls that the data may use a GET or a POST to call the same endpoint....我正在尝试使用相同的路由在同一个 controller 中处理 GET 和 POST,因为我有某些 rest 调用,数据可能使用 GET 或 POST 来调用相同的端点....

This works fine with a GET:这适用于 GET:

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

And this works for POST:这适用于 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;
    }
}

But this does not return the values from a POST:但这不会从 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;
    }
}

In the above example, a GET request works fine, but when doing a POST, the parameter accountID is NULL, because I have removed the [FromForm] in order to make it work with a GET.在上面的示例中,GET 请求工作正常,但在执行 POST 时,参数 accountID 为 NULL,因为我删除了[FromForm]以使其与 GET 一起使用。

Is there some way that I can combine this into a single route?有什么方法可以将它组合成一条路线吗?

This is for a .net core 5.0 site....这是针对 .net 核心 5.0 站点的....

Example of how I am posting to the endpoint from javascript:我如何从 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");
   });

And here is my complete Startup file (in case I don't have something registered correctly):这是我完整的启动文件(以防我没有正确注册):

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();
      });
    }
}

Thanks!谢谢!

You can try to change your code like below:您可以尝试更改您的代码,如下所示:

    [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";
        }
    }

In addition, I think there may be no problem with your code.另外,我认为您的代码可能没有问题。 When issuing the post method, you should check your accountID parameter.发出 post 方法时,您应该检查您的 accountID 参数。

Update更新

The default attribute of the api controller is [FromBody], so you must specify the source.If you don't want to specify as [FromForm], you can pass data through querystring. api controller的默认属性是[FromBody],所以必须指定源。如果不想指定为[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");
            });
    });

Action:行动:

    [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 });
    }

Have you tried to create two separate functions.您是否尝试过创建两个单独的功能。 One for GET and the other for POST?一个用于 GET,另一个用于 POST? You can still set the Route attribute the same but it will be the HTTP method which from the consumer which will determine which method will be invoked.您仍然可以将Route属性设置为相同,但它将是 HTTP 方法,该方法来自消费者,它将确定将调用哪个方法。

Also, you need to use the [FromBody] attribute to access any payload that is sent with the request.此外,您需要使用[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;
    }
}

EDIT编辑

You may need to use [FromQuery] for your GET endpoint and [FromBody] for your POST endpoint.您可能需要将[FromQuery]用于 GET 端点,将[FromBody]用于 POST 端点。

Then for your GET, your URL will use query parameters instead of a data payload.然后对于您的 GET,您的 URL 将使用查询参数而不是数据有效负载。 eg /api/accounts/GetAccount?accountID=12345例如/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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM