I’m using ASP.NET MVC 2.

Keeping it simple, I have three payment types: credit card, e-check, or “bill me later”. I want to:
- choose one payment type
- display some fields for one payment type in my view
- run some logic using those fields (specific to the type)
- display a confirmation view
- run some more logic using those fields (specific to the type)
- display a receipt view
Each payment type has fields specific to the type… maybe 2 fields, maybe more. For now, I know how many and what fields, but more could be added. I believe the best thing for my views is to have a partial view per payment type to handle the different fields and let the controller decide which partial to render (if you have a better option, I’m open). My real problem comes from the logic that happens in the controller between views. Each payment type has a variable number of fields. I’d like to keep everything strongly typed, but it feels like some sort of dictionary is the only option. Add to that specific logic that runs depending on the payment type.
In an effort to keep things strongly typed, I’ve created a class for each payment type. No interface or inherited type since the fields are different per payment type. Then, I’ve got a Submit() method for each payment type. Then, while the controller is deciding which partial view to display, it also assigns the target of the submit action.
This is not elegant solution and feels very wrong. I’m reaching out for a hand. How would you do this?
It’s one for thing for, say, an
Orderobject to not really care about the particular payment type–just knowing that there is aPledgedAmountand aDepositedAmountproperty, for example, is enough for that class to do its job (e.g., “don’t allow myself to go to Shipped status if order is not charged, via whatever payment method, I don’t really care, as long as it’s charged somehow I’m cool”).It’s another thing for the UI to not really care: you either write a
switchto load the right view and be done with it, or you end up creating a dictionary-like collection of fields, rules, and validation metadata and let the UI generate itself dynamically.For example, I took the latter approach when I was adding international address support for one of my applications. I abstracted addresses into a common set of fields:
AdministrativeArea,Municipality, etc, and defined anAddressSchemeclass which definedAddressFieldRules for each field, stating whether or not it was required, if a regex should be applied, if there is a specific set of allowed values, etc. It was appropriate since we could add or remove countries to the allowed list at any time without recompiling and redeploying the application; the UI could dynamically generate itself based on theAddressScheme, which itself was loaded from the database. Sweet.But are you really going to be adding payment types (a) with great frequency or (b) without re-compiling your application? Sometimes you really do need an actual Toaster instead of a Breakfast Cooking Machine w/ Bread and Other Yeast-Based Goods Browning Module, so just add a switch or a dictionary that maps a type to the correct view: I think it’s perfectly acceptable for the UI to have to be able to distinguish among these types, and, more importantly, for you to custom-write and tailor the presentation of each type–but the higher-up parts might benefit from some abstraction. I talked about that in my answer to a different question related to billing.
In your example, you can share common code for steps 1, 4, and 6, but delegate to specific UI methods and views for steps 2, 3, and 5. And the world will still spin round.
My two cents. Good luck!