2012-12-08 113 views
10

我想发布一个JSON数组到MVC控制器。但不管我尝试什么,一切都是0或者为空。发布JSON数组到mvc控制器

我有这张包含文本框的表。我需要从所有这些文本框中将它作为对象的ID和值。

这是我的javascript:

$(document).ready(function() { 

    $('#submitTest').click(function (e) { 

     var $form = $('form'); 
     var trans = new Array(); 

     var parameters = { 
      TransIDs: $("#TransID").val(), 
      ItemIDs: $("#ItemID").val(), 
      TypeIDs: $("#TypeID").val(), 
     }; 
     trans.push(parameters); 


     if ($form.valid()) { 
      $.ajax(
       { 
        url: $form.attr('action'), 
        type: $form.attr('method'), 
        data: JSON.stringify(parameters), 
        dataType: "json", 
        contentType: "application/json; charset=utf-8", 
        success: function (result) { 
         $('#result').text(result.redirectTo) 
         if (result.Success == true) { 
          return fase; 
         } 
         else { 
          $('#Error').html(result.Html); 
         } 
        }, 
        error: function (request) { alert(request.statusText) } 
       }); 
     } 
     e.preventDefault(); 
     return false; 
    }); 
}); 

这是我的看法代码:

<table> 
     <tr> 
      <th>trans</th> 
      <th>Item</th> 
      <th>Type</th> 
     </tr> 

     @foreach (var t in Model.Types.ToList()) 
     { 
      { 
      <tr> 
       <td>     
        <input type="hidden" value="@t.TransID" id="TransID" /> 
        <input type="hidden" value="@t.ItemID" id="ItemID" /> 
        <input type="hidden" value="@t.TypeID" id="TypeID" /> 
       </td> 
      </tr> 
      } 
     } 
</table> 

这是控制器即时通讯试图接收数据:

[HttpPost] 
public ActionResult Update(CustomTypeModel ctm) 
{ 


    return RedirectToAction("Index"); 
} 

什么时我做错了?

+1

请说明你的'CustomTypeModel'的样子。 –

+0

您正在使用哪个版本的mvc? –

+0

好像你可能会缺少'name'属性和你想要POST的属性的名字。你能发布你发布的实际数据吗?实际的POST请求? – rae1

回答

50

你的代码有很多问题。让我们从标记开始。你有一张桌子,里面的每一行里面都有隐藏的字段。除此之外,您已对这些隐藏元素的id属性进行了硬编码,这意味着您可能最终会在标记中使用相同标识的多个元素,从而导致标记无效。

因此,让我们先固定你的标记开始:

@foreach (var t in Model.Types.ToList()) 
{ 
    <tr> 
     <td>     
      <input type="hidden" value="@t.TransID" name="TransID" /> 
      <input type="hidden" value="@t.ItemID" name="ItemID" /> 
      <input type="hidden" value="@t.TypeID" name="TypeID" /> 
     </td> 
    </tr> 
} 

好了,现在你有有效的标记。现在让我们继续讨论javascript事件,点击一些submitTest按钮后会触发这个事件。如果这是表单的提交按钮,我建议您订阅表单的.submit事件而不是其提交按钮的.click事件。原因是因为如果用户在焦点位于某个输入字段内时按下Enter键,可能会提交表单。在这种情况下,您的点击事件将不会被触发。

所以:

$(document).ready(function() { 
    $('form').submit(function() { 
     // code to follow 

     return false; 
    }); 
}); 

好吧,其次是你需要收获隐藏要素这是表内的值,并把它们放到一个JavaScript对象,我们也将随之JSON序列化和发送的部分作为对服务器的AJAX请求的一部分。

让我们继续前进:

var parameters = []; 
// TODO: maybe you want to assign an unique id to your table element 
$('table tr').each(function() { 
    var td = $('td', this); 
    parameters.push({ 
     transId: $('input[name="TransID"]', td).val(), 
     itemId: $('input[name="ItemID"]', td).val(), 
     typeId: $('input[name="TypeID"]', td).val() 
    }); 
}); 

到目前为止,我们已经填补了参数,现在让我们把它们发送到服务器:

$.ajax({ 
    url: this.action, 
    type: this.method, 
    data: JSON.stringify(parameters), 
    contentType: 'application/json; charset=utf-8', 
    success: function (result) { 
     // ... 
    }, 
    error: function (request) { 
     // ... 
    } 
}); 

现在让我们进入到服务器端。与往常一样,我们首先来定义视图模型:

public class MyViewModel 
{ 
    public string TransID { get; set; } 
    public string ItemID { get; set; } 
    public string TypeID { get; set; } 
} 

和一个控制器动作,将采取这种模式的集合:

[HttpPost] 
public ActionResult Update(IList<MyViewModel> model) 
{ 
    ... 
} 

而这里的最终客户端代码:

$(function() { 
    $('form').submit(function() { 
     if ($(this).valid()) { 
      var parameters = []; 
      // TODO: maybe you want to assign an unique id to your table element 
      $('table tr').each(function() { 
       var td = $('td', this); 
       parameters.push({ 
        transId: $('input[name="TransID"]', td).val(), 
        itemId: $('input[name="ItemID"]', td).val(), 
        typeId: $('input[name="TypeID"]', td).val() 
       }); 
      }); 

      $.ajax({ 
       url: this.action, 
       type: this.method, 
       data: JSON.stringify(parameters), 
       contentType: 'application/json; charset=utf-8', 
       success: function (result) { 
        // ... 
       }, 
       error: function (request) { 
        // ... 
       } 
      }); 
     } 
     return false; 
    }); 
}); 

显然,如果你的视图模型不同(你没有在你的问题中展示过),你可能需要修改代码以使它与你的结构相匹配,否则默认模型联编程序将无法使用将JSON反序列化。

+0

我正在测试你的代码。 – Yustme

+4

我见过的最佳答案之一。不是因为复杂性,而是因为能够通过答案走向人,并向他们展示如何正确地做某件事。 –

-1

我觉得你对MVC世界的做法有点不对劲。 如果你有一个合适的模型来绑定你的数据 - 你最好使用助手从框中而不是使用“手工制作”的JavaScript。如果您需要异步调用,请查看HtmlHelper或AjaxHelper。

并将您的数据绑定到使用@Html.TextBoxFor()@Html.BeginForm块内的表示法这将简化您的代码并减少javascript的数量,这对维护更好。

在服务器部件上,您需要实现自定义模型联编程序并更改设置,以便通过模型联编程序为当前控制器操作提出处理请求。它会让你编写一些服务器端代码,但静态类型代码看起来更容易编码和测试,而且它更适合你的应用程序需要,因为我更喜欢JavaScript做它应该做的事情=>管理UI,但不构建模型在服务器端正确解析。它更适合单一职责原则。

看到这个video,这是简单的教程如何做到这一点

+0

它是一个复杂的类型。不能这样绑定,至少我还没有想出如何。 javascript现在适用于我。但是对于记录来说,没有关于InputFor的@ Html.InputFor() – Yustme

+0

Thx,我上次编码java并且很难正确记住所有名称。我编辑我的答案,你可以看看它。 – Ph0en1x

+0

听起来不错,但我已经尝试了很多东西来避免JavaScript。这是一个复杂的模型。另外,我确实使用了@ Html.TextBoxFor(),但我不知道如何使用javascript从数据中获取数据。 – Yustme

6

还有一种更简单的方法:使用查询字符串来发送数据。如果您感兴趣, 您目前的方法是错误的,因为JSON数组数据类型是string而不是CustomTypeModel

首先,删除data ajax选项。我们不再需要这个了。

其次,改变你的控制器类似如下:

[HttpPost] 
public ActionResult Update(string json) 
{ 
    // this line convert the json to a list of your type, exactly what you want. 
    IList<CustomTypeModel> ctm = 
     new JavaScriptSerializer().Deserialize<IList<CustomTypeModel>>(json); 

    return RedirectToAction("Index"); 
} 

注1:您CustomTypeModel属性的名称是一样的,你输入的内容为JSON中的元素是很重要的。所以,你的CustomTypeModel应该是这样的:

public class CustomTypeModel 
{ 
    // int, or maybe string ... whatever you want. 
    public int TransIDs { get; set; } 
    public int ItemIDs { get; set; } 
    public int TypeIDs { get; set; } 
} 

注2:当你想通过查询字符串来发送数据这种方法是非常有用的。所以,你的网址可以是这样的:

url: '/controller/action?json=' + JSON.stringify(trans) 
+1

为我工作。谢谢 –

相关问题