【问题标题】:asp.net mvc / web api 2 - controller to accept an array of JSON objectsasp.net mvc / web api 2 - 接受 JSON 对象数组的控制器
【发布时间】:2015-06-24 17:29:36
【问题描述】:

我已经在这个问题上讨论了一整天,我已经阅读了一个又一个帖子,但我仍然卡住了。我正在尝试为我们的网络部门开发一个 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"
        }
    ]
}

订单类:

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

    }

OrderItem 类:

 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 无效,所以我返回了最后一个返回响应,它显示了一个空数组。这基本上与我尝试过的任何 MVC 控制器遇到的问题相同:它们都没有对传入的 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 签出。我使用经过验证的“漂亮”版本 JSONlint 更新了上面的示例。

[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 请求直接生成 OrderItems,但您的 MVC 需要一个 Order 对象?尝试请求一个完全成熟的Order,或者将Action 的参数类型更改为List&lt;OrderItem&gt;(特别是PostOrder(List&lt;OrderItem&gt; OrderItems))... 猜测一下=)
  • Wep API 如果您只是尝试将项目列表推送到数据库而不使用 MVC 的正常 POST 行为,则可以使用 jQuery 的 .each() 之类的东西,并将项目传递给一次使用 ajax 到控制器中的方法只是为了绑定它们。这不是最有效的方法,但可以尝试看看是否还有其他问题。 (这是不知道 UI 的样子或屏幕的作用)。
  • @Matt West 你如何生成你的 json 请求??
  • Feras - 它是一个数组,是前端生成的 JavaScript 对象的一部分。我 JSON.stringify 数组,然后将它提供给我在原始问题中的 ajax 请求。输出就是你在那里看到的。

标签: c# json asp.net-mvc asp.net-web-api2


【解决方案1】:

首先,我会在这里检查您的 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/

【讨论】:

  • 感谢 Thufir 的输入,很遗憾这也没有解决问题。
  • 你说modelstate是无效的,但是当你在它上断点时,模型是否被填充?另外,您的模型属性是否有任何属性?
  • 最终,这确实是一个 JSON 问题。我的代码中有两次 JSON.Stringify,创建了经过验证的 JSON,但 .net 无法识别。消除较早的 JSON.Stringify 解决了这个问题。
【解决方案2】:

这里是如何使用您的输入数据作为 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;
    }
}

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

提琴手请求:

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

提琴手回应:

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

【讨论】:

  • 您好,感谢您的回复。我只是为了测试目的而回显了数据。我建立了这个,但控制器只是发回“空”响应。你介意发布你的ajax请求代码吗?也许这就是我的问题所在(尽管在 Fiddler 中看起来还不错......)
  • 在我的回答中添加了 javascript。
猜你喜欢
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-28
  • 2015-03-01
  • 1970-01-01
  • 2015-10-17
相关资源
最近更新 更多