Отправка данных 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 (где я передаю более сложный объект 'data'), jsonOfLog получает значение {object}. Но отладчик не показывает больше подробностей в окне наблюдения, и я не знаю, какие методы я могу использовать для работы с этой переменной.
Как передать данные JSON в контроллер MVC, где передаваемые данные представляют собой строковый сложный объект?
Спасибо, Нотр
6 ответов
Проблема ваша 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]}
Я думаю, что вы найдете свой ответ, если обратитесь к этому посту: десериализовать JSON в C# динамический объект?
Есть различные способы достижения того, что вы хотите здесь. Подход System.Web.Helpers.Json (несколько ответов ниже) представляется наиболее простым.
VB.NET VERSION
Итак, я только что потратил несколько часов в поисках жизнеспособного метода для публикации нескольких параметров в веб-API MVC 4, но большая часть того, что я обнаружил, была либо для действия 'GET', либо просто для вывода из строя, не работало. Тем не менее, я, наконец, получил это работает, и я думал, что поделюсь своим решением.
Используйте пакеты NuGet для загрузки
JSON-js json2
а такжеJson.NET
, Шаги для установки пакетов NuGet:(1) В Visual Studio перейдите на Веб-сайт > Управление пакетами NuGet...
(2) Введите json (или что-то в этом роде) в строку поиска и найдите
JSON-js json2
а такжеJson.NET
, Двойной щелчок по ним установит пакеты в текущий проект.(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 Web 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.
Вот некоторые дополнительные ссылки, которые помогли (в основном в C#):
- Использование jQuery для отправки параметров FromBody
- Отправка объекта JSON в Web API
- И, конечно же, ответ Дж. Торреса был последним кусочком головоломки.
// простой объект 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
}
Ну, моя клиентская часть (файл cshtml) использовала DataTables для отображения сетки (теперь с помощью управления Infragistics, что отлично). И как только пользователь щелкнул по строке, я зафиксировал событие строки и дату, связанную с этой записью, чтобы вернуться на сервер и сделать дополнительные запросы со стороны сервера для сделок и т. Д. И нет - я НЕ СТРОГАЛИЗИРОВАЛ его...
DataTables def начинался как этот (оставляя много вещей вне), и событие click видно ниже, где я нажимаю на мой объект 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
});
Несколько месяцев назад я столкнулся со странной ситуацией, когда мне также нужно было отправить некоторую дату в формате 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;
}
}
и поэтому я смог десериализовать свой узел JSON-параметр объекта в объекте "узлов"; естественно, конечно, используя класс "NodeList1", чтобы он работал.
Я надеюсь, что это помогает.... Боб