0

I've implemented the model binder shown below. Everything is working as expected only that nested properties are not bound:

  • Order.Customer.Name <- Is not bound in the OrderModelBinder, but initial values are shown correctly in form (leading me to the assuption that the prefixes are correct)
  • Order.EventDate <- Is bound correctly and values are shown correctly in the form

I'm using MEF to get the data store into the binder. Should the binding for the nested property name work, or am I missing the point? Is calling base.BindModel(...) the right way to go?

[Export(typeof(OrderModelBinder))] public class OrderModelBinder : DefaultModelBinder
{        
    private readonly IProjectEntities _data;
    private const string _orderSessionKey = "OrderSessionKey";

    [ImportingConstructor]
    public OrderModelBinder([Import]IProjectEntities data)
    {
        _data = data;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Order order = (Order)controllerContext.HttpContext.Session[_orderSessionKey];
        if (order == null)
        {
            order = new Order();
            order.Customer = new Customer();
            controllerContext.HttpContext.Session[_orderSessionKey] = order;

            _data.Orders.AddObject(order);                
        }

        bindingContext.ModelMetadata.Model = order;
        return base.BindModel(controllerContext, bindingContext);
    }
}

This is the controller where the post lands:

[HttpPost]
public ActionResult ShipmentDetails(Order order)
{
    // do stuff here
}

This is a part of the razor view with the form:

@using(Html.BeginForm()) 
{    
    @Html.ValidationSummary()    
    <table class="formTable">
        <tbody>
        ...
        <tr>
            <td class="formTableLabel">@Html.LabelFor(model => model.Order.Customer.Name)</td>
            <td>@Html.TextBoxFor(model => model.Order.Customer.Name, new { @class = "formTableLong" })</td>
            <td>@Html.ValidationMessageFor(model => model.Order.Customer.Name)</td>
        </tr>
        ...
        <input type="submit" value="Go on." />

2 Answers 2

2

I solved the problem in my special case. The model binder was not the problem. The problem was that the the actual model class was annotated like this which then correctly (but unwanted) excluded Customer (the nested object) from the binding process:

[MetadataType(typeof(OrderMetatdata))]
[Bind(Include = "EventDate, PaymentProcessor")]
partial class Order
{
    ...

Fixed Version is this:

[MetadataType(typeof(OrderMetatdata))]
[Bind(Include = "EventDate, PaymentProcessor, Customer")]
partial class Order
{
    ...

If you have any problems with databinding I recommend to check any Annotations on your model classes that might be wrong as they were in my case.

Sign up to request clarification or add additional context in comments.

Comments

0

@Html.TextBoxFor(model => model.Order.Customer.Name, new { @class = "formTableLong" })

This is the right way if you have nested properties. Try removing your custom model binder and then see if it works. Suggesting this because that's the only alien piece of code for me.

1 Comment

Thanks for your reply. Still no luck though. What I found out is the following. When I initialize some Members of the nested object (for e.g. I set in the constuctor Order.Customer.Name = "M. Klein") this initial value is shown correctly in the razor form shown above. This leads me to the assuption that the binding string are basically correct, but something is wrong with binding nested objects. Any ideas on this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.