Hi All,

Sorry if this is a n00b thing to ask - I've only been into DotNet/C#
for about two weeks.

But basicly what I am trying to do is expose DAO's throught WCF
services.

The problem is when I try to call the Service from the client I get
the following exception : Test method
jTekPos.Client.RemoteProxy.Tests.UserProxy_Fixture.Can_We_Lookup_A_Member
threw exception:  System.ServiceModel.FaultException`1
[System.ServiceModel.ExceptionDetail]: No persister for: User.

I believe ( from what I have googled ) that it has something to do
with the Serializer not serializing the references properly, But I
have spent way to long googling and really need some help now.

My User.cs is defined here :

[code]
namespace jTekPos.Data.Model
{
    [Serializable]
    [DataContract]
    [ActiveRecord("usrs")]
    public class User : ActiveRecordBase<User>
    {
        [DataMember]
        [PrimaryKey("user_id")]
        public int UserId { get; set; }

        [DataMember]
        [Property("user_name")]
        public String Username { get; set; }

        [DataMember]
        [Property("pass_word")]
        public String Password { get; set; }

        [DataMember]
        [Property("firstname")]
        public String Firstname { get; set; }

        [DataMember]
        [Property("surname")]
        public String Surname { get; set; }

        [DataMember]
        [HasAndBelongsToMany(typeof(Role),
            Table = "usr_role_link", ColumnKey = "user_id", ColumnRef
= "role_id",
            Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy =
true)]
        public IList<Role> Roles { get; set; }
    }
}
[/code]

My Role.cs is defined here :
[code]
namespace jTekPos.Data.Model
{
    [Serializable]
    [DataContract]
    [ActiveRecord("user_role")]
    public class Role : ActiveRecordBase<Role>
    {
        [DataMember]
        [PrimaryKey("role_id")]
        public int RoleId { get; set; }

        [DataMember]
        [Property("role_name")]
        public String RoleName { get; set; }

        [DataMember]
        [Property("role_desc")]
        public String RoleDescription { get; set; }

        [DataMember]
        [HasAndBelongsToMany(typeof(User),
            Table = "user_role_link", ColumnKey = "role_id", ColumnRef
= "user_id",
            Inverse = true, Cascade =
ManyRelationCascadeEnum.SaveUpdate, Lazy = true)]
        public IList<User> Users { get; set; }

        [DataMember]
        [HasAndBelongsToMany(typeof(Permission),
            Table = "role_perm_link", ColumnKey = "role_id", ColumnRef
= "perm_id",
            Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy =
true)]
        public IList<Permission> Permissions { get; set; }
    }
}
[/code]


The DAO that I expose (UserDAO.cs) :
[code]
namespace jTekPos.Data.AccessObject
{
    [ServiceContract(Namespace="www.#####co.za/jTekPos/
DataAccessObject/User")]
    [ServiceBehavior(IncludeExceptionDetailInFaults=true,
MaxItemsInObjectGraph=1000)]
    public class UserDao : StandardDao<User>
    {
        [OperationContract]
        [PreserveCircularReferences]
        public virtual User FindUserById( int id )
        {
            return GetSingleResultFromCriteria
(MakeOneParamSimpleEqCriteria("Id", id));
        }

        [OperationContract]
        [PreserveCircularReferences]
        public virtual User FindUserByUsername(String username)
        {
            return GetSingleResultFromCriteria
(MakeOneParamSimpleEqCriteria("Username", username));
        }
    }
}
[/code]

The UserDao extends StandardDAO.cs thats this :
[code]

namespace jTekPos.Data.AccessObject
{
    public abstract class StandardDao<T>
    {
        public readonly ISession _Session;
        public T _BaseEntity;

        public StandardDao()
        {
            ISessionFactory factory =
                ObjectFactory.GetInstance<ISessionFactory>();
            _Session = factory.OpenSession();
            _BaseEntity = (T)
                typeof(T).GetConstructor(new Type[]{}).Invoke(new
Object[]{});
        }

        public ICriteria MakeCriteria()
        {
            return _Session.CreateCriteria(typeof(T).Name);
        }

        public ICriteria MakeOneParamSimpleEqCriteria(String
PropertyName, Object Value)
        {
            ICriteria crit = MakeCriteria();
            crit.Add(Restrictions.Eq(PropertyName, Value));
            return crit;
        }

        public T GetSingleResultFromCriteria(ICriteria iCrit)
        {
            iCrit.SetMaxResults(1);
            IList<T> lst = iCrit.List<T>();
            if (lst == null || lst.Count == 0)
                return default(T);
            return lst[0];
        }
    }
}

[/code]

I followed an Microsoft article recommending me to create these
(supposed to help the dataContractSerializer preserver my
references) :

[b]OpBehaviourPreserveRefs.cs[/b]
[code]
public class OpBehaviourPreserveRefs :
DataContractSerializerOperationBehavior
    {
         public OpBehaviourPreserveRefs ( OperationDescription
operationDescription) : base(operationDescription) { }

         public override XmlObjectSerializer CreateSerializer( Type
type, string name, string ns, IList<Type> knownTypes)
         {
            return CreateDataContractSerializer(type, name, ns,
knownTypes);
         }

         private static XmlObjectSerializer
CreateDataContractSerializer( Type type, string name, string ns,
IList<Type> knownTypes)
         {
            return CreateDataContractSerializer(type, name, ns,
knownTypes);
         }

         public override XmlObjectSerializer CreateSerializer( Type
type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type>
knownTypes)
         {
             return new DataContractSerializer(type, name, ns,
knownTypes, 0x7FFF, false, true, null);
         }
    }
[/code]

[b]The attribute : [/b]
[code]
  public class PreserveCircularReferencesAttribute : Attribute,
IOperationBehavior
    {
        public void AddBindingParameters(OperationDescription
description, BindingParameterCollection parameters) { }

        public void ApplyClientBehavior(OperationDescription
description, ClientOperation proxy) {
            IOperationBehavior innerBehavior =
              new OpBehaviourPreserveRefs(description);
            innerBehavior.ApplyClientBehavior(description, proxy);
        }

        public void ApplyDispatchBehavior(OperationDescription
description, DispatchOperation dispatch)
        {
            IOperationBehavior innerBehavior =
              new OpBehaviourPreserveRefs(description);
            innerBehavior.ApplyDispatchBehavior(description,
dispatch);
        }

        public void Validate(OperationDescription description) { }
    }
[/code]

And Then to host these I tried the standard selfHost option, and tried
the WcfIntegration package from Castle :

[b]IServiceHostCache.cs[/b]
[code]
 public abstract class IServiceHostCache
    {
        public const String URI_TEMPLATE =
            "http://${BindAddress}:${Port}/jtek/wcf/${ServiceType}/$
{ServiceName}";

        public IList<Object> RunningServiceHosts =
            new List<Object>();

        public abstract void HostService(String ServiceName, String
ServiceType, Type ServiceContractImpl);

        public Uri GenerateServiceUri(string ServiceName, string
ServiceType)
        {
            return new Uri(URI_TEMPLATE
                .Replace("${BindAddress}", "localhost")
                .Replace("${Port}", "8000")
                .Replace("${ServiceType}", ServiceType)
                .Replace("${ServiceName}", ServiceName));
        }

        public abstract void Destroy();
[/code]

[b]Standard WCF impl:[/b]
[code]
 public class WcfBasedServiceHostCache : IServiceHostCache
    {
        public override void HostService(String ServiceName, String
ServiceType, Type ServiceContractImpl)
        {
            Uri uri = GenerateServiceUri( ServiceName, ServiceType );
            ServiceHost host =
                new ServiceHost( ServiceContractImpl , uri );
            try
            {
                host.AddServiceEndpoint(
                    ServiceContractImpl,
                    new WSHttpBinding(),
                    ServiceName);
                ServiceMetadataBehavior httpGetBehaviour =
                    new ServiceMetadataBehavior();
                httpGetBehaviour.HttpGetEnabled = true;
                host.Description.Behaviors.Add( httpGetBehaviour );
                host.Open();
                RunningServiceHosts.Add(host);
            }
            catch (CommunicationException ce)
            {
                host.Abort();
                throw new Exception("Something Bad Happened", ce);
            }
        }

        public override void Destroy()
        {
            foreach (ServiceHost host in RunningServiceHosts)
            {
                host.Close();
            }
            this.RunningServiceHosts.Clear();
        }
    }
[/code]

[b]The Windsor Impl[/b]
[code]
public class WindsorServiceHostCache : IServiceHostCache
    {
        public override void HostService(String ServiceName, String
ServiceType, Type ServiceContractImpl)
        {
            Uri uri = this.GenerateServiceUri(ServiceName,
ServiceType);
            DefaultServiceHostFactory.RegisterContainer
(((IWindsorContainer) ObjectFactory.FetchDelegate()).Kernel);
            DefaultServiceHost host =
                new DefaultServiceHost(ServiceContractImpl, uri);
            try
            {
                host.AddServiceEndpoint(
                    ServiceContractImpl,
                    new WSHttpBinding(),
                    ServiceName);
                ServiceMetadataBehavior httpGetBehaviour =
                    new ServiceMetadataBehavior();
                httpGetBehaviour.HttpGetEnabled = true;
                host.Description.Behaviors.Add(httpGetBehaviour);
                host.Open();
                RunningServiceHosts.Add(host);
            }
            catch (CommunicationException ce)
            {
                host.Abort();
                throw new Exception("Something Bad Happened", ce);
            }
            this.RunningServiceHosts.Add(host);
        }

        public override void Destroy()
        {
            foreach (DefaultServiceHost host in
this.RunningServiceHosts)
            {
                host.Close();
            }
            this.RunningServiceHosts.Clear();
        }
    }
[/code]

[b]My Application Configuration[/b]
[code]
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="castle"
 
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
Castle.Windsor" />
  </configSections>

  <castle>
  <facilities>
    <!-- NHibernate Active Record Facility -->
    <facility
        id="arfacility"
 
type="Castle.Facilities.ActiveRecordIntegration.ActiveRecordFacility,
Castle.Facilities.ActiveRecordIntegration"
        isDebug="true"
        isWeb="false">
      <assemblies>
        <item>jTekPos.Data.Model</item>
      </assemblies>
      <config>
        <add key="connection.driver_class"
value="NHibernate.Driver.MySqlDataDriver" />
        <add key="dialect" value="NHibernate.Dialect.MySQLDialect" />
        <add key="connection.provider"
value="NHibernate.Connection.DriverConnectionProvider" />
        <add key="connection.connection_string"
value="Database=jtekposclientdb;Data Source=localhost;User
Id=root;Password=mrozio" />
        <add key="proxyfactory.factory_class"
value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory,
NHibernate.ByteCode.LinFu" />
        <add key="hbm2ddl.keywords" value="none" />
      </config>
    </facility>

    <!-- ActiveRecord Automatic Transaction Management -->
    <facility
           id="atm"
 
type="Castle.Facilities.AutomaticTransactionManagement.TransactionFacility,
Castle.Facilities.AutomaticTransactionManagement" />
  </facilities>
  </castle>
</configuration>
[/code]

And the remote client I use is basicly the selfgenerated code from
that svcutil.exe thing.

Sorry for asking you guys for help - But I have been struggling with
this whole project setup the whole of today and yesterday.

Please if I'm posting in the wrong place - just lemme know.

[/code]

--

You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-users?hl=en.


Reply via email to