Проводка данных JSON через jQuery для действия контроллера ASP.NET MVC 4
У меня возникли проблемы с попыткой передать сложный объект 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 имеет значение null.
Если я изменю значение переменной json в JavaScript, чтобы свойство jsonOfLog было простой строкой, например.
json = { jsonOfLog: "simple string" };
тогда, когда моя точка останова в начале метода ConvertLogInfoToXML попадает, jsonOfLog - это значение строки (например, "простая строка" ).
Я попытался изменить тип параметра jsonOfLog в методе действий для объекта типа:
[HttpPost]
[ValidateInput(false)]
public string ConvertLogInfoToXml(object jsonOfLog)
Теперь, с исходным кодом JavaScript (где я передаю более сложный объект данных), jsonOfLog получает значение {object}. Но отладчик не показывает больше деталей в окне просмотра, и я не знаю, какие методы я могу использовать для работы с этой переменной.
Как передать данные JSON в контроллер MVC, где переданные данные являются сложным сложным объектом?
Спасибо,
Notre
Ответы
Ответ 1
Проблема заключается в вашем dataType
и формате вашего параметра data
. Я просто проверил это в песочнице и выполнил следующие работы:
С#
[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]}
Ответ 2
Я думаю, вы найдете ответ, если ссылаетесь на этот пост: Deserialize JSON в динамический объект С#?
Существуют различные способы достижения того, что вы хотите здесь. Подход System.Web.Helpers.Json(несколько ответов ниже) кажется самым простым.
Ответ 3
ВЕРСИЯ VB.NET
Хорошо, поэтому я потратил несколько часов на поиски жизнеспособного метода для публикации нескольких параметров в MVC 4 WEB API, но большинство из того, что я нашел, было либо для действия GET, либо просто плоский не работает. Тем не менее, я, наконец, получил эту работу, и я решил поделиться своим решением.
-
Используйте пакеты NuGet для загрузки JSON-js json2
и Json.NET
. Шаги по установке пакетов NuGet:
(1) В Visual Studio перейдите в Веб-сайт > Управление пакетами NuGet... ![enter image description here]()
(2) Введите json (или что-то в этом роде) в строку поиска и найдите JSON-js json2
и Json.NET
. Дважды щелкнув по ним, эти пакеты будут установлены в текущий проект. ![enter image description here]()
(3) NuGet автоматически поместит json файл в ~/Scripts/json2.min.js
в каталог проекта. Найдите файл json2.min.js и перетащите его в голову вашего сайта. Примечание. Инструкции по установке файлов .js(javascript) читайте это решение.
-
Создайте объект класса, содержащий требуемые параметры. Вы будете использовать это для доступа к параметрам в контроллере 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
-
Затем мы настраиваем фактический MVC 4 API-интерфейс API, который мы будем использовать для действия POST. В нем мы будем использовать 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
-
Теперь, когда у нас есть наш контроллер API, настроенный для получения нашего стробированного объекта JSON, мы можем свободно вызывать действие POST с клиентской стороны с помощью $.ajax; Продолжая предыдущий пример, вот мой код (замените 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 Controller. Для тех, у кого есть проблемы с интеграцией MVC 4 Web API с VS2010, вы можете скачать патч, чтобы сделать это возможным. Вы можете загрузить его из Microsoft Центр загрузки.
Вот несколько дополнительных ссылок, которые помогли (в основном на С#):
Ответ 4
//простой объект json в asp.net mvc
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
}
Ответ 5
Несколько месяцев назад я столкнулся с странной ситуацией, когда мне также нужно было отправить некоторую дату в формате Json на мой контроллер. Вот что я придумал после вытягивания волос:
Мой класс выглядит следующим образом:
public class NodeDate
{
public string nodedate { get; set; }
}
public class NodeList1
{
public List<NodeDate> nodedatelist { get; set; }
}
и мой код С# следующим образом:
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;
}
}
и поэтому мне удалось десериализовать параметр nodedates Json object в объекте "nodes"; естественно, конечно, используя класс "NodeList1", чтобы заставить его работать.
Надеюсь, это поможет...
Боб
Ответ 6
Ну, моя клиентская сторона (файл cshtml) использовала DataTables для отображения сетки (теперь она отлично управляет контролем Infragistics).
И как только пользователь нажал на строку, я захватил событие строки и дату, связанную с этой записью, чтобы вернуться на сервер и сделать дополнительные серверные запросы для сделок и т.д.
И нет - я НЕ УСТАНАВЛИВАЯ...
Определения DataTables начались как это (оставляя много вещей), а событие click видно ниже, где я PUSH на свой объект 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
});