Print Page | Close Window

OData and Cocktail?

Printed From: IdeaBlade
Category: Cocktail
Forum Name: Community Forum
Forum Discription: A professional application framework using Caliburn.Micro and DevForce
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3571
Printed Date: 31-Mar-2025 at 1:41am


Topic: OData and Cocktail?
Posted By: pmolijn
Subject: OData and Cocktail?
Date Posted: 08-Aug-2012 at 9:15am

I'm trying to get my head around the caliburn/cocktail framework in regards with OData

I did the following:

    public class ODataService : DataService< EntityManagerProvider<TempHireEntities> >
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("Addresses", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }

Address entity is decorated as follows:

    [System.Data.Services.IgnoreProperties(@"EntityAspect", @"AAAA_EntityAspectForSerialization")]
#if !SILVERLIGHT
    [System.Data.Services.Common.DataServiceKey(@"Id")]
#endif
    public partial class Address : AuditEntityBase, IHasRoot
    {
        // ... body of class untouched from sample
     }
The call at config.SetEntityAccessRule("Addresses", EntitySetRights.All) fails with an ArgumentException.
The given name 'Addresses' was not found in the entity sets.
Parameter name: name
What am I doing wrong here?
Thanks for any answers!
 
Regards,
Patrick



Replies:
Posted By: pmolijn
Date Posted: 08-Aug-2012 at 10:11am
Got a bit further.
Instead of  public class ODataService : DataService< EntityManagerProvider<TempHireEntities> >
I used:  public class ODataService : DataService< TempHireEntities>
 
At runtime complained about a constructor missing. Added TempHireEntities() {} constructor.
Now stuck at following error:
 
The server encountered an error processing the request. The exception message is 'The property 'EntityState' on type 'DomainModel.EntityFacts' is not a valid property. Make sure that the type of the property is a public type and a supported primitive type or a entity type with a valid key or a complex type.'.
 


Posted By: mgood
Date Posted: 08-Aug-2012 at 11:27am
First off, OData is a way to make your server-side domain model available to a non .NET client. There wouldn't be any Cocktail in play. DO NOT USE Cocktail on the server! Cocktail is a client framework. It doesn't work on the server as-is. You will get threading and composition issues.
 
Having said that, you can certainly make any domain model used by a Cocktail client available via OData for other clients. To make the TempHire domain model work with OData, you need to add EntityFacts to the ignored properties list. EntityFacts is a wrapper property that provides "safe" access to EntityAspect and just like EntityAspect, it needs to be ignored by OData.
 


Posted By: pmolijn
Date Posted: 08-Aug-2012 at 1:38pm
Thanks Michael!
 
This is what my question should be;
How to make the TempHire domain model work with OData for my iOS (iPhone/iPad) app consumption?


Posted By: pmolijn
Date Posted: 08-Aug-2012 at 1:50pm
Added

[IgnoreProperties(@"EntityFacts")]

to the EntityBase class,
 
But now I'm getting:
The exception message is 'The property 'EntityState' on type 'IdeaBlade.EntityModel.EntityAspect' is not a valid property. Make sure that the type of the property is a public type and a supported primitive type or a entity type with a valid key or a complex type.'


Posted By: mgood
Date Posted: 08-Aug-2012 at 1:58pm
Don't get rid of the properties you were already ignoring according to your original post. I said ADD EntityFacts to the ignore list, not replace the entire list with just EntityFacts. You still need to ignore the two properties you already had.
 
[IgnoreProperties(@"EntityFacts", @"EntityAspect", @"AAA_EntityAspectForSerialization")]
If it bombs on other properties just keep adding to the ignore list. OData should ignore anything other than your data properties.
 
BTW, my name is Marcel not Michael :-)


Posted By: pmolijn
Date Posted: 08-Aug-2012 at 5:32pm
Thanks Marcel and sorry for calling you Michael.
 
Applied the [IgnoreProperties(@"EntityFacts", @"EntityAspect", @"AAA_EntityAspectForSerialization")]
 
And now it's complaining that it does not have a property of EntityAspect after all for the DomainModel.Address ?????
 
 
The server encountered an error processing the request. The exception message is 'The property 'EntityAspect' is not a valid property name for type 'DomainModel.Address'. Please specify a valid property name.'.
 
It sounded soo simple. Decorate the entity with IgnoreProperties and Dataservicekey and it should work.
 
Just for the record.
This is what I have now:
 
namespace DomainModel
{
    [IgnoreProperties(@"EntityFacts", @"EntityAspect", @"AAAA_EntityAspectForSerialization")]
    [DataServiceKey(@"Id")]
    public partial class Address
    {
    }
}
 

namespace DomainModel
{
    [DataContract(IsReference = true)]
    [ProvideEntityAspect]
    [RequiresAuthentication]

    public abstract class EntityBase
    {
 //  content not altered. TempHire sample class
    }
}

 



Posted By: mgood
Date Posted: 08-Aug-2012 at 8:11pm
Looks like the WCF Data Service struggles with the implicit implementation of EntityAspect. The only way around it I found so far is to explicity implement EntityAspect. Unfortunately, TempHire very deliberately hides EntityAspect. It gives the consumer of the entity way too much power. Looks like in order to use Code-First and OData together, the EntityAspect has to be exposed. Sigh!
 
    public abstract class EntityBase : IEntity
    {
        private EntityFacts _entityFacts;
 
        [NotMapped]
        public EntityFacts EntityFacts
        {
            get { return _entityFacts ?? (_entityFacts = new EntityFacts(this)); }
        }
 
        [DataMember]
        [ConcurrencyCheck]
        [ConcurrencyStrategy(ConcurrencyStrategy.AutoIncrement)]
        public int RowVersion { getinternal set; }
 
        public virtual void Validate(VerifierResultCollection validationErrors)
        {
        }
 
        public EntityAspect EntityAspect
        {
            get { return null; }  // PostSharp will replace body
        }
    }
 


Posted By: pmolijn
Date Posted: 09-Aug-2012 at 6:55am
Excellent!!
This works.
 
Too bad we have to expose the EntityAspect.
 
Thanks Marcel


Posted By: mgood
Date Posted: 09-Aug-2012 at 9:19am
One thing we can do to counter that is to make the property obsolete and hide it from IntelliSense. This way you get warnings if somebody does use it.

    [ProvideEntityAspect]
    [DataContract(IsReference = true)]
    [RequiresAuthentication]
    public abstract class EntityBase : IEntity
    {
        private EntityFacts _entityFacts;
 
        [NotMapped]
        public EntityFacts EntityFacts
        {
            get { return _entityFacts ?? (_entityFacts = new EntityFacts(this)); }
        }
 
        [DataMember]
        [ConcurrencyCheck]
        [ConcurrencyStrategy(ConcurrencyStrategy.AutoIncrement)]
        public int RowVersion { getinternal set; }
 
        public virtual void Validate(VerifierResultCollection validationErrors)
        {
        }
 
        [BeforeSet]
        internal void RemoveWhiteSpace(IEntityPropertySetInterceptorArgs args)
        {
            if (args.EntityProperty.DataType != typeof(string))
                return;
 
            args.Value = ((string) args.Value).Trim();
        }
 
        [Obsolete("DO NOT USE EntityAspect directly. Use EntityFacts instead.")]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public EntityAspect EntityAspect
        {
            get { return null; }
        }
    }



Print Page | Close Window