h bob
h bob

Reputation: 3780

Custom model binding for a particular property in a strongly-typed model

I could use a custom model binder to bind a 0 and 1 to a false and true in this action:

[IntToBoolBinder]
public virtual ActionResult foo(bool someValue) {
}

But now suppose the argument is a strongly-typed model:

public class MyModel {
  public int SomeInt { get; set; }
  public string SomeString { get; set; }
  public bool SomeBool { get; set; }          // <-- how to custom bind this?
}

public virtual ActionResult foo(MyModel myModel) {
}

The request will contain an int and my model expects a bool. I could write a custom model binder for the entire MyModel model, but I want something more generic.

Is is possible to custom bind a particular property of a strongly-typed model?

Upvotes: 1

Views: 1493

Answers (1)

Bartosz Czerwonka
Bartosz Czerwonka

Reputation: 1651

If you want to make a custom binding to it can look like this:

public class BoolModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext,
                                         PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.PropertyType == typeof(bool))
        {
            Stream req = controllerContext.RequestContext.HttpContext.Request.InputStream;
            req.Seek(0, SeekOrigin.Begin);
            string json = new StreamReader(req).ReadToEnd();

            var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

            string value = data[propertyDescriptor.Name];
            bool @bool = Convert.ToBoolean(int.Parse(value));
            propertyDescriptor.SetValue(bindingContext.Model, @bool);
            return;
        }
        else
        {
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }
    }
}

But MVC and WebAPI int conversion to bool (field names must be the same) and do not need anything extra to write, so I do not know if you need the code above.

Try this demo code:

public class JsonDemo
{
    public bool Bool { get; set; }
}

public class DemoController : Controller
{
    [HttpPost]
    public ActionResult Demo(JsonDemo demo)
    {
        var demoBool = demo.Bool;

        return Content(demoBool.ToString());
    }
}

And send JSON object :

{
  "Bool" : 0
}

Upvotes: 3

Related Questions