28

我在尝试将复杂的 JSON 对象传递给 MVC 4 控制器操作时遇到问题。由于 JSON 内容是可变的,我不希望 MVC 将 JSON 的各个属性/元素映射到操作方法的参数列表中的参数。我只想在控制器操作中将数据作为单个 JSON 字符串参数获取。

这是我的操作方法的签名:

    [HttpPost]
    [ValidateInput(false)]
    public string ConvertLogInfoToXml(string jsonOfLog)

这是我从浏览器发布一些 JSON 数据的尝试:

    data = {prop: 1, myArray: [1, "two", 3]}; 
    //'data' is much more complicated in my real application
    json = {jsonOfLog: data};

    $.ajax({
        type: 'POST',
        url: "Home/ConvertLogInfoToXml",
        data: JSON.stringify(json),
        success: function (returnPayload) {
            console && console.log ("request succeeded");
        },
        error: function (xhr, ajaxOptions, thrownError) {
            console && console.log ("request failed");
        },
        dataType: "xml",
        contentType: "application/json",            
        processData: false,
        async: false
    });

当我在 ConvertLogInfoToXML 方法的开头命中断点时,jsonOfLog 为空。

如果我更改 JavaScript 中设置的 'json' 变量以使 jsonOfLog 属性成为简单字符串,例如:

json = { jsonOfLog: "simple string" };

然后当我在 ConvertLogInfoToXML 方法开头的断点被命中时,jsonOfLog 是字符串的值(例如“简单字符串”)。

我尝试将 action 方法中的 jsonOfLog 参数的类型更改为对象类型:

    [HttpPost]
    [ValidateInput(false)]
    public string ConvertLogInfoToXml(object jsonOfLog)

现在,使用原始 JavaScript 代码(我在其中传递一个更复杂的“数据”对象),jsonOfLog 获取 {object} 的值。但是调试器并没有在监视窗口中显示更多细节,而且我不知道我可以使用什么方法来操作这个变量。

如何将 JSON 数据传递给 MVC 控制器,其中传递的数据是字符串化的复杂对象?

谢谢, 诺特

4

6 回答 6

24

问题是你dataType和你的data参数的格式。我刚刚在沙箱中对此进行了测试,并且以下工作:

C#

    [HttpPost]
    public string ConvertLogInfoToXml(string jsonOfLog)
    {
        return Convert.ToString(jsonOfLog);
    }

javascript

<input type="button" onclick="test()"/>

    <script type="text/javascript">

        function test() {
            data = { prop: 1, myArray: [1, "two", 3] };
            //'data' is much more complicated in my real application
            var jsonOfLog = JSON.stringify(data);

            $.ajax({
                type: 'POST',
                dataType: 'text',
                url: "Home/ConvertLogInfoToXml",
                data: "jsonOfLog=" + jsonOfLog,
                success: function (returnPayload) {
                    console && console.log("request succeeded");
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    console && console.log("request failed");
                },

                processData: false,
                async: false
            });
        }

    </script>

特别注意data,发送文本时,需要发送一个与你的参数名称匹配的变量。它不漂亮,但它会让你得到你梦寐以求的无格式字符串。

运行它时,jsonOfLog 在服务器函数中看起来像这样:

    jsonOfLog   "{\"prop\":1,\"myArray\":[1,\"two\",3]}"    string

HTTP POST 标头:

Key Value
Request POST /Home/ConvertLogInfoToXml HTTP/1.1
Accept  text/plain, */*; q=0.01
Content-Type    application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With    XMLHttpRequest
Referer http://localhost:50189/
Accept-Language en-US
Accept-Encoding gzip, deflate
User-Agent  Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host    localhost:50189
Content-Length  42
DNT 1
Connection  Keep-Alive
Cache-Control   no-cache
Cookie  EnableSSOUser=admin

HTTP POST 正文:

jsonOfLog={"prop":1,"myArray":[1,"two",3]}

响应头:

Key Value
Cache-Control   private
Content-Type    text/html; charset=utf-8
Date    Fri, 28 Jun 2013 18:49:24 GMT
Response    HTTP/1.1 200 OK
Server  Microsoft-IIS/8.0
X-AspNet-Version    4.0.30319
X-AspNetMvc-Version 4.0
X-Powered-By    ASP.NET
X-SourceFiles   =?UTF-8?B?XFxwc2ZcaG9tZVxkb2N1bWVudHNcdmlzdWFsIHN0dWRpbyAyMDEyXFByb2plY3RzXE12YzRQbGF5Z3JvdW5kXE12YzRQbGF5Z3JvdW5kXEhvbWVcQ29udmVydExvZ0luZm9Ub1htbA==?=

响应正文:

{"prop":1,"myArray":[1,"two",3]}
于 2013-06-28T18:40:33.237 回答
2

如果您参考这篇文章,我想您会找到答案:将JSON 反序列化为 C# 动态对象?

有多种方法可以在这里实现您想要的。System.Web.Helpers.Json 方法(几个答案)似乎是最简单的。

于 2013-06-28T18:12:14.637 回答
2

VB.NET 版本

好的,所以我刚刚花了几个小时寻找一种可行的方法来将多个参数发布到 MVC 4 WEB API,但我发现的大部分内容要么用于“GET”操作,要么完全不起作用。然而,我终于得到了这个工作,我想我会分享我的解决方案。

  1. 使用 NuGet 包下载JSON-js json2Json.NET. 安装 NuGet 包的步骤:

    (1) 在 Visual Studio 中,转到网站>管理 NuGet 包... 在此处输入图像描述

    (2) 在搜索栏中输入 json (或类似的东西)并找到JSON-js json2and Json.NET。双击它们会将包安装到当前项目中。在此处输入图像描述

    (3) NuGet 会自动将 json 文件~/Scripts/json2.min.js放到你的项目目录中。找到 json2.min.js 文件并将其拖放到您网站的头部。注意:有关安装 .js (javascript) 文件的说明,请阅读此解决方案

  2. 创建一个包含所需参数的类对象。您将使用它来访问 API 控制器中的参数。示例代码:

    Public Class PostMessageObj
    
    Private _body As String
    Public Property body As String
        Get
            Return _body
        End Get
        Set(value As String)
            _body = value
        End Set
    End Property
    
    
    Private _id As String
    Public Property id As String
        Get
            Return _id
        End Get
        Set(value As String)
            _id = value
        End Set
    End Property
    End Class
    
  3. 然后我们设置我们将用于 POST 操作的实际 MVC 4 Web API 控制器。在其中,我们将使用 Json.NET 在发布字符串对象时对其进行反序列化。请记住使用适当的名称空间。继续前面的示例,这是我的代码:

    Public Sub PostMessage(<FromBody()> ByVal newmessage As String)
    
    Dim t As PostMessageObj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of PostMessageObj)(newmessage)
    
    Dim body As String = t.body
    Dim i As String = t.id
    
    End Sub
    
  4. 现在我们已经设置了 API 控制器来接收我们的字符串化 JSON 对象,我们可以使用 $.ajax 从客户端自由调用 POST 操作;继续前面的示例,这是我的代码(适当替换 localhost+rootpath):

    var url = 'http://<localhost+rootpath>/api/Offers/PostMessage';
    var dataType = 'json'
    var data = 'nothn'
    var tempdata = { body: 'this is a new message...Ip sum lorem.',
        id: '1234'
    }
    var jsondata = JSON.stringify(tempdata)
    $.ajax({
        type: "POST",
        url: url,
        data: { '': jsondata},
        success: success(data),
        dataType: 'text'
    });
    

如您所见,我们基本上是在构建 JSON 对象,将其转换为字符串,将其作为单个参数传递,然后通过 JSON.NET 框架重新构建它。我没有在我们的 API 控制器中包含返回值,所以我只是在success()函数中放置了一个任意字符串值。


作者的笔记

这是在 Visual Studio 2010 中使用 ASP.NET 4.0、WebForms、VB.NET 和 MVC 4 Web API 控制器完成的。对于在将 MVC 4 Web API 与 VS2010 集成时遇到问题的任何人,您可以下载补丁以使其成为可能。您可以从 Microsoft 的下载中心下载它。

以下是一些有帮助的其他参考资料(主要在 C# 中):

于 2013-09-25T04:03:39.780 回答
1

//asp.net mvc中的简单json对象

var model = {"Id": "xx", "Name":"Ravi"};
$.ajax({    url: 'test/[ControllerName]',
                        type: "POST",
                        data: model,
                        success: function (res) {
                            if (res != null) {
                                alert("done.");
                            }
                        },
                        error: function (res) {

                        }
                    });


//model in c#
public class MyModel
{
 public string Id {get; set;}
 public string Name {get; set;}
}

//controller in asp.net mvc


public ActionResult test(MyModel model)
{
 //now data in your model 
}
于 2015-12-24T17:05:00.837 回答
0

几个月前,我遇到了一个奇怪的情况,我还需要将一些 Json 格式的日期发送回我的控制器。这是我拔掉头发后的想法:

我的课看起来像这样:

public class NodeDate
{
    public string nodedate { get; set; }
}
public class NodeList1
{
    public List<NodeDate> nodedatelist { get; set; }
}

我的 c# 代码如下:

        public string getTradeContribs(string Id, string nodedates)
    {            
        //nodedates = @"{""nodedatelist"":[{""nodedate"":""01/21/2012""},{""nodedate"":""01/22/2012""}]}";  // sample Json format
        System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
        NodeList1 nodes = (NodeList1)ser.Deserialize(nodedates, typeof(NodeList1));
        string thisDate = "";
        foreach (var date in nodes.nodedatelist)
        {  // iterate through if needed...
            thisDate = date.nodedate;
        }   
    }

所以我能够在“nodes”对象中反序列化我的nodedates Json对象参数;自然当然要使用“NodeList1”类来使其工作。

我希望这会有所帮助....鲍勃

于 2013-06-28T18:04:04.297 回答
0

好吧,我的客户端(一个 cshtml 文件)正在使用 DataTables 来显示一个网格(现在使用很棒的 Infragistics 控件)。一旦用户单击该行,我就捕获了该行事件和与该记录关联的日期,以便返回服务器并发出额外的服务器端交易请求等。不-我没有将其字符串化。 ..

DataTables def 是这样开始的(留下很多东西),点击事件如下所示,我推到我的 Json 对象上:

    oTablePf = $('#pftable').dataTable({         // INIT CODE
             "aaData": PfJsonData,
             'aoColumnDefs': [                     
                { "sTitle": "Pf Id", "aTargets": [0] },
                { "sClass": "**td_nodedate**", "aTargets": [3] }
              ]
              });

   $("#pftable").delegate("tbody tr", "click", function (event) {   // ROW CLICK EVT!! 

        var rownum = $(this).index(); 
        var thisPfId = $(this).find('.td_pfid').text();  // Find Port Id and Node Date
        var thisDate = $(this).find('.td_nodedate').text();

         //INIT JSON DATA
        var nodeDatesJson = {
            "nodedatelist":[]
        };

         // omitting some code here...
         var dateArry = thisDate.split("/");
         var nodeDate = dateArry[2] + "-" + dateArry[0] + "-" + dateArry[1];

         nodeDatesJson.nodedatelist.push({ nodedate: nodeDate });

           getTradeContribs(thisPfId, nodeDatesJson);     // GET TRADE CONTRIBUTIONS 
    });
于 2013-06-28T20:33:55.187 回答