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?
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"}]}