简体   繁体   中英

asp.net mvc / web api 2 - controller to accept an array of JSON objects

I've been on this issue for a full day and I've read post after post but I'm still stuck. I'm trying to develop an intranet service catalog for our network department. I'd like to be able to send an array of JSON objects to the server, with each object being an item in the order. I would be happy doing this with either MVC or Web API controllers. It's primarily been an MVC project thus far.

My ajax call:

$.ajax({
        url: url,
        async: true,
        type: "POST",
        data: JSON.stringify({ "OrderItems": OrderItems }),
        dataType:'json',
        contentType: "application/json",
        error: function (jqXHR, textStatus, errorThrown) {
        },
        success: function (data, textStatus, jqXHR) {
            console.log("order sent!");
        }
    });

The JSON request I'm generating (from Fiddler)

{
    "OrderItems": [
        {
            "Manufacturer": "Cisco",
            "PartNumber": "WS-C3650-24PS-S",
            "Description": "Cisco Catalyst 3650 24 Port PoE 4x1G Uplink IP Base",
            "Price": "3510.00",
            "Quantity": 1,
            "TotalPrice": "3510.00"
        },
        {
            "Manufacturer": "Cisco",
            "PartNumber": "WS-C3650-48PS-S",
            "Description": "Cisco Catalyst 3650 48 Port PoE 4x1G Uplink IP Base",
            "Price": "5500.00",
            "Quantity": 1,
            "TotalPrice": "5500.00"
        }
    ]
}

The Order class:

  public class Order
    {
        public int ID { get; set; }
        public List<OrderItem> OrderItems { get; set; }

    }

The OrderItem class:

 public class OrderItem
    {
        public int ID { get; set; }
        public string Manufacturer { get; set; }
        public string PartNumber { get; set; }
        public string Description { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
        public decimal TotalPrice { get; set; }

    }

I've tried to build out both MVC and Web Api 2 controllers to get this information in a database. My MVC controller would always see the ObjectItem JSON as null, and the Web Api 2 Controller couldn't translate the array to a list. My brain is now broken.

If someone could show me the way to creating the controller I'm looking for I'd be very grateful.

EDIT

Currently I'm working with the auto-generated Web API 2 controller

// POST api/Order
        [ResponseType(typeof(Order))]
        public IHttpActionResult PostOrder(Order order)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            db.Orders.Add(order);
            db.SaveChanges();

            return CreatedAtRoute("DefaultApi", new { id = order.ID }, order);
        }

EDIT 2

Here's an MVC controller based on Immersive's hint below. I build in some JSON responses so I can try to see what's going on. The ModelState isn't valid, so I get back the last return response, which shows an empty array. This is basically the same problem I've had with any MVC controller I've tried: none of them do anything with the JSON data coming in.

EDIT 3

I've got a little movement with an API controller based on Immersive's hint. This one kicks back the error that it is unable to deserialize the array because it requires a JSON array... I have no idea why mine doesn't qualify.

[ResponseType(typeof(Order))]
    public IHttpActionResult PostOrder(List<OrderItem>orderitems)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        Order order = new Order();
        order.OrderItems = orderitems;
        db.Orders.Add(order);
        db.SaveChanges();

        return CreatedAtRoute("DefaultApi", new { id = order.ID }, order);
    }

Edit 4

Here is an MVC controller based on Thufir's input, but the model state always shows invalid. My JSON checks out at JSONlint. I updated the example above with the 'pretty' version JSONlint validated.

[HttpPost]
        public ActionResult Create(Order model)
        {
            if (ModelState.IsValid)
            {
                db.Orders.Add(model);
                db.SaveChanges();
              //  return RedirectToAction("Index");
                return Json("Valid!");
            }

            return Json("Was not valid");
            // return View(model);
        }

First, I would check if your JSON is valid here: http://jsonlint.com/

Second, try replacing this line:

public ActionResult Create([Bind(Include="ID")] List<OrderItem>OrderItems)

with this:

public ActionResult Create(Order model)

Update 1: You should check what your JSON.Stringify actually outputs, it's not exactly clear to me how you put that object together, so it may be worth checking. I have a hunch, that most of the problem here is in the JavaScript.

Update 2: Usually before using JSON.Stringify I create my object like this (Fill the array with a loop or something):

var myObject = {
    myName: 'Big Bob',
    myItems: someArrayHere
}

Then in my AJAX call simply write this:

data: JSON.Stringify(myObject)

Here is how I like to put together objects and stringify them:

http://jsfiddle.net/4q2gx15c/

Here is how to do this as an ApiController using your input data as is, you should be able to convert to a View if needed.

Keeping your data classes as is change the Action to be an array of OrderItem

public class OrderController : ApiController
{
    public Order PostOrder([FromBody] OrderItem[] orderitems)
    {
        if (orderitems != null)
        {
            Order order = new Order();
            order.OrderItems = orderitems.ToList<OrderItem>();

            return order;
        }
        return null;
    }
}

Not sure why you are echoing the data back but converting it into a list sends it back.

Fiddler request:

POST http://localhost:64719/api/Order HTTP/1.1 User-Agent: Fiddler Content-Type: application/json Host: localhost:64719 Content-Length: 615

[   {
    "ID": 1,
    "Manufacturer": "sample string 2",
    "PartNumber": "sample string 3",
    "Description": "sample string 4",
    "Price": 5.0,
    "Quantity": 6,
    "TotalPrice": 7.0   },   {
    "ID": 1,
    "Manufacturer": "sample string 2",
    "PartNumber": "sample string 3",
    "Description": "sample string 4",
    "Price": 5.0,
    "Quantity": 6,
    "TotalPrice": 7.0   },   {
    "ID": 1,
    "Manufacturer": "sample string 2",
    "PartNumber": "sample string 3",
    "Description": "sample string 4",
    "Price": 5.0,
    "Quantity": 6,
    "TotalPrice": 7.0   } ]

Fiddler response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya1xFSVAgV29ya1xRdWVzdGlvbnNcU2FtcGxlTVZDXFNhbXBsZU1WQ1xhcGlcT3JkZXI=?=
X-Powered-By: ASP.NET
Date: Wed, 24 Jun 2015 20:09:38 GMT
Content-Length: 464

{"ID":0,"OrderItems":[{"ID":1,"Manufacturer":"sample string 2","PartNumber":"sample string 3","Description":"sample string 4","Price":5.0,"Quantity":6,"TotalPrice":7.0},{"ID":1,"Manufacturer":"sample string 2","PartNumber":"sample string 3","Description":"sample string 4","Price":5.0,"Quantity":6,"TotalPrice":7.0},{"ID":1,"Manufacturer":"sample string 2","PartNumber":"sample string 3","Description":"sample string 4","Price":5.0,"Quantity":6,"TotalPrice":7.0}]}

UPDATE 1

I do not have ajax setup and install but here is my java script. I think you need to remove the string around your JSON.stringify call to only pass the ogject.

    var TestXmlhttp = new XMLHttpRequest();

    TestXmlhttp.open("POST", "http://localhost:64719/api/Order", true);
    TestXmlhttp.setRequestHeader("Content-Type", "application/json");

    TestXmlhttp.onreadystatechange = function () {
        if (TestXmlhttp != null) {
            if (TestXmlhttp.readyState == 4) {
                try {
                    alert("Good");
                }
                catch (e) {
                    alert("Bad");
                }
            }
            else {
            }
        }
    }
    TestXmlhttp.send(JSON.stringify(OrderItems));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM