1

I need to make a view which will support bulk inserting of objects. I am using the repository pattern with Entity Framework 4.

Since there will be multiple individual models in the View, how do I handle binding the view's model to what get's sent to the Repository?

How do I retreive the input values from the form into the controller?


I have managed to do the view but I am unable to retrieve the data from controller. I used the folowing statement but after the post it heppens to be nul

    public ActionResult AddPaymentForRoot_post(PaymentViewModelObject payments) {


        return null;

    }

1 Answer 1

2

I haven't used EF yet, but I have a similar requirement on our site. I accomplished it by specifying the View as inheriting System.Web.Mvc.ViewPage<IEnumerable<MyModelObject>> then use a for loop to build multiple input sections, utilizing the naming conventions required to allow the model binder to build the enumerable.

I prefer to create a view model with a property that is an enumerable (see update 2 below). In this example we could say it would be the MyViewModel object with an IEnumerable<MyModelObject> property called MyModelObjects. In this case, the view would play out as follows...

Specifically, make sure to include for each input section a hidden field named MyModelObjects.Index, then have your property inputs named MyModelObjects[0].MyProperty, where the value of the Index hidden field corresponds to the array index in the property names.

What you would end up with would look like this, for example:

<div>
    <input type="hidden" name="MyModelObjects.Index" value="0" />
    Name: <input type="text" name="MyModelObjects[0].Name" /><br />
    Value: <input type="text" name="MyModelObjects[0].Value" />
</div>
<div>
    <input type="hidden" name="MyModelObjects.Index" value="1" />
    Name: <input type="text" name="MyModelObjects[1].Name" /><br />
    Value: <input type="text" name="MyModelObjects[1].Value" />
</div>
<div><a href="#" id="addItem">Add another item</a></div>

In some cases I also have javascript (triggered by the anchor link in the markup above) that will clone a template input section, modify the names to populate the index value, and add it to the DOM. In this way users can dynamically add records to the view.

Depending on how you are handling your models, you may also pass in a ViewModel that has a property that is IEnumerable. The typing for the view would change, but fundamentally the design of the view wouldn't.

UPDATE Using the example above, here's a quick snippet of the jQuery code I use to add items. I'm assuming this is an insert, but note the comments if you wanted to support this type of interface for editing as well.

First, I set up a template. While this could be built totally in jQuery, I just find it easier to do the markup and manipulate the names.

<div id="templateDiv" style="display: none;">
    <input type="hidden" name="MyModelObjects.Index" value="0T" />
    Name: <input type="text" name="MyModelObjects[0T].Name" /><br />
    Value: <input type="text" name="MyModelObjects[0T].Value" />
</div>

You can also specify IDs in there...probably a good practice, but in the interest of brevity I'll leave it out for the example.

With that, you can set up the jQuery function as follows:

var currentIndex = 1 // if you were using this for editing, this would be dynamically set to the number of items you have
var doAddItem =
    function() {
        currentIndex++;
        var newItem = $("#templateDiv").clone();
        newItem.attr("id", "item" + currentIndex); // reset the ID here
        newItem.find("input[name=MyModelObjects.Index]").val(currentIndex);
        newItem.find("input[name$=.Name]").attr("name", "MyModelObjects[" + currentIndex + "].Name");
        newItem.find("input[name$=.Value]").attr("name", "MyModelObjects[" + currentIndex + "].Value");
        newItem.insertBefore($(this).closest("div")); // insert it before the div containing the add link...adjust appropriate to your layout
        return false;
    }

$(document).ready(function() {
    $("#addItem").click(doAddItem);
    // In a real-world app you'd probably want to have a delete option, too
});

UPDATE 2 There's a bit of an error up there - if your view is typed to an IEnumerable<object> then your field names will end up just being Index and [0].Name / [0].Value. In my actual app I use a view model that has a property that is itself an enumerable, so I actually type my pages as <MyViewModelObject>. In the example above, that view model object would have a property called MyModelObject, which would be an enumerable (and more realistically called MyModelObjects plural).

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

2 Comments

Wow, I haven't thought that way before. that is a perfect idea. I didn't give it a try but the logic makes sense to me and pretty sure it will work. Could you give me a hint on jquery code to clone a template input section? Thanks a lot by the way. this meant alot for me.
Added the code. Bear in mind your controller will have to accept the model and you will have to insert each item in the collection.

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.