ASP.NET MVC 2 and passing JSON objects to Actions

by ahura mazda 10. June 2011 10:39

I’ve recently made the jump to ASP.NET MVC 2 (my Godaddy host is running ASP.NET 3.5). Everything worked well until I started converting my old ASP.NET JSON Webservices to Controller Actions.

Retrieving JSON responses from the Action worked fine, but sending complex JSON objects or arrays back to the Action as parameters started failing. I started using other developers solutions which worked with complex JSON objects but then 2 types of objects fail, Enums and Arrays.

I first used Javier G. Lozano’s JsonModelBinderwhich worked for everything except I could not use it on Godaddy because the code uses Reflection to invoke an internal method in JavaScriptSerializer (throws a Security Exception).

I then used ASP.NET MVC 2 Futuresand its JsonValueProviderFactory approach. That worked for JSON arrays but not for Enums. Integers coming back from JavaScript are not converted to their .NET Enum equivalent. So I went back to Javier’s JsonModelBinder and removed the Reflection code only to find it no longer works with JSON arrays.

At my wit’s end as I needed to fix a broken site for my client, I decided to reverse engineer JavaScriptSerializer using ILSpy as Javier’s reflection code was invoking an internal method Deserialize(). That worked great; no Security exceptions and my complex JSON objects were being passed correctly.

However, I did not like this hacked solution. Fortunately, I came across James Newton-King’s Json.NET. This solves the problems of Enums and Arrays elegantly. Here’s what you need:

Server Side References

Client Side References

  • jQuery or any other library or custom Ajax code,
  • Json2 or any other Json library

Server Side Code

part 1 of 2
Create a JsonModelBinder class. I've customized Javier's JsonModelBinder.cs file to use Json.NET JsonConvert instead of Reflection:

using System.IO;
using System.Web.Mvc;
using Newtonsoft.Json;

namespace AhuraMazda.Mvc.Binders
{
	/// 
	/// Model binder that does the mapping for any JSON request or basic request
	/// 
	///	Original code from http://lozanotek.com/blog/archive/2010/04/16/simple_json_model_binder.aspx
	/// 
	/// 
	public class JsonModelBinder : DefaultModelBinder
	{
		public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
		{
			if (!IsJSONRequest(controllerContext))
			{
				return base.BindModel(controllerContext, bindingContext);
			}
			// Get the JSON data that's been posted
			var request = controllerContext.HttpContext.Request;
			var jsonStringData = new StreamReader(request.InputStream).ReadToEnd();

			return JsonConvert.DeserializeObject(jsonStringData, bindingContext.ModelMetadata.ModelType);
		}

		private static bool IsJSONRequest(ControllerContext controllerContext)
		{
			var contentType = controllerContext.HttpContext.Request.ContentType;
			return contentType.Contains("application/json");
		}
	}
}

part 2 of 2
Register your JsonModelBinder with MVC. In Global.asax, add this:

protected void Application_Start()
{
	// This custom model binder is required to allow JSON to be correctly serialised from client to server.
	// Don't worry about setting the DefaultBinder as JsonModelBinder inherits DefaultBinder and uses it accordingly.
	ModelBinders.Binders.DefaultBinder = new AhuraMazda.Mvc.Binders.JsonModelBinder();

	// Your other code goes here...
}

 

optional (for testing)

public class ServicesController : Controller
{
	public class TestModel
	{
		public int TestId {get;set;}
		public List<NestedTestModel> NestedTests {get;set;}
	}
	public class NestedTestModel
	{
		public int NestedTestId {get;set;}
		public string Name {get;set;}
	}

	[HttpPost]
	public ActionResult Test(TestModel testModel)
	{
		return Json(testModel);
	}
}

Client Side Code

In your page/view, use this example jQuery Ajax:

function testAjax()
{
	var data =
	{
		TestId: 1,
		NestedTests:
		[
			{
				NestedTestId: 2,
				Name: "two"
			},
			{
				NestedTestId: 3,
				Name: "three"
			},
		]
	};

	jQuery.ajax({
		type: "POST",
		url: "/services/Test/", // assuming ServicesController with action Test(TestModel testModel)
		data: JSON.stringify(data), // JavaScript object must be converted to Json string representation
		contentType: 'application/json', // must be application/json as JsonModelBinder checks for this content type
		dataType: "json",
		success: function (data, textStatus, jqXHR)
		{
			alert(JSON.stringify(data));
		},
		error: function (jqXHR, textStatus, errorThrown)
		{
			alert(jqXHR.responseText);
		}
	});
}

Tags: , , , ,

release: band scan

by ahura mazda 16. January 2010 17:19

I’ve uploaded a new release to CodePlex and the Demo has been updated as well.

I’ve added a new Visual called Band Scan which displays a graph of certain frequencies over time.

I’ve also added the actual bands being analyzed for both this and the Peak Meter. The peak meter bars are now smoother and should be slightly faster as well.

Tags:

updated saluse mediakit for 2009-12-27

by ahura mazda 27. December 2009 23:13

i’ve uploaded a new release to salusemediakit.codeplex.com

the live demo shows the faster rendering with setting MaxFrameRate=30 on the Silverlight plugin making a tremendous positive difference.

also fixed the position calculation but again, still not close to ideal.

Tags:

MediaKit | Silverlight 3

new location

by ahura mazda 12. December 2009 01:06

just moved over from net.sanchezsalvador.com

needed a new domain for a while, eventually beat those domain squatters

Tags:

new audio effect: duet

by ahura mazda 10. December 2009 23:12

i've added a new effect named Duet. it's the Pitch Shift effect blended with the original audio to create the illusion of 2 people singing.

play with the effect slider to adjust the key of the "second singer", exactly how it is done with the Pitch Shift effect

live demo found here

Tags:

MediaKit | Silverlight 3

pitch shifting in real-time

by ahura mazda 8. December 2009 03:18

i’ve added a real-time pitch shifter as an AudioPreProcessor to the sample demo.
i’ve also changed the effect slider to now work with both the Pan and Pitch Shift effects.

the Pitch Shift effect uses code from a C# conversion from dspdimension.com

have a play

Tags:

MediaKit | Silverlight 3

audio pre-processor for mediakit

by ahura mazda 7. December 2009 17:18

i'm currently working at adding an interface for processing the raw audio data before it reaches a consumer (MediaElement for example).it will allow you to write any code to modify the audio data for special effects, noise removal or for whatever else you can think of. currently testing speed issues, closures and scope (since it uses a delegate for this feature).

update: Saluse MediaKit now includes a AudioPreProcessor delegate that is executed against the raw audio data before it is passed onto the consumer (e.g. MediaElement).
i will be updating the source on CodePlex shortly. i’ve changed back to developing in Visual Studio 2010 beta2 and I will like to offer the source for both VS 2008 and 2010, so I’ve some hacking to do.

the live demo has been updated to show off some effects i’ve thrown together; Pan, Noise and Echo (a poor man’s version)

Tags:

MediaKit | Silverlight 3

silverlight mediakit live demo

by ahura mazda 3. December 2009 02:14

I promise to add documentation soon, on how to use the MediaKit to get results like this:

press play


The MediaKit library contains a custom MP3 MediaStreamSource which decodes MP3 files and provides the raw audio data for your use. It works hand-in-hand with a custom SeekableStream class (included) that allows non seekable streams (HTTP response stream) to appear seekable.

Also supports modification of the audio data to create effects or corrections.

Source code can be found on CodePlex at salusemediakit.codeplex.com

note: there are still quite a few bugs, for example, the position calculation is wonky and the visuals are sometimes out of sync. still working on it

Tags:

MediaKit | Silverlight 3

Silverlight MP3 Decoder coming soon

by ahura mazda 28. November 2009 13:12

I'll soon be uploading a Silverlight 3 library that has a custom MediaStreamSource that provides raw PCM data for MP3 files.

As well, the library will include a SeekableStream that makes any other stream seekable and gets around the limitations imposed by Silverlight.

Tags:

Silverlight 3