Search code examples
c#asp.net-mvcasp.net-web-apiodataasp.net-web-api2

WebApi OData 4 , second POST endpoint for bulk insertion in the controller


I have a basic WebApi OData 4 controller for TEAM model which has a POST action for adding a new TEAM to the database.

    public async Task<IHttpActionResult> Post(USER_TEAMS userTeam)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        context.USER_TEAMS.Add(userTeam);
        await context.SaveChangesAsync();
        return Created(userTeam);
    }

I want to have another endpoint in that controller for bulk insertion of teams which takes a list of team objects and adds them to the database. What is the best approach in WebApi OData 4 to do that?


Solution

  • The OData spec includes a batching concept, but for this problem an OData action is a cleaner solution. The action will be bound to the Teams entity set and will accept a collection of Team entities in the request payload. (I've changed USER_TEAMS to Team in the code below.)

    Given the following simple definition of Team entity type:

    public class Team
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    First, define the action method in the same controller as your Post method.

        [HttpPost]
        public IHttpActionResult BulkAdd(ODataActionParameters parameters)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest();
            }
    
            var newTeams = (IEnumerable<Team>)parameters["NewTeams"];
    
            // Your data access layer logic goes here.
    
            return this.StatusCode(HttpStatusCode.NoContent);
        }
    

    Then declare the OData action in your Web API configuration code.

        var builder = new ODataConventionModelBuilder();
    
        builder.Namespace = "TeamService";
        builder.EntitySet<Team>("Teams");
        builder.EntityType<Team>().Collection
            .Action("BulkAdd")
            .CollectionParameter<Team>("NewTeams");
    

    Note in the above:

    • EntityTypeConfiguration<T>.Collection is necessary to bind the action to the Team entity set (vs. a single Team entity)
    • ActionConfiguration.CollectionParameter<T> is necessary to specify that the parameter is a collection (vs. a scalar)

    On the client, invoke the action as follows.

    POST http://domain/Teams/TeamService.BulkAdd
    Content-Type: application/json
    
    {"NewTeams": [{"Name": "Demons"}, {"Name": "Angels"}]}