mardi 30 juin 2015

MVC manually serializing complex object or model binding

One of the largest issues I run into in MVC is when I attach a complex property (view model) to my model to use on a form. For example, I have a model called Customer.cs. This Customer has ( for simplicity sake ) 1 order at any time. So I give him a property of Customer.Order. The Customer has many other properties defining him as a unique customer. The Order property has a set of unique properties itself. So I’m rolling along, building my Controller, other model values, and finally I start working out my View details.
I start by defining the Form itself.

@using (Html.BeginForm("Customer", "Home", FormMethod.Post, new { @id = "customerForm" })

This form declaration basically tells the View that when a user clicks Submit, everything within this form should be serialized and sent to the Controller. First, I create a view for my main model, Customer.cshtml. It takes in a Customer.cs model.

I create a View specifically for this complex object I’ve created called Order.cshtml. It takes in an Order.cs model (so I can reuse it later on other parent models, such as Invoice because I’m smart and think ahead.) I build my textboxes, dropdown lists, grids, whatever you need it’s there, it’s flashy and it works. So I’ve written all of this javascript and view logic that depends on the view being independent and reusable with other models, etc, etc. My textboxfor declarations look like so:

@Html.TextBoxFor(m => m. OrderDate) 

When I go to click Submit, the first thing I notice is that none of the values from the Order object is posted back. So I sit there and debug and it takes a while but I finally figure out that this will not work this way. Unless there’s a way to serialize the view model separately, then attach it to the parent model, even then you’d have to write a bunch of Javascript to manually override the default form submission process, along with any other model submits you may be making for client-side field validation.
I think there should be an easier way to handle this. I know a way around this issue, but it’s not pretty. You ‘could’ create the view for Order.cs to take in a Customer.cs model instead. Then, use textboxfor declarations like so:

@Html.TextBoxFor(m => m.Order.OrderDate) 

To define all of the properties on the View. This will work with the default binding and all is well. Except, what about the code I’ve already written in JavaScript? I’d have to go through and append “Order_” to all of the references to ID’s laid out on the form. Also, this does not move easily between models now, I’d have to recreate this View each time I create a new model that uses the Order object, since it now takes in the Customer.cs model. I’d also have to rewrite the javascript, or come up with some fancy way to pass in a prefix (ViewData). This doesn’t seem correct. What am I doing wrong?

Aucun commentaire:

Enregistrer un commentaire