How to post an array of complex objects with JSON, jQuery to ASP.NET MVC Controller?
I've found an solution. I use an solution of Steve Gentile, jQuery and ASP.NET MVC – sending JSON to an Action – Revisited.
My ASP.NET MVC view code looks like:
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); } }); };
and my controller action is decorated with an custom attribute
[JsonFilter(Param = "widgets", JsonDataType = typeof(List<PageDesignWidget>))]public JsonResult SaveOrUpdate(List<PageDesignWidget> widgets
Code for the custom attribute can be found here (the link is broken now).
Because the link is broken this is the code for the 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 is from Json.NET
Action Filters, jquery stringify, bleh...
Peter, this functionality is native to MVC. That's one of things that makes MVC so great.
$.post('SomeController/Batch', { 'ids': ['1', '2', '3']}, function (r) { ...});
And in the action,
[HttpPost]public ActionResult Batch(string[] ids){}
Works like a charm:
If you're using jQuery 1.4+, then you want to look into setting traditional mode:
jQuery.ajaxSettings.traditional = true;
As described here: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters
This even works for complex objects. If you're interested, you should look into the MVC documentation about Model Binding: http://msdn.microsoft.com/en-us/library/dd410405.aspx
In .NET4.5
, MVC 5
no need for widgets.
Javascript:
object in JS:
mechanism that does post.
$('.button-green-large').click(function() { $.ajax({ url: 'Quote', type: "POST", dataType: "json", data: JSON.stringify(document.selectedProduct), contentType: 'application/json; charset=utf-8', }); });
C#
Objects:
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; }}
Controller:
[AcceptVerbs(HttpVerbs.Post)]public ActionResult Quote(WillsQuoteViewModel data){....}
Object received:
Hope this saves you some time.