Author |
Share Topic Topic Search Topic Options
|
pmolijn
Newbie
Joined: 08-Aug-2012
Posts: 6
|
Post Options
Quote Reply
Topic: OData and Cocktail? Posted: 08-Aug-2012 at 9:15am |
I'm trying to get my head around the caliburn/cocktail framework in regards with ODataI 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
|
|
pmolijn
Newbie
Joined: 08-Aug-2012
Posts: 6
|
Post Options
Quote Reply
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.'.
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
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.
|
|
pmolijn
Newbie
Joined: 08-Aug-2012
Posts: 6
|
Post Options
Quote Reply
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?
|
|
pmolijn
Newbie
Joined: 08-Aug-2012
Posts: 6
|
Post Options
Quote Reply
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.'
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
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 :-)
|
|
pmolijn
Newbie
Joined: 08-Aug-2012
Posts: 6
|
Post Options
Quote Reply
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 } }
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
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 { get; internal set; }
public virtual void Validate(VerifierResultCollection validationErrors)
{
}
public EntityAspect EntityAspect
{
get { return null; } // PostSharp will replace body
}
}
|
|
pmolijn
Newbie
Joined: 08-Aug-2012
Posts: 6
|
Post Options
Quote Reply
Posted: 09-Aug-2012 at 6:55am |
Excellent!! This works. Too bad we have to expose the EntityAspect. Thanks Marcel
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
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 { get; internal 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; }
}
}
|
|