如何使用JSON,jQuery将复杂对象数组发布到ASP.NET MVC Controller?


92

我当前的代码如下所示。如何将数组传递给控制器​​,并且控制器动作必须接受哪种参数?

function getplaceholders() {
    var placeholders = $('.ui-sortable');
    var result = new Array();
    placeholders.each(function() {
        var ph = $(this).attr('id');
        var sections = $(this).find('.sort');
        var section;

        sections.each(function(i, item) {
            var sid = $(item).attr('id');

            result.push({ 'SectionId': sid, 'Placeholder': ph, 'Position': i });
        });
    });
    alert(result.toString());
    $.post(
        '/portal/Designer.mvc/SaveOrUpdate',
        result,
        function(data) {
            alert(data.Result);
        }, "json");
};

我的控制器动作方法看起来像

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)

Answers:


84

我找到了解决方案。我使用了Steve Gentile,jQuery和ASP.NET MVC的解决方案-将JSON发送到Action-Revisited

我的ASP.NET MVC视图代码如下所示:

function getplaceholders() {
        var placeholders = $('.ui-sortable');
        var results = new Array();
        placeholders.each(function() {
            var ph = $(this).attr('id');
            var sections = $(this).find('.sort');
            var section;

            sections.each(function(i, item) {
                var sid = $(item).attr('id');
                var o = { 'SectionId': sid, 'Placeholder': ph, 'Position': i };
                results.push(o);
            });
        });
        var postData = { widgets: results };
        var widgets = results;
        $.ajax({
            url: '/portal/Designer.mvc/SaveOrUpdate',
            type: 'POST',
            dataType: 'json',
            data: $.toJSON(widgets),
            contentType: 'application/json; charset=utf-8',
            success: function(result) {
                alert(result.Result);
            }
        });
    };

并且我的控制器动作装饰有一个自定义属性

[JsonFilter(Param = "widgets", JsonDataType = typeof(List<PageDesignWidget>))]
public JsonResult SaveOrUpdate(List<PageDesignWidget> widgets

可在此处找到自定义属性的代码(该链接现在已断开)。

由于链接断开,因此这是JsonFilterAttribute的代码

public class JsonFilter : ActionFilterAttribute
{
    public string Param { get; set; }
    public Type JsonDataType { get; set; }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
        {
            string inputContent;
            using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
            {
                inputContent = sr.ReadToEnd();
            }
            var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
            filterContext.ActionParameters[Param] = result;
        }
    }
}

JsonConvert.DeserializeObject来自Json.NET

链接:使用Json.NET序列化和反序列化JSON


看起来很棒-博客文章和自定义属性代码链接不再起作用-您可以重新发布吗?
littlechris 2010年

4
此解决方案需要在客户端和服务器端进行更改。我知道您很早以前就需要这样做,但是我也可以提供一个不同方法的链接,该方法使用一个简单的jQuery插件,该插件可以将任何Javascript对象转换为默认模型绑定程序可以理解并将模型绑定到参数的形式。无需过滤器。erraticdev.blogspot.com/2010/12/...我不知道你是怎么解决验证错误,但我有一个解决方案,以及:erraticdev.blogspot.com/2010/11/...
罗伯特Koritnik

3
能否提供JavaScriptConvert.DeserializeObject的来源/来源?
Matthieu

它是Newtonsoft Json库-如果您打开nuget软件包管理器并在Newtonsoft上搜索,它将为您显示(现在是2016年)。现在也许很明显,但是万一有人想知道。
罗布·萨德勒

22

动作筛选器,jQuery字符串化,令人毛骨悚然...

彼得,此功能是MVC固有的。这就是使MVC如此出色的原因之一。

$.post('SomeController/Batch', { 'ids': ['1', '2', '3']}, function (r) {
   ...
});

在行动中

[HttpPost]
public ActionResult Batch(string[] ids)
{
}

奇迹般有效:

在此处输入图片说明

如果您使用的是jQuery 1.4+,则需要研究设置传统模式:

jQuery.ajaxSettings.traditional = true;

如此处所述:http : //www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

这甚至适用于复杂的对象。如果您有兴趣,则应该查看有关模型绑定的MVC文档:http : //msdn.microsoft.com/zh-cn/library/dd410405.aspx


1
您可能是对的,但是JSON模型资料夹是MVC3的新增功能,并且在2008年不支持此功能时提出了此问题。在您的回答中值得一提。
Piotr Owsiak

3
这是如何传递一组复杂对象的示例?
DuckMaestro 2012年

不是,但是该示例仍然适用(MVC 3+)。只要您的参数名称与您期望的模型相匹配,就不会有任何问题。
J. Mitchell

此处的关键是使用方法参数名称(“ ids”)创建JSON对象,然后将复杂对象的数组放入其中。另外,将第三个参数设置为“ true”,您将使用传统模式。
redwards510

11

在中.NET4.5MVC 5不需要小部件。

Javascript:

JS中的对象: 在此处输入图片说明

确实发布的机制。

    $('.button-green-large').click(function() {
        $.ajax({
            url: 'Quote',
            type: "POST",
            dataType: "json",
            data: JSON.stringify(document.selectedProduct),
            contentType: 'application/json; charset=utf-8',
        });
    });

C#

对象:

public class WillsQuoteViewModel
{
    public string Product { get; set; }

    public List<ClaimedFee> ClaimedFees { get; set; }
}

public partial class ClaimedFee //Generated by EF6
{
    public long Id { get; set; }
    public long JourneyId { get; set; }
    public string Title { get; set; }
    public decimal Net { get; set; }
    public decimal Vat { get; set; }
    public string Type { get; set; }

    public virtual Journey Journey { get; set; }
}

控制器:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Quote(WillsQuoteViewModel data)
{
....
}

收到的对象:

在此处输入图片说明

希望这可以节省您一些时间。


8

对于使用ASP.NET MVC的REST API的后半部分,它同时讲JSON和纯XML并引用:

现在,我们需要接受通过HTTP POST传递的JSON和XML有效负载。有时您的客户可能想要一次上传一个对象集合以进行批处理。因此,他们可以使用JSON或XML格式上传对象。ASP.NET MVC中没有本机支持,无法自动分析发布的JSON或XML并自动映射到Action参数。所以,我写了一个过滤器来做到这一点。”

然后,他实现了一个动作过滤器,该动作过滤器将JSON映射到具有显示代码的C#对象。


我只是在写我的答案。但是我还是会发布它;-)
JSC

7

首先下载此JavaScript代码JSON2.js,它将帮助我们将对象序列化为字符串。

在我的示例中,我通过Ajax 发布了jqGrid的行:

    var commissions = new Array();
    // Do several row data and do some push. In this example is just one push.
    var rowData = $(GRID_AGENTS).getRowData(ids[i]);
    commissions.push(rowData);
    $.ajax({
        type: "POST",
        traditional: true,
        url: '<%= Url.Content("~/") %>' + AREA + CONTROLLER + 'SubmitCommissions',
        async: true,
        data: JSON.stringify(commissions),
        dataType: "json",
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            if (data.Result) {
                jQuery(GRID_AGENTS).trigger('reloadGrid');
            }
            else {
                jAlert("A problem ocurred during updating", "Commissions Report");
            }
        }
    });

现在在控制器上:

    [HttpPost]
    [JsonFilter(Param = "commissions", JsonDataType = typeof(List<CommissionsJs>))]
    public ActionResult SubmitCommissions(List<CommissionsJs> commissions)
    {
        var result = dosomething(commissions);
        var jsonData = new
        {
            Result = true,
            Message = "Success"
        };
        if (result < 1)
        {
            jsonData = new
            {
                Result = false,
                Message = "Problem"
            };
        }
        return Json(jsonData);
    }

创建一个JsonFilter类(感谢JSC参考)。

    public class JsonFilter : ActionFilterAttribute
    {
        public string Param { get; set; }
        public Type JsonDataType { get; set; }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
            {
                string inputContent;
                using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
                {
                    inputContent = sr.ReadToEnd();
                }
                var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
                filterContext.ActionParameters[Param] = result;
            }
        }
    }

创建另一个类,以便过滤器可以将JSON字符串解析为实际的可操作对象:此类comissionsJS是jqGrid的所有行。

    public class CommissionsJs
    {
        public string Amount { get; set; }

        public string CheckNumber { get; set; }

        public string Contract { get; set; }
        public string DatePayed { get; set; }
        public string DealerName { get; set; }
        public string ID { get; set; }
        public string IdAgentPayment { get; set; }
        public string Notes { get; set; }
        public string PaymentMethodName { get; set; }
        public string RowNumber { get; set; }
        public string AgentId { get; set; }
    }

我希望该示例有助于说明如何发布复杂的对象。


0

哦,我的上帝。不需要做任何特别的事情。仅在您的帖子部分中执行以下操作:

    $.post(yourURL,{ '': results})(function(e){ ...}

在服务器中使用以下命令:

   public ActionResult MethodName(List<yourViewModel> model){...}

该链接帮助您完成...


-1
    [HttpPost]
    public bool parseAllDocs([FromBody] IList<docObject> data)
    {
        // do stuff

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.