Noah Blumenthal's Blog

June 17, 2009

jEditable note: don’t return JSON (and how to return strings from ASP.NET MVC Actions)

Filed under: ASP.NET MVC,jQuery — noahblu @ 5:42 pm

jEditable is a cool jQuery plugin for inline editing.  I was toying around with it today and found an interesting ‘feature’: it expects a string response from the server.  Now that’s a problem because I was returning a JSON object so my string had quotes around it (Test became “Test”).  Ok, so I have to return a regular string.  I guess I just didn’t expect that because I’m used to my jQuery plugins expecting json (or at least accepting it).

Well, my Action returns an ActionResult because not always will it be accessed via jQuery (yup, this does not actually require javascript!).  I check the request (if (Request.IsAjaxRequest())) and proceed…
So, what I did was create a StringResult.  Much like the JsonResult class, the StringResult outputs the data you give it but it just outputs text.  Simple but effective, here’s the code:

public class StringResult : ActionResult
 {
 private string _output;
 public StringResult(string output)
 {
 _output = output;
 }
 public override void ExecuteResult(ControllerContext context)
 {
 HttpResponseBase response = context.HttpContext.Response;
 response.ContentType = "text/html";
 response.Write(_output);
 }
 }
Advertisements

June 15, 2009

ModelBinder for objects without default constructors

Filed under: Uncategorized — noahblu @ 4:46 pm

My DDD Value Objects don’t have default constructors.  Neither do many of my entity objects — I like having my objects valid on instantiation.  But ASP.NET’s DefaultModelBinder doesn’t know how to instantiate these objects.  I created a ConstructorModelBinder to achieve this functionality.  The code is below.  Keep in mind that this will currently use the constructor with the most parameters.

You use it by specifying something like this in the Global.asax:

System.Web.Mvc.ModelBinders.Binders.Add(typeof(MyClass), new ConstructorModelBinder<MyClass>());

public class ConstructorModelBinder<T> : DefaultModelBinder
 {
 protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
 {
 Type type1 = typeof(T);
 ConstructorInfo[] constructors = type1.GetConstructors();
 ConstructorInfo largestConstructor = constructors.OrderByDescending(x => x.GetParameters().Count()).First();
 ParameterInfo[] parameters = largestConstructor.GetParameters();
 List<object> paramValues = new List<object>();
 IModelBinder binder;
 string oldModelName = bindingContext.ModelName;
 foreach (ParameterInfo param in parameters)
 {
 string name = CreateSubPropertyName(oldModelName, param.Name);
 bindingContext.ModelType = param.ParameterType;
 bindingContext.ModelName = name;
 if (!System.Web.Mvc.ModelBinders.Binders.TryGetValue(param.ParameterType, out binder))
 binder = System.Web.Mvc.ModelBinders.Binders.DefaultBinder;
 object model = binder.BindModel(controllerContext, bindingContext);
 paramValues.Add(model);
 }
 bindingContext.ModelType = typeof(T);
 bindingContext.ModelName = oldModelName;
 object obj = Activator.CreateInstance(type1, paramValues.ToArray());
 return obj;
 }
 }

Create a free website or blog at WordPress.com.