Phillip Schmidt
Phillip Schmidt

Reputation: 8818

Accepting two models as action method parameters

I'm developing a site in MVC, and I have a payment form which includes customer information as well as payment information. I'm not storing payment info in my database, so I don't want to add any of it to my customer info model. It'd be nice if I could do something like this:

public void PaymentConfirmation(CustomerInfo customer, PaymentInfo payment)
{
    //do stuff
}

But I don't think the mvc model binder does anything like that by default. What's the best practice for handling situations like this?

Upvotes: 0

Views: 51

Answers (1)

Tommy
Tommy

Reputation: 39807

I am assuming that when you say

I'm not storing payment info in my database, so I don't want to add any of it to my customer info model.

What you mean is that your customer model is a domain model (generated from EF or some other ORM). If not using an ORM, the single responsibility principle still comes into play in that PaymentInfo is really not related to the CustomerInfo and should have its own base class. Not combining these into a big "do everything" class makes sense.

What you can do, however, is create a ViewModel for this particular view that contains all of the information that you need. This will not cause a DB change and is, basically, a simple wrapper for all the data that is needed by the view to do whatever it does. A basic example would be

public class PaymentConfirmationViewModel{

    public CustomerInfo Customer {get;set;}

    public PaymentInfo Payment {get;set;}

}

As you can see, we are wrapping two stand alone classes into one for consumption by the view/action result. However, using View Models allows you to completely customize and restrict/add the information that is available to your view. Meaning, if there are properties on the domain model that the view does not need, then don't make them part of the view model.

Now, your controller method would be

public void PaymentConfirmation(PaymentConfirmationViewModel model)
{
    //do stuff
}

The only other item you would need to change is your view, in that your Html Helpers would need a slightly different lambda expression (random example).

@Html.LabelFor(x=>x.FirstName) 

would become

@Html.LabelFor(x=>x.Customer.FirstName)

If you are manually creating your input fields in raw HTML, the the following updates would occur.

<input type="text" id="FirstName" name="FirstName" />

would become (note the underscore in the ID attribute of the input field)

<input type="text" id="Customer_FirstName" name="Customer.FirstName" />

Upvotes: 1

Related Questions