【问题标题】:How to post an array of complex objects with JSON, jQuery to ASP.NET MVC Controller?如何将带有 JSON、jQuery 的复杂对象数组发布到 ASP.NET MVC 控制器?
【发布时间】:2010-09-24 03:11:32
【问题描述】:

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

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)

【问题讨论】:

    标签: c# javascript jquery asp.net-mvc json


    【解决方案1】:

    我找到了解决方案。我使用 Steve Gentile 的解决方案,jQuery and ASP.NET MVC – sending JSON to an 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
    

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

    由于链接已损坏,这是 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

    链接:Serializing and Deserializing JSON with Json.NET

    【讨论】:

    • 看起来很棒 - 博客文章和自定义属性代码链接不再起作用 - 你可以重新发布吗?
    • 此解决方案需要在客户端和服务器端进行更改。我知道你很久以前就需要这个,但我不妨提供一个不同方法的链接,它使用一个简单的 jQuery 插件,可以将任何 Javascript 对象转换为默认模型绑定器可以理解的形式,并将模型绑定到参数。不需要过滤器。 erraticdev.blogspot.com/2010/12/…我不知道你是如何解决验证错误的,但我也有一个解决方案:erraticdev.blogspot.com/2010/11/…
    • 你能给出 JavaScriptConvert.DeserializeObject 的来源/出处吗?
    • 这是 Newtonsoft Json 库 - 如果您打开 nuget 包管理器并在 Newtonsoft 上搜索,它会为您显示(现在是 2016 年)。可能现在这很明显,但以防万一有人想知道。
    【解决方案2】:

    动作过滤器、jquery stringify、bleh...

    Peter,这个功能是 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/en-us/library/dd410405.aspx

    【讨论】:

    • 您可能是对的,但 JSON 模型绑定器对 MVC3 来说是新的,并且在 2008 年不支持此问题时提出了这个问题。在您的回答中值得一提。
    • 这是一个传递复杂对象数组的例子吗?
    • 不是,但该示例仍然适用(MVC 3+)。只要您的参数名称与您期望的模型匹配,您就不会遇到任何问题。
    • 这里的关键是使用方法参数名称(“ids”)创建一个 JSON 对象,然后将复杂对象数组放入其中。此外,将第三个参数设为“true”,您将处理传统模式。
    【解决方案3】:

    .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)
    {
    ....
    }
    

    收到的对象:

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

    【讨论】:

      【解决方案4】:

      迈向Create REST API using ASP.NET MVC that speaks both JSON and plain XML的后半段,引述:

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

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

      【讨论】:

      • 我只是在写我的答案。但无论如何我都会发布它;-)
      【解决方案5】:

      首先下载这个 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; }
          }
      

      我希望这个例子有助于说明如何发布一个复杂的对象。

      【讨论】:

        【解决方案6】:
            [HttpPost]
            public bool parseAllDocs([FromBody] IList<docObject> data)
            {
                // do stuff
        
            }
        

        【讨论】:

          【解决方案7】:

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

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

          在服务器中使用这个:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-05-28
            • 1970-01-01
            • 2014-10-20
            • 2016-11-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多