asp.net mvc / web api 2 - 接受 JSON 对象数组的控制器

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

我已经在这个问题上研究了一整天,我在 post 之后阅读了 post,但我仍然卡住了。我正在尝试为我们的网络部门开发一个 Intranet 服务目录。我希望能够将 JSON 对象数组发送到服务器,每个对象都是订单中的一个项目。我很乐意使用 MVC 或 Web API 控制器来执行此操作。到目前为止,它主要是一个 MVC 项目。

我的ajax电话:

$.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!");
        }
    });

我正在生成的 JSON 请求(来自 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"
        }
    ]
}

订单class:

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

    }

订单项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; }

    }

我尝试构建 MVC 和 Web Api 2 控制器以在数据库中获取此信息。我的 MVC 控制器总是将 ObjectItem JSON 视为 null,而 Web Api 2 控制器无法将数组转换为列表。我现在脑子坏了。

如果有人能告诉我创建我正在寻找的控制器的方法,我将不胜感激。

编辑

目前我正在使用自动生成的 Web API 2 控制器

// 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);
        }

编辑 2

下面是一个基于 Immersive 提示的 MVC 控制器。我内置了一些 JSON 响应,这样我就可以尝试查看发生了什么。 ModelState 无效,因此我返回最后一个 return 响应,它显示一个空数组。这基本上与我尝试过的任何 MVC 控制器遇到的问题相同:none 它们对传入的 JSON 数据做任何事情。

编辑 3

根据 Immersive 的提示,我对 API 控制器有了一些了解。这回退了它无法反序列化数组的错误,因为它需要一个 JSON 数组...我不知道为什么我的不合格。

[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);
    }

编辑 4

这是一个基于 Thufir 输入的 MVC 控制器,但是模型状态总是显示无效。我的 JSON 在 JSONlint 结账。我用 'pretty' 版本 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);
        }

首先,我会在这里检查您的 JSON 是否有效:http://jsonlint.com/

其次,尝试替换此行:

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

有了这个:

public ActionResult Create(Order model)

更新 1:您应该检查 JSON.Stringify 实际输出的内容,我不太清楚您是如何将那个对象放在一起的,因此可能值得检查一下。我有一种预感,这里的大部分问题都在 JavaScript 中。

更新 2:通常在使用 JSON.Stringify 之前,我会像这样创建我的对象(用循环或其他东西填充数组):

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

然后在我的 AJAX 调用中简单地写下:

data: JSON.Stringify(myObject)

以下是我喜欢将对象放在一起并对其进行字符串化的方式:

http://jsfiddle.net/4q2gx15c/

以下是如何使用输入数据作为 ApiController 执行此操作,如果需要,您应该能够转换为视图。

保持您的数据类不变,将 Action 更改为 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;
    }
}

不确定为什么要回显数据,但将其转换为列表会发回。

Fiddler 请求:

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 响应:

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

更新 1

我没有 ajax 设置和安装,但这是我的 java 脚本。我认为您需要删除 JSON.stringify 调用周围的字符串以仅传递 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));