Search code examples
asp.net-web-api2asp.net-mvc-5.1

How to setup a web api controller Post method


I am changing my project to post multiple objects to my db table. The issue I am having is, after I changed the Post method I do not know how to return the created route with the Id's of the objects. I have not done this before so I believe I a correct on everything else up until that point.

 public async Task<IHttpActionResult> PostNewPurchaseOrderDetail([FromBody]IEnumerable<PurchaseOrderDetail> newPurchaseOrderDetail)
    {
        try
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            using (var context = new ApplicationDbContext())
            {
                context.PurchaseOrderDetails.AddRange(newPurchaseOrderDetail);
                await context.SaveChangesAsync();
                return CreatedAtRoute("PurchaseOrderDetailApi", new { newPurchaseOrderDetail.PurchaseOrderDetailId }, newPurchaseOrderDetail);
            }
        }
        catch (Exception ex)
        {
            return this.BadRequest(ex.Message);
        }
    }

Error Message

Error 2 'System.Collections.Generic.IEnumerable' does not contain a definition for 'PurchaseOrderDetailId' and no extension method 'PurchaseOrderDetailId' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?) C:\Development\TexasExterior\TexasExterior\apiControllers\apiPurchaseOrderDetailController.cs 58 98 TexasExterior


Solution

  • The error tells you exactly what the issue is. You variable, newPurchaseOrderDetail is an enumerable of PurchaseOrderDetail, and you're trying to reference a property of PurchaseOrderDetail directly off of it. You need to get a single item from the list before you can call the property. For example:

    return CreatedAtRoute("PurchaseOrderDetailApi", new { newPurchaseOrderDetail.First().PurchaseOrderDetailId }, newPurchaseOrderDetail);
    

    Notice the .First(). However, that would only give you the id of the first item in the collection, which is probably not what you want. I'm not sure what your CreatedAtRoute method does or how it works, but you could change the second parameter to expect a collection of ids and then pass something like:

    newPurchaseOrderDetail.Select(m => m.PurchaseOrderDetailId)
    

    Which would give you a list of ids.