Page 1 of 3 123 LastLast
Results 1 to 10 of 25

Thread: Mapping DTOs to Models

  1. #1
    Join Date
    Nov 2006
    Posts
    6

    Default Mapping DTOs to Models

    Spring looks fascinating, look forward to learning more. I have an immediate need that I am trying to see if Spring will fulfill.

    We are using Data Transfer Objects to pass information between our Views and our Controller/Presenter tier. I am looking for a way to automatically convert dtos to models and back. (Something similar to DynaDTO for Java, I think...)

    What I am envisioning is some xml mapping config like the objects node for Spring where I can define that "classA1.classA2.propertyA3 = classB1.propertyB2" for example. Then, in C# code I would say something like

    Model m = Model.GetById(5);
    DTO d = Something.GenerateDTOFromModel(m);

    Is this something that can be handled in Spring somehow? Or does anyone know of any projects out there better suited for this task?

    Thanks...

  2. #2
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi,

    Maybe Spring.DataBinding.DataBindingManager and its use of Spring.Expressions in Spring.Core.dll is what you're looking for.

    Since it's use is only little documented yet, here's a brief description of DataBindingManager. It only describes usage on webpages, but nothing prevents you from using it "standalone".
    Here's a good description of Spring.Expressions.

    I could imagine first defining some xml-format for describing the mapping:

    Code:
    <mappings>
      <mapping src="propertyA1.propertxA2.propertyA3"
                    target=""propertyB1.propertyB2"
      />
      <mapping ...
    </mappings>
    Second, write some code for reading in these mapping-definitions.

    Third, build a DataBindingManager instance with Bindings according to the definitions:
    Code:
    DataBindingManager bindingMgr = new DataBindingManager();
    foreach( Mapping m in mappings )
    {
      bindingMgr.AddBinding( m.Src, m.Target );
    }

    Finally use this bindingMgr instance for mapping the properties:
    Code:
    Model model;
    DTO dto;
    
    // model -> dto
    ValidationErrors errors = new ValidationErrors();
    bindingMgr.BindSourceToTarget( model, dto, errors );
    // examine any errors here
    
    // dto -> model
    ValidationErrors errors = new ValidationErrors();
    bindingMgr.BindTargetToSource( model, dto, errors );
    // examine any errors here
    Let us know, how you are doing. The possibility to externally describing DataBindings has been requested by others as well.

    cheers,
    Erich

  3. #3
    Join Date
    Sep 2004
    Location
    Belgrade, Serbia
    Posts
    613

    Default

    As Erich pointed out, this would be fairly simple to accomplish using our standard data binding framework. You will have to do some of the work (reading the mappings from the config file and creating a manager class that will apply them as necessary), but for the most part all of the heavy-lifting has already been done.

    Let us know if you run into any issues or have some suggestions for improvement of the data binding framework.

    - Aleks

  4. #4
    Join Date
    Nov 2006
    Posts
    6

    Default

    Thank you, this looks terrific.

    I am running a little test to get my feet wet and figure out how to use the tool. I tried the following:

    Code:
    DataBindingManager bindingMgr = new DataBindingManager();
                
                bindingMgr.AddBinding("Email","Text");
    
                Spring.Validation.ValidationErrors e = new Spring.Validation.ValidationErrors();
                bindingMgr.BindSourceToTarget(myClass as IAccount, txtAccountName, e);
    The object that I am passing in as the Source is a class that explicitly implements an Interface. It has two Email properties - one for the class itself, and one as IAccount.Email. Regardless of whether I pass in the class directly or cast it as the Interface, the Email property on the class gets called. In addition, there are specific members on the Interface that are explicitly implemented that I need to reference.

    Any ideas?

  5. #5
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    hi,

    Casting doesn't help in this case - the object you pass is always the same. Internally the passed object is "simply" (sorry Aleks - I know it's a bit more than that;-)) reflected for the property you want to bind.

    I don't believe this works: But have you tried binding to "IAccount.Email" instead of "Email"?

    Otherwise I guess you'll need some kind of delegating proxy - a wrapper that implements the properties of IAccount directly and delegates set/get calls to the real object. There are various proxy generators available in Spring - but I'm afraid I don't know much about them. Hopefully Bruno can help us out on this.

    cheers,
    Erich

  6. #6
    Join Date
    Nov 2006
    Posts
    6

    Default

    I tried IAccount.Email, and it did not work.

    I am guessing there is a way to automate the proxy methodology?

  7. #7
    Join Date
    Oct 2005
    Location
    Belgium
    Posts
    213

    Default

    Interesting topic. I haven't looked on any of the databinding stuff, but is mapping entities also covered somehow?

    I.e.:
    public class MyOtherEntity
    {
    public int Id;
    }

    public class MyModel
    {
    public MyOtherEntity someValue;
    public string someString;
    }

    public class MyModelDto
    {
    string someString;
    int someValueId;
    }
    I want to create the model from the dto. Is it possible to map the MyOtherEntity according it's id, or would be needed to get this working somehow.

    We're currently working on several smart clients and we use Dto's to send our objects over the internet. We make 'full' objects of them on each end of the wire.Mapping the properties is not the most interesting code to write. So perhaps this can help.

  8. #8
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi,

    I'm not sure, if I understand what you want to do. Could you describe a little more detailed, what you are trying to do?

    cheers,
    Erich

  9. #9
    Join Date
    Nov 2006
    Posts
    6

    Default

    Dynamic Proxy update ...

    I tried the following:
    Code:
    ProxyFactory factory = new ProxyFactory(dto);
    IAccount iface = (IAccount)factory.GetProxy();
    Then when I make the call:
    Code:
    Spring.Validation.ValidationErrors e = new Spring.Validation.ValidationErrors();
    bindingMgr.BindSourceToTarget(iface, txtAccountName, e);
    I receive an error: "'Email' node cannot be resolved for the specified root context."

    Am I using the ProxyFactory incorrectly?

  10. #10
    Join Date
    Oct 2005
    Location
    Belgium
    Posts
    213

    Default

    I'll attempt to illustrate it better:

    The 'problem' domain:

    Code:
    public class Car
        {
            public string Note;
            public Person Owner;
            
    public void Start()
            { 
            //starts the car
            }
    
            public void Stop()
            { 
            //stops the car
            }
        }
    
        public class Person
        {
            public int Id;
            public string Name;
        }
    
        public class CarDto
        {
            public int Id;
            public string Note;
            public int OwnerId;
        }
    The cars and persons can be retrieved via a webservice. They are returned in Dto format. You can view the CarDto above. Now I want to use my Domain Model on the client as well, so I can use the business logic both on the server and the client.

    The client changes the owner of a car and commits the changes so all changed objs are send back. (domain->Dto->Internet->|Server|->Dto->Domain->Service/Dao/etc).
    The assembler below is used on the server:
    Code:
      public class CarAssembler
        {
    
            private ICarDao m_carDao;
            private IPersonDao m_personDao;
    
            public CarDto CreateDto(Car domainObj)
            {
                CarDto dto = new CarDto();
                dto.Note = domainObj.Note;
                dto.OwnerId = domainObj.Owner.Id;
                return dto;
            }
    
            public Car CreateDomainObj(CarDto dto)
            {
                Car newCar = new Car();
                newCar.Owner = m_personDao.GetById(dto.OwnerId);
                newCar.Note = dto.Note;
                return newCar;
            }
    
            public Car UpdateDomainObj(CarDto dto)
            {
                Car updatedCar = m_carDao.GetById(dto.OwnerId);
                updatedCar.Owner = m_personDao.GetById(dto.OwnerId);
                updatedCar.Note = dto.Note;
                return updatedCar;
            
            }
        }
    Now my question was : can I use the databinding framework to do this. With the examples I saw here it seemed mapping 'simple' stuff (strings) was no problem. But what about the owner of the updated car as in UpdateDomainObj, can the databindingmanager do this too? Or should I start looking at something else. Writing dto's and assemblers is not the most interesting part of the application.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •