After a frustrating couple of hours trying to determine WHY WHY my object did not bind with MVC3 I finally found why.
The story began like this.
I have a very simple method in a controller. Something like this:
public class Form1Controller : Controller
{
//
// GET: /Form1/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult DoButton1(Person zzz)
{
System.Diagnostics.Debug.WriteLine(zzz.Name);
return Json(data: "Good Test");
}
}
And I called that code with a jquery Statement like:
var person= JSON.stringify({ Name: "Mauricio", LastName: "Rojas" }); $.ajax({
url: "/Form1/DoButton1/",
type: "POST",
dataType: "json",
data: person,
success: function () {
alert("OK");
},
});
But!!! (maybe you already saw the obvious mistake) no matter what I sent, the Person object was not bind.
The action method got called but I was not able to see the sent values. I used Chrome developer tools and the network that show the
values I had modified.
SO WHYYYYY!!!!
I tried to debug the MVC code, but VS studio could not load the pdb, something I get that I still not sure why.
So how could I intercept what was happening? Simple with a ModelBinder.
A ModelBinder is class that is used to bind your request to a model object.
So I went to the Global.asax file and register my binder, and set some breakpoints.
//Code in Global.asax to register a Person Binder
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ModelBinders.Binders.Add(typeof(Person), new PersonBinder());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public class PersonBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var contentType = controllerContext.HttpContext.Request.ContentType;
if (!contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return (null);
string bodyText;
using (var stream = controllerContext.HttpContext.Request.InputStream)
{
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
bodyText = reader.ReadToEnd();
}
if (string.IsNullOrEmpty(bodyText)) return (null);
var xx = new JavaScriptSerializer().Deserialize<Person>(bodyText);
return xx;
}
}
And voila!! the content type I was getting was something like:application/x-www-form-urlencoded
So I just added the content type parameter to my javascript code:
$.ajax({
url: "/Form1/DoButton1/",
type: "POST",
dataType: "json",
data: viewModelStr,
success: function () {
alert("inside");
}//,
contentType: 'application/json; charset=utf-8'
});
While doing some experiments with Razor, and trying to generate some simple JSON objects in my ASP.NET MVC views
I had to deal with problems because my json string got a lot of weird " and other strange escape character.
That in general is very good but I needed my string just as is.
The current workaround that I have found for doing that is:
var objectInStr = @(new HtmlString(Json.Encode(Model or your object)));