What is the recommended approach for getting multiple-choice lists and displaying them in MVC?

I searched both SO and Google, but did not find a suitable / acceptable answer.
Reference Information:
* Using MVC 4.5
* I have a common Repo<T> , which I use on top of EF5, which, in turn, is accessed by common Service<T>
* I have domain models and view models, and I use Automapper to display between them, this display happens in the Service layer
* In addition, I have my Controllers , which again is as general as possible.

So to the question; I have several scenarios where I need to present a list of options to the user, and they need to select one or more. The parameters are user-specific, so my User domain has a List<Location> , which is their saved locations, and when adding / changing Item they must select at least one Location .

I resist the temptation to get this List<Location> in my controllers because I want to keep them generic and subtle, but at the same time I would prefer not to have two properties in my ItemView model, one for AvailableLocations and one for SelectedLocations , because This model is used not only for adding / changing, but also for search results, etc.

Options:
* You must enter another model to add / change Item , for example. ItemInput ?
* Should I use some kind of custom mapping and get Automapper to get a list of available places?
* In which layer should I get these available locations?

What are people's suggestions for a neat and general approach to this, please?
Many thanks!

+8
c # asp.net-mvc asp.net-mvc-4
source share
2 answers

I would do something like this:

  public IEnumerable<Location> GetLocations() { return db.GetAll(); } 

Then inside your controller (I followed it from the MVC forests):

  ViewBag.Locations = new SelectList(service.GetLocations, "name", "id"); 

(or your own checklist) and put the listing control on the HTML / View page.

I believe this is the best method because the logic is all inside the service. If you put it in your DTO / data model, you may run into this problem:

What happens if you need extra logic to drop locations? i.e. location subfields.

You change your service (or redefine) to reflect new changes, and this logic will go inside the service:

  public IEnumerable<Location> GetLocations(string parent) { return db.GetAll().Where(loc => loc.parentname = parent); } 

ps I never use shared services, the reason I have a service is because some of the data access it provides contains logic that is not intended to be shared with a DAL of a general type.

I could make an interface or an abstract service to make my life a little easier for general operations between services, but as soon as you define a specific UserManagementSerive sure that you say that you want to manage an object in which there are users, and Places and elements, each of which has its own specific functionality?

+2
source share

I do not think that there is only one possible answer to this question.

I would recommend a simple but not very general approach. I would write what is called ViewModels, i.e. Model classes related to your specific representations. Then I get your available locations from the controller and populate the ViewModel instance in your controller using the selected locations.

Basically, I would suggest some services, for example:

 IEnumerable<Location> GetAvailableLocationsForUser(string userName); 

Notice that I used IEnumerable<T> and not IQueryable<T> . Since the implementation actually queries the database, because it is too error prone (at least IMO) if this is the role of the controller for this (remember the deferred execution of IQueryable<T> ). And it returns an instance of the domain, that is, an object, not a map. I personally would not do anything except domain classes at the service level. There may be domain classes not , but, for example, composition of objects. This can help make efficient queries and avoid using lazy loading and delayed execution in controllers. This is useful when the controller needs an entire object graph, not just an entity.

Then I would like to write Models and ViewModels, as shown below, in a web application assembly:

 public LocationModel { ... } public CreateItemViewModel : ItemModel { public List<LocationModel> AssociatedLocations { get; set; } public List<LocationModel> AvailableLocations { get; set; } ... } 
  • Basically, there are models ( ItemModel and LocationModel ) that are objects associated with the web application. This means that in these models there may be some things related to web things, for example, calculated read-only properties or property attributes ( DisplayAttribute ... etc.). I would write these models several times, in fact, because I don’t think that this is something that could be generalized: for example, one view may need to use the navigation property, and another view will not. Thus, this changes the depth of the mapping process depending on the representations that use the model. And I would not use AutoMapper at all (only manual mappers).
  • There are also ViewModels ( CreateItemViewModel ) that are objects associated with a single view (for example, a view that allows you to create an element in this example). The difference between Model and ViewModel is that the ViewModel is associated with one view (and is specified according to that view). On the other hand, models are associated with several views (their namespace will help you find out which views. For example, xxx.Item.Models for models associated with all views in the xxx.Item directory). ViewModels are created from scratch in the controller (or in a separate mapping) based on the domain classes.

In the example above, you could build domain classes that would return AssociatedLocations and AvailableLocations , but for this you would need your service level to know about the web part (I mean, your service interface and domain classes will know which properties are necessary for a certain kind). I'm not sure that these properties are actually associated with one view in your application, but if it is not, you can also create a domain class as a set of objects that return AssociatedLocations and AvailableLocations :

 public ItemExtended : Item { public List<Location> AssociatedLocations { get; set; } public List<Location> AvailableLocations { get; set; } } ItemExtended GetItemExtendedById(long idItem); 
+1
source share

All Articles