views:

149

answers:

1

Using S#arp Architecture 1.0RC...

I have a controller that never seems to update one of my properties.

My class is a User abstract class with a Manager property. Manager is subclasses from User, as is Employee.

I declared the property setter for Manager as protected and provided a method to AddManager. That way, I could also control the Users that a Manager has from the collection in that entity.

My problem is that the ModelBinder doesn't locate the Manager property of the updated item on the postback. If I remove protected, it works fine. Add protected back: no soup for me.

What portion of the following allows me to keep my setter protected and still get the value in the controller on the postback?

Thanks...

Here's the obligatory mapping (some editing out of non-particulars):

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="">
  <class name="Core.User, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Users" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Int32" unsaved-value="0" column="UserId">
        <generator class="identity" />
    </id>
 <le snip..>
<many-to-one access="field.camelcase-underscore" cascade="save-update" name="Manager" column="ManagerId" />
<joined-subclass name="Core.Employee, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
  <key column="EmployeeId" />
</joined-subclass>
<joined-subclass name="Core.Approver, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
  <key column="ManagerId" />
  <bag name="Users" lazy="true" cascade="save-update" inverse="true">
    <key column="ManagerId" />
    <one-to-many class="Core.User, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </bag>
</joined-subclass>

My polymorphic class is

public abstract class User : Entity
{
    public virtual string Name { get; set; }
    private Manager _manager;
    public virtual Manager Manager
    {
        get { return _manager; }
        protected set { _manager = value; }
    }

    public virtual void SetManager(Manager manager)
    {
        if (_manager != null)
        {
            _manager.RemoveUser(this);
        }
        _manager = manager;
    }

}


public class Manager : User
{
    public Manager()
    {
        _users = new List<User>();
    }

    private IList<User> _users;
    public virtual IList<User> Users
    {
        get { return _users; }
        protected set { _users = value; }
    }

    public virtual void AddUser(User user)
    {
        if (_users.Contains(user)) return;
        Users.Add(user);
        user.SetManager(this);
    }

    public virtual void RemoveUser(User user)
    {
        if (!_users.Contains(user)) return;
        Users.Remove(user);
        user.SetManager(null);
    }
}
+2  A: 

You might want to consider use a view-model class instead of passing your domain entities to your views. You could populate your view-model class from your domain query, pass that to your view and when it comes back, in your controller re map it to your domain entity and carry on. A great tool to help you do this very thing is called AutoMapper. This may also help with other issues down the road.

AutoMapper on CodePlex

Ryan Montgomery
Thanks, Ryan. I will give AutoMapper a look right now and report back how it worked for this... Appreciated!
Kurt Johnson
+1: Always use view models.
Craig Stuntz
This is my answer. I already see where AutoMapper will benefit me.One note: I should have clarified that I *was* using a ViewModel class in my controller and in passing to my page -- that's the best way I know to send SelectList items that exist outside of my entity.
Kurt Johnson