开发者

MVC2 confusion over when to use viewmodels or domain objects

开发者 https://www.devze.com 2023-03-14 20:33 出处:网络
After following the tutorial is Steve Sandersons pro asp.net framework book I have managed to get basic editing and display functionality for two database objects using the repository pattern.

After following the tutorial is Steve Sandersons pro asp.net framework book I have managed to get basic editing and display functionality for two database objects using the repository pattern.

I am having problems when i want to display/update properties from multiple objects.

I am aware that viewmodels are a way to do this but im confused as to when i should use a viewmodel and how they fit in with my domain model objects.

For example for my two objects i have repository's and the following methods to return each list of the objects

public IQueryable<Customer> Customers
    {
        get { return customersTable; }
    } 

public IQueryable<CustomerSite> CustomerSites
    {
        get { return customerSitesTable; }
    }

Then in my controller im passing the objects from the repository to the view like

 public ViewResult List([DefaultValue(1)] int page)
    {
        var customerSitesToShow = customerSiteRepository.CustomerSites;
        var customersToShow = customerRepository.Customers; 
        var viewModel = new CustomerSitesListViewModel
        {

            CustomerSites = customerSitesToShow.Skip((page - 1) *  PageSize).Take(PageSize).ToList(),
            customers = customersToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),

            PagingInfo = new PagingInfo
            {
                CurrentPage = page,
                ItemsPerPage = PageSize,
                TotalItems = customerSitesToShow.Count()
            }
        };

        return View(viewModel);  //Passed to view as ViewData.Model (or simply model)
    }

}

I now understand i can use a viewmodel to access properties for two objects in one view so i have one viewmodel with properties for my two objects

{
public class SiteViewMode开发者_运维技巧l
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public string AddressLine1 { get; set; }
}

public class CustomerViewModel
{
    public int Id { get; set; }
    public string CustomerName { get; set; }
    public string PrimaryContactName { get; set; }
    public SiteViewModel Site { get; set; }
}

}

Then a master view model that i strongly type to a display template

public class CustomerSitesListViewModel
{
    public IList<CustomerSite> CustomerSites { get; set; }
    public PagingInfo PagingInfo { get; set; }
    public IList<Customer> customers { get; set; }
    public CustomerViewModel Customers { get; set; }
}

When i run this the display template is rendered but my customer collection is empty as i think i need a LINQ join statement to retrieve both the list of customers and the customer sites? Is a LINQ join the best way to do this? so i can access both objects from the display template like

<%= Html.DisplayFor(x => x.Customers.CustomerName) %>
<%= Html.DisplayFor(x => x.Customers.Site.AddressLine1) %>

This is where i get more confused, where should the method containing the LINQ query to return the customer collection should go, should this be in the repository or the view model?


From what I understand you're confusing two different responsibilities the domain objects have and the one of the view model.

I don't see very well your model. Does the Customer has one site or more? What's the relationships between them? From my point of view what you can do a the repository level, do it at that level. So I would return a Customer with it's Site directly from the repository because you can aggregate data at repository level with joins and return it in one round-trip to the database.

Why bother returning two separate entities Customer and CustomerSite as you know that you need them agregated in your view ? You're creating more problems then necessary.

So returning Customer and Site from the repository at once, could be after mapped to the flat view model object for example called CustomerWithSite. For that you can use AutoMapper(http://automapper.codeplex.com/). You can have also a "special" repository for views that already returns an object formated for the view that is issue from the queries and projections in the repository. It's up to you. But don't use your domain object for the view purpose.

I also would not expose IQueryable outside my repository. You will get yourself in trouble. Because once, you enable other layers to manipulate your queries, the repository is no longer responsible about what is returned. Then some developpers would attempt to manipulate Iqueryable in the view, but the drawback is that it needs the connection to the database open. Not very good desgn from my point of view to keep the connection open for that. What if connection is closed before ? You would get Disposed exception while displaying objects on the view. No very good. Think also about testability.

I don't know if it's clearer for you but be aware of the shortcomings I'm talking about.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号