1

In a heavy enviroment application, we have Users, Locations, bla bla bla... and we use in many situations a call to a service where we retrieve the list of countries.

Where is the 'best practice' or 'proper way' to implement this. This method is called in several places and many objects has a List<CountryVO> property.

Specially considering using Razor views an often having to add this property to ModelViews

The solution is using DAL / BLL / SERVICE / UI[s] architecture.

Real Example:

public class User {
...
...
public List<DeliveryZoneVO> DeliveryZones {get;set;}
    public User() {
    ...
        DeliveryZones = service.GetDeliveryZones().ToList();
    }
}

The class DeliveryZoneVO comes from a webservice, so one property is

int IdCountry

The class User have a list of DeliveryZoneVO as presented on the class, the 'problem' here, is since it retrieves the data from a web service, I only have the ID of the country.

When I prepare the data in the controller to send to the View:

UserModelView userMV = new UserModelView();
userMV.user = service.GetUserById(1);
ViewData.Model = userMV;

BUT, inside userMV.user, I have DeliveryZones with a list of DeliveryZoneVO objects with IdCountries.

In the view, when I do (for example) :

@DisplayFor(m => m.user.DeliveryZones)

I want to show the Country Name, only have the ID. So i need a reference somewhere.. the question lies in where should that data needs to be placed that is considered BEST PRACTICES.

Is having in all modelview (in the case of the example, the UserModelView() the property Countries with a List ?

Bart Calixto
  • 19,210
  • 11
  • 78
  • 114

2 Answers2

1

I would create a partial view that is responsible for just rendering the country list. Then any changes to how the list is rendered is can be made in just one place. I would create a model class that encapsulates calling the service to get the countries. Assuming that the country list is fairly static you could handle caching of the information in the model class for less calls to the service and better performance. Below is an example of a method in the model that gets the country list from the server cache if it is available.

    const string cacheId = "deliveryZones";

    public List<DeliveryZoneVO> GetDeliveryZones()
    {
        List<DeliveryZoneVO> deliveryZones = (List<DeliveryZoneVO>)HttpRuntime.Cache.Get(cacheId);
        if (deliveryZones == null)
        {
            deliveryZones = service.GetDeliveryZones().ToList();
            System.Web.HttpContext.Current.Cache.Insert(cacheId, deliveryZones);
        }
        return deliveryZones;

    }
Kevin Junghans
  • 17,475
  • 4
  • 45
  • 62
  • i dont need to only display the country list, some objects have a idCountry attribute and I need to get the (for example) country name. So if I display a list of address of a contact, I want to display the country name for them. – Bart Calixto Jan 25 '12 at 20:19
  • I guess I do not understand what the question is then. What specifically are you trying to achieve with the correct answer? – Kevin Junghans Jan 25 '12 at 20:33
  • Something like in a ModelView have the an object with DeliveryZones with a list of ids, then when I iterate the DeliveryZones ( I have deliveryZone.IdCountry ) but i want to display something like Country[idCountry].name since this is based on services. This Country object I use everywhere, and also doesn't change much. So i don't want to call a service for countries everytime, and also do I have to define it in every ModelView ? is that ok? – Bart Calixto Jan 25 '12 at 20:45
  • I know some ways to accomplish the task, this is not a problem. The question is about Best Practices, not getting it done. – Bart Calixto Jan 25 '12 at 20:46
1

A good thing because this kind of issues is to have a BaseController class that derived from controller, and all the other controllers you have derived from it.

in the BaseController put a static List<CountryVO> property with getter only, this way it will be initialized once and will be accessible to all of your's controllers and views(If you pass it with the ViewModel or ViewBag).


Example:

public class BaseController : Controller
{
    private static List<CountryVO> _allCountries;

    public static List<CountryVO> AllCountries
    {
        get{ return _allCountries ?? _GetCountriesFromSomeWhere();}
    }       
}

public class HomeController : BaseController 
{
    public ActionResult Index()
    {
        ViewBag.AllCountries  = this.AllCountries;          
        return View();
    }
}
gdoron
  • 147,333
  • 58
  • 291
  • 367
  • That's a good option for a fairly small site I guess, but since this is a big / heavy website, I don't want that country list in ALL controllers and views. Actually, sometimes I don't to even want to call the service. Even this is a common property, it shouldn't be a global one. Maybe someway to decorate a controller? Don't know if that will work or how. – Bart Calixto Jan 25 '12 at 21:04
  • 1. It will be in the only views you sent it. 2. It will be a "service" that you can use from all of your's controllers, But you don't have to call it. It will be initialized only once for any number of controllers! – gdoron Jan 25 '12 at 21:08
  • Can you elaborate a little bit more? – Bart Calixto Jan 26 '12 at 03:11
  • Excellent! Just for anyone else : return _allCountries ?? _allCountries = GetCountriesFromSomeWhere(); should be return _allCountries ?? GetCountriesFromSomeWhere(); – Bart Calixto Jan 26 '12 at 12:32