Search code examples
.net-corerazorasp.net-core-mvc

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....

This works fine with a 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:

[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:

[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.

Is there some way that I can combine this into a single route?

This is for a .net core 5.0 site....

Example of how I am posting to the endpoint from 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!


Solution

  • 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.

    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.

    $.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 });
        }