Search code examples
asp.net-web-apipostmanslackasp.net-core-2.2slack-commands

Asp.net core 2.2 web api FromForm of complex object contains only null values


Hi I am trying to build an endpoint for slack commands in asp.net core 2.2. I have a data structure representing a commandrequest from slack like so:

    public class SlackCommandDTO
    {
        [FromForm(Name = "token")]
        public string Token { get; set; }

        [FromForm(Name = "team_id")]
        public string TeamId { get; set; }

        [FromForm(Name = "team_domain")]
        public string TeamDomain { get; set; }

        [FromForm(Name = "channel_id")]
        public string ChannelId { get; set; }

        [FromForm(Name = "channel_name")]
        public string ChannelName { get; set; }

        [FromForm(Name = "user_id")]
        public string UserId { get; set; }

        [FromForm(Name = "user_name")]
        public string UserName { get; set; }

        [FromForm(Name = "command")]
        public string Command { get; set; }

        [FromForm(Name = "text")]
        public string Text { get; set; }

        [FromForm(Name = "response_url")]
        public string ResponseUrl { get; set; }

        [FromForm(Name = "trigger_id")]
        public string TriggerId { get; set; }
    }

My controller to receive data looks like this:

    [Route("api/[controller]")]
    [ApiController]
    public class CustomerServiceController : ControllerBase
    {
        // POST api/customerservice
        [HttpPost]
        public void Post([FromForm] SlackCommandDTO command)
        {
            Console.Write(command.Token);
        }
    }

my startup.cs looks like this

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

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }
    }

I have tried setting the compatability settings in startup.cs to 2.1 and 2.2.

The result is always an instance of the object that contain null in all properties.

I have tried setting the decorator to [FromBody] (not that that is supposed to work) but in that case I get 415 unsupported media type (as it should).

I have tried sending the requests with content-type x-www-form-urlencoded and form-data as well as text/plain and application/json. the latter two return 415.

I have also tried sending the request through swagger with the same result and curl both using -d keyword and -F keyword for each pair of data.

If I am missing some information please let me know, I am drawing a blank here on how to solve it so please help.

The data I am receiving is from Slack according to this article about implementing slash commands in slack. https://api.slack.com/slash-commands#responding_to_commands


Solution

  • I have solved my problem. My issue was the fundamental misunderstanding that the parameters would be bound as a single object when using the FromForm attribute when actually I was supposed to parameterize each field as a string input in the post method like so:

        [Route("api/[controller]")]
        [ApiController]
        public class CustomerServiceController : ControllerBase
        {
            // POST api/customerservice
            [HttpPost]
            public void Post([FromForm] string token, 
                [FromForm] string team_id, 
                [FromForm] string team_domain, 
                [FromForm] string channel_id, 
                [FromForm] string channel_name, 
                [FromForm] string user_id, 
                [FromForm] string user_name, 
                [FromForm] string command, 
                [FromForm] string text, 
                [FromForm] string response_url, 
                [FromForm] string trigger_id)
            {
                Console.Write(token);
            }
        }