English 中文(简体)
Accessing domain objects in the view
原标题:

If I don t want to expose the internal state of my Domain Objects, but I need to display them, I can think of three approaches. Which of these is the most "correct" (if any?).

  1. The "DTO/ViewModel approach". This seems to be a popular approach in the ASP.NET MVC world (especially with the use of AutoMapper).
  2. The "decorator approach". If I have a "Customer" entity, I decorate it with a "DisplayableCustomer" who can access the internal state of the customer (in most languages that I ve dealt with).
  3. The "interface approach". Where I do something like this:

    class Customer {
        ....
        public void renderWith(CustomerRenderer renderer) {
             renderer.renderCustomer(address,name);
        } 
    }
    
    interface CustomerRenderer {
        public void renderCustomer(Address address, Name name);
    }
    
最佳回答

I vote for, and widely use, your #1 option. Several reasons why:

  • Allows for complex view models, like combining multiple lists of my domain objects. Think a PostViewModel with a Post element and an IList container hanging off of it.
  • On my current project, we have abstracted the domain validation to where it bubbles up into our custom ViewModels, and do some slick Ajax-validation on forms.
  • While the concept doesn t directly expose your domain objects on the Model, I have no problem hanging Post off of a property of my PostViewModel.

The last point is why the ViewModels concept really exists. It s no violation of DDD to expose your Domain object all the way up to your UI or even the view - this is by designed and expected of DDD and UI concepts. You only expose objects from your domain to use, and lock in/persist their states with services and infrastructure. So, you are in no violation of using the actual Domain object in your UI.

It s when you involve MVC concepts for your UI, and trying to render that specific View of a page/location. You may (and will) have additional display elements that may not be related to the Domain at all, like a Progress Bar that is only for the UI. A progress bar is a concern only for the UI and APplication layer. It has nothing to do with your domain.

So, the DDD solution I accept is to use a hybird object in the Application/UI layers that can hold a number of objects: both Domain objects and Application objects to render for that one specific View. This is the concept of a ViewModel, at its core reason of being.

The ViewModel concept can be thought of as your Application Layer non-business objects in DDD terms.


Going off topic a little and talking about one specific technology, ASP.NET MVC has additional features to help make this concept work together nicely. It s not directly built into ASP.NET MVC, but is available as an additional assembly from Microsoft called the Futures project.

Check out my blog post about a couple of features, the single most useful feature is the RenderAction extension method:

http://eduncan911.com/blog/html-renderaction-for-asp-net-mvc-1-0.aspx

This is an extremely powerful concept that spins up the underlying controller and calls the action method. Doing this greatly simplified our ViewModels to only care about the View they are rendering. I no longer have to attach things like sidebar controls or other common data boxes, navbars, etc that have nothing to do with the View.

RenderAction is different then RenderPartial for pure DDD reasons: It lets you move the business logic back into a Controller, where it belongs. And the controller calls the proper view to render it s display. This strictly follows both DDD and MVC concepts.

Microsoft has stated that RenderAction will be part of ASP.NET MVC 2.0 when it is released next year.

Sorry for the rant...

问题回答

暂无回答




相关问题
WebForms and ASP.NET MVC co-existence

I am trying to make a WebForms project and ASP.NET MVC per this question. One of the things I ve done to make that happen is that I added a namespaces node to the WebForms web.config: <pages ...

Post back complex object from client side

I m using ASP.NET MVC and Entity Framework. I m going to pass a complex entity to the client side and allow the user to modify it, and post it back to the controller. But I don t know how to do that ...

Create an incremental placeholder in NHaml

What I want to reach is a way to add a script and style placeholder in my master. They will include my initial site.css and jquery.js files. Each haml page or partial can then add their own required ...

asp.net mvc automapper parsing

let s say we have something like this public class Person { public string Name {get; set;} public Country Country {get; set;} } public class PersonViewModel { public Person Person {get; ...

structureMap mocks stub help

I have an BLL that does validation on user input then inserts a parent(PorEO) and then inserts children(PorBoxEO). So there are two calls to the same InsertJCDC. One like this=>InsertJCDC(fakePor)...

ASP.NET MVC: How should it work with subversion?

So, I have an asp.net mvc app that is being worked on by multiple developers in differing capacities. This is our first time working on a mvc app and my first time working with .NET. Our app does not ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...

热门标签