Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Assumptions:

  • Minimalist ASP.NET MVC 3 application for sending emails where the view represents the contents of an email.
  • Over 500+ email types. I would NOT like to have 500+ actions in my controller corresponding to each email type.
  • Email types are stored in an enum named MailType, so we could have:
    • MailType.ThankYouForYourPurchase, MailType.OrderShipped, etc.
  • The view name is the same as the mailType name:
    • MailType.OrderShipped would have a corresponding view: OrderShipped.cshtml
  • Some views would directly use an Entity while others would use a ViewModel.

So, given that I have 500+ email types, what is the best way/pattern to organize my application?

Here is what I was thinking,

Controller:

    public class MailController : Controller
    {
        public ActionResult ViewEmail(MailType mailType, int customerId)
        {
            string viewName = mailType.ToString();

            var model = _mailRepository.GetViewModel(mailType, customerId);

            return View(viewName, model);
        }

        public ActionResult SendEmail(MailType mailType, int customerId)
        {
            ...
        }
    }

MailRepository Class:

    public class MailRepository
    {
        private readonly CustomerRepository _customerRepository;
        private readonly OrderRepository _orderRepository;

        //pretend we're using dependency injection
        public MailRepository()
        {
            _customerRepository = new CustomerRepository();
            _orderRepository = new OrderRepository();
        }

        public object GetViewModel(MailType mailType, int customerId)
        {
            switch (mailType)
            {
                case MailType.OrderShipped:
                    return OrderShipped(customerId);
                case MailType.ThankYouForYourPurchase:
                    return ThankYouForYourPurchase(customerId);
            }

            return _customerRepository.Get(customerId);
        }

        public Order OrderShipped(int customerId)
        {
            //Possibly 30 lines to build up the model...
            return _orderRepository.GetByCustomerId(customerId);
        }

        public Customer ThankYouForYourPurchase(int customerId)
        {
            return _customerRepository.Get(customerId);
        }
    }

But then this would lead to my MailRepository class becoming extremely large unless I somehow broke it up...

share|improve this question
    
"Some views would directly use an Entity while others would use a ViewModel" -- can you elaborate on exactly how this happens or at least what the ground rules are? Everything else is a pretty easy convention/mapping exercise. –  Wyatt Barnett Oct 25 '11 at 0:58
    
If you're not comfortable writing hundreds of actions for all of the mail types (perfectly understandable) then you probably shouldn't be comfortable writing hundreds of views, either, as that's going to be a lot more work than the controller actions. Surely you can generalize a lot of this? An e-mail message is just a subject, recipient list, and body, right? Can this really not be done in half a dozen or so views? –  Aaronaught Oct 25 '11 at 2:26
    
@WyattBarnett I think by entity he means a class, and by ViewModel he means a class only needed for displaying the page(View). –  e-MEE Oct 25 '11 at 5:29
    
@e-MEE gotcha but the question still stands -- you need to know how you are picking the data; once you've got that logic to pick the right template is relatively straightforward. –  Wyatt Barnett Oct 25 '11 at 13:26

2 Answers 2

up vote 3 down vote accepted

To avoid any one class getting too big you need to be mapping mail types to classes rather than method names - pick a naming convention like MailControllers.OrderShippedController and load the class with reflection.

I'd also note that your MailRepository seems to be behaving more like a controller - not a major issue, but something that could become confusing later.

share|improve this answer
    
Assuming there are 500+ views, each view corresponding to a mail type, is your suggestion to create a class corresponding to each view? I'm just really looking for a way to not have so much code and somehow use some conventions to abstract away much of the code. –  Randy Burden Oct 25 '11 at 16:41
    
Nothing in your question indicates what, if anything is shared between the views. However, it is reasonably easy to find the class based on the view name rather than using a switch statement, and it is a lot easier to deal with 500 classes than with 500 methods in one class. If the data is the same across two classes, use inheritance - there is still a class for each view (so easy to find) but one of those classes is only one line. –  Tom Clarkson Oct 25 '11 at 23:17
    
I agree that your suggestion would make managing the code easier. Thank you for your comments. –  Randy Burden Oct 26 '11 at 0:58

@Tom Clarkson answer is good. Additionally, if you are not already doing so, you could use an IOC Container such as Spring.NET for example to declare a "MailTypeRetriever" bean. The only parameter in the constructor of this bean should be a map (dictionary) with the key being the mail type, and the value the name of the method to call.

That way your mail type configuration is not in your code, and the code for calling the right method will be short. Of course, you don't need Spring for externalizing your mail type configuration, that's just one way of doing it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.