Sending an Interface definition over the wire (WCF service) - wcf

I have a WCF service that generates loads Entity Framework objects (as well as some other structs and simple classes used to lighten the load) and sends them over to a client application.
I have changed 2 of the classes to implement an interface so that I can reference them in my application as a single object type. Much like this example:
Is it Possible to Force Properties Generated by Entity Framework to implement Interfaces?
However, the interface type is not added to my WCF service proxy client thingymebob as it is not directly referenced in the objects that are being sent back over the wire.
Therefore in my application that uses the service proxy classes, I can't cast or reference my interface..
Any ideas what I'm missing?
Here's some example code:
//ASSEMBLY/PROJECT 1 -- EF data model
namespace Model
{
public interface ISecurable
{
[DataMember]
long AccessMask { get; set; }
}
//partial class extending EF generated class
//there is also a class defined as "public partial class Company : ISecurable"
public partial class Chart : ISecurable
{
private long _AccessMask = 0;
public long AccessMask
{
get { return _AccessMask; }
set { _AccessMask = value; }
}
public void GetPermission(Guid userId)
{
ChartEntityModel model = new ChartEntityModel();
Task task = model.Task_GetMaskForObject(_ChartId, userId).FirstOrDefault();
_AccessMask = (task == null) ? 0 : task.AccessMask;
}
}
}
//ASSEMBLY/PROJECT 2 -- WCF web service
namespace ChartService
{
public Chart GetChart(Guid chartId, Guid userId)
{
Chart chart = LoadChartWithEF(chartId);
chart.GetPermission(userId); //load chart perms
return chart; //send it over the wire
}
}

Interfaces won't come across as separate entities in your WSDL - they will simply have their methods and properties added to the object that exposes them.
What you want to accomplish you can do using abstract classes. These will come across as distinct entities.
Good luck. Let us know how you decided to proceed.

Related

Configure WCF to deserialize arrays as collections without svcutil

I have a net.tcp WCF service and its client, each in one assembly and sharing another assembly containing the service interface and DTOs.
The client is implemented as a proxy to the service using a Channel instantiated through ChannelFactory:
public ServiceClient : IService
{
IService _channel;
public ServiceClient()
{
_channel = new ChannelFactory<IService>("NetTcp_IService")
.CreateChannel();
}
public DTO ServiceMethod()
{
return _channel.ServiceMethod();
}
}
public class DTO
{
public IList<int> SomeList;
}
As expected, the SomeListfield of the DTO returned by the client is an array but I would like it to be converted by WCF to a List. As you may suspect from the described set-up, I don't use svcutil (or the Add Service Reference dialog for that matter), so I can't use configureType.
I don't want to modify the client proxy to instantiate the List and modify the received DTO in my client proxy because the actual implementation uses a command processor using interfaces resolved through dependency injection at run-time to avoid coupling - and this solution would do the opposite, by requiring the client to perform know service commands.
Therefore, I'm currently using the work-around which modifies the DTO to internally create the List instance:
public class DTO
{
private IList<int> _someList;
public IList<int> SomeList
{
get { return _someList; }
set {
if (value != null)
_someList = new List<int>(value);
else
_someList = new List<int>();
}
}
}
However, I'd rather avoid this. So the question is:
How can I configure the WCF deserialization so that the array is converted to the expected List?
Is there any way to configure the deserialization through the binding either in the App.config or from code upon Channel creation? Maybe through ImportOptions.ReferencedCollectionTypes or CollectionDataContract?
There are 4 ways:
Convert data to List in your save methods on Client side
Change property type:
public IList<int> SomeList;
to
public List<int> SomeList;
Approach you have shown above (changing type on assigment).
Implement IDataContractSurrogate. But you will have to apply a behaviour on client side.

DbContext, EF, & LINQ - Whats the best way to expose methods on DbContext via an Interface?

I am pretty new to EF and DBContext, and so am looking for some advise as to the best way to set out my code for a WCF service using EF, Stored Procs, or SQL.
The Background
I have an MVC3 front end that is hooked up to a WCF service layer for the Data access (Oracle). The actual Data access is via a separate DAO class library.
My goal is to have the service layer consume an interface only, on which it can call a set of methods to return the data. I do not want the service layer aware that we are using EF for the queries, as I may replace the slow EF bits with Stored Procs or plain SQL text as an when required.
Where I'm upto at the moment
I have an Interface for my database IDB, and a concreate implementation of IDB, MyDB, that also implements DBContext. MyDb then has a couple of derived classes called MyStdDB and MySecureDB. When I want the interface, I call my factory method which works out if I need a standard or secure db, and then returns that into my interface variable.
WCF Code:
public List<string> GetAccount() {
IDB _db = DBFactory.GetInstance();
return _db.GetAccount();
}
DBFactory code:
pubilc class DBFactory {
pubilc static IDB GetInstance()
{
if bSecure
return MySecureDB;
else
return MyStdDB;
}
}
So when I want to ask for a query I want to ask _db.GetAccount() within my Service call. At the moment I have added this as an extension method on the IDB interface. The reason for that was to prevent the service seeing my EF entities, and it allows spearation of the qqueries into logical files, eg. Class full of CUSTOMER queries, class full of ACCOUNT queries.
IDB Code:
public interface IDB : IDisposable
{
ObjectContext UnderlyingContext { get; }
int SaveChanges();
}
MyDB Code:
public class MyDB : DbContext, IDB
{
ObjectContext IDB.UnderlyingContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
int IDB.SaveChanges()
{
return SaveChanges();
}
public DbSet<Customer> Customer { get; set; }
}
Extension Method:
public static List<string> GetAccount(this IDB _db)
{
((MyDB)_db).Customer.AsNoTracking().First();
}
The Issue
As you may see, I have to cast the interface into the concrete object so that I can get to the EF entities. This is because the entities are on the implementation of the class rather than the interface. The Extension method is in my DAO class library, so that would change when my IDB implmentation changed, but I still dont like it.
Is there a better way to do this? Am I looking at DI?
The big drivers for me are:
Access to the database must be via an interface only, as we may be replacing the db soon.
The data access methods must be hidden from the service. I should only be able to access data via the methods provided by the interface/extension methods etc.
The workaround is moving your GetAccount to IDB instead of using extension methods:
public interface IDB : IDisposable
{
ObjectContext UnderlyingContext { get; }
List<string> GetAccount();
int SaveChanges();
}
It solves your issue because MyDB will implement the method and all derived classes will use implementation as well. If they provide other implementation they will simply override it.
The data access methods must be hidden from the service. I should only
be able to access data via the methods provided by the
interface/extension methods etc.
But they are not. The method / property is hidden if it is not public but currently any your service can convert IDB to MyDB and access DbSet directly.

oData WCF service - hide an element

I'm new to WCF. My web project has an ADO.NET Entity Data Model (aka EF edmx), which has the Entity Container Name JobSystemEntities.
I've created a simple oData WCF data service which uses JobSystemEntities, and it works great:
public class JobService : DataService<JobSystemEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Jobs", EntitySetRights.ReadSingle);
}
However, this exposes all of the properties on the Job. I would like to hide sensitive data, i.e. the Cost field/property/column of the Job table.
I am posting this a but late, but it might help others.
You can use the IgnoreProperties attribute http://msdn.microsoft.com/en-us/library/system.data.services.ignorepropertiesattribute.aspx on your class.
You will have to define a partial Job class in order to do this. Something in the lines of:
namespace DAL.Entities
{
[IgnoreProperties("Cost")]
public partial class Job
{
}
}
I've done something similar to this. A good starting point is found here:
http://weblogs.asp.net/rajbk/archive/2010/05/15/pre-filtering-and-shaping-odata-feeds-using-wcf-data-services-and-the-entity-framework-part-1.aspx
Basically you will need to separate the protected properties of an entity into a separate entity that is linked as a property of the other. Once that is done user a Query Interceptor to restrict when that protected entity can be viewed.
[QueryInterceptor("YourObjectsProtectedProperties")]
public Expression<Func<YourObjectsProtectedProperties, bool>> OnReadYourObjectsProtectedProperties()
{
if (ShowEntityToUser())
return o => true == true;
return o => true == false;
}

Object hierarchy returned by WCF Service is different than expected

My understanding may be wrong, but I thought once you applied the correct attributes the DataContractSerializer would render fully-qualified instances back to the caller.
The code runs and the objects return. But oddly enough, once I look at the returned objects I noticed the namespacing disappeared and the object-hierarchy being exposed through the (web applications) service reference seems to become "flat" (somehow). Now, I expect this from a web-service…but not through WCF. Of course, my understanding of what WCF can do may be wrong.
...please keep in mind I'm still experimenting with all this.
So my questions are…
Q: Can I do something within the WCF Service to force the namespacing to render through the (service reference) data client proxy?
Q: Or perhaps, am I (merely) consuming the service incorrectly?
Q: Is this even possible?
The service code looks like…
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class DataService : IFishData
{
public C1FE GetC1FE(Int32 key)
{
//… more stuff here …
}
public Project GetProject(Int32 key)
{
//… more stuff here …
}
}
[ServiceContract]
[ServiceKnownType(typeof(wcfFISH.StateManagement.C1FE.New))]
[ServiceKnownType(typeof(wcfFISH.StateManagement.Project.New))]
public interface IFishData
{
[OperationContract]
C1FE GetC1FE(Int32 key);
[OperationContract]
Project GetProject(Int32 key);
}
[DataContract]
[KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class Project
{
[DataMember]
public wcfFISH.StateManagement.ObjectState ObjectState { get; set; }
//… more stuff here …
}
[DataContract]
KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class C1FE
{
[DataMember]
public wcfFISH.StateManagement.ObjectState ObjectState { get; set; }
//… more stuff here …
}
[DataContract(Namespace = "wcfFISH.StateManagement")]
[KnownType(typeof(wcfFISH.StateManagement.C1FE.New))]
[KnownType(typeof(wcfFISH.StateManagement.Project.New))]
public abstract class ObjectState
{
//… more stuff here …
}
[DataContract(Namespace = "wcfFISH.StateManagement.C1FE", Name="New")]
[KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class New : ObjectState
{
//… more stuff here …
}
[DataContract(Namespace = "wcfFISH.StateManagement.Project", Name = "New")]
[KnownType(typeof(wcfFISH.StateManagement.ObjectState))]
public class New : ObjectState
{
//… more stuff here …
}
The web application code looks like…
public partial class Fish_Invite : BaseForm
{
protected void btnTest_Click(object sender, EventArgs e)
{
Project project = new Project();
project.Get(base.ProjectKey, base.AsOf);
mappers.Project mapProject = new mappers.Project();
srFish.Project fishProject = new srFish.Project();
srFish.FishDataClient fishService = new srFish.FishDataClient();
mapProject.MapTo(project, fishProject);
fishProject = fishService.AddProject(fishProject, IUser.UserName);
project = null;
}
}
In case I’m not being clear…
The issue arises in that the namespacing I expect to see (returned) is different from what is actually returned.
fishProject.ObjectState SHOULD look like...
srFish.StateManagement.Project.New
fishC1FE.ObjectState SHOULD look like...
srFish.StateManagement.C1FE.New
fishProject.ObjectState ACTUALLY looks like...
srFish.New1
fishC1FE.ObjectState ACTUALLY looks like...
srFish.New
OK - default behavior for a WCF Service is this:
you define your service contracts, operations, and data contract on the server (e.g. in namespace "Server.MyService")
once the service is up and running, on your client, you create a service reference
when doing so, what Visual Studio or svcutil.exe do, is interrogate that service for its metadata (description of service methods and data)
based on that metadata, the client side proxy is generated (namespace "Client.MyService") and it contains replicas of the service contract (the methods) and the data contract
Important: it contains replicas of those things! They look the same, and they serialize into the same XML format on the wire - but they are different - in different namespaces, most notably.
This is the very nature of WCF - all you do is exchange serialized messages between client and server - all that goes back and forth are textual messages. Nothing more - no object references, no remote object - nothing like that. Toss that out of your mind! :-)
If you control both ends of the wire, this can be a pain - if you need to change anything, you have to change it on the server side, update the client references and so forth.
So if you control both ends of the wire - both the server and the client - and they're both .NET based, you can do the following:
put your service contracts and your data contracts (only the contracts - no implementations!) into a separate assembly
from your service implementation, reference that contracts assembly
copy the contracts assembly to your client, and also reference it in your client project
Now, if you add the service reference, by default, the Add Service Reference function in Visual Studio will reuse existing types in referenced assemblies - so if you have referenced your common "Contracts" assembly, those types (in their full glory, including their namespace) will be reused - no additional copies will be created.
That way, you can create a single, shared contracts assembly used by both the server side code, as well as your client, and you don't have to mess with any duplication of data structures. But again: that only works if you are in control of both ends of the wire, and both are .NET

Accessing more than one data provider in a data layer

I'm working on a business application which is being developed using DDD philosophy. Database is accessed through NHibernate and data layer is implemented using DAO pattern.
The UML class diagram is shown below.
UML Class Diagram http://img266.imageshack.us/my.php?image=classdiagramhk0.png
http://img266.imageshack.us/my.php?image=classdiagramhk0.png
I don't know the design is good or not. What do you think?
But the problem is not the design is good or not. The problem is after starting up the application an IDaoFactory is instantiated in presentation layer and send as parameter to presenter classes(which is designed using MVC pattern) as below
...
IDaoFactory daoFactory = new NHibernateDaoFactory(); //instantiation in main class
...
SamplePresenterClass s = new SamplePresenterClass(daoFactory);
...
Using just one data provider (which was just one database) was simple. But now we should get data from XML too. And next phases of the development we should connect to different web services and manipulate incoming and outgoing data.
The data from XML is going to be got using a key which is an enum. We add a class named XMLLoader to the data layer and add an interface ILoader to the domain. XMLLoader has a method whose signature is
List<string> LoadData(LoaderEnum key)
If we instantiate ILoader with XMLLoader in presentation layer as below we have to send it to objects which is going to get some XML data from data layer.
ILoader loader = new XMLLoader();
SamplePresenterClass s = new SamplePresenterClass(daoFactory, xmlLoader);
After implementing web service access classes
SamplePresenterClass s = new SamplePresenterClass(daoFactory, xmlLoader, sampleWebServiceConnector1, sampleWebServiceConnector2, ...);
The parameters is going to be grown in time. I think i can hold all instances of data access objects in a class and pass it to required presenters (maybe singleton pattern can helps too). In domain layer there must be a class like this,
public class DataAccessHolder
{
private IDaoFactory daoFactory;
private ILoader loader;
...
public IDaoFactory DaoFactory
{
get { return daoFactory; }
set { daoFactory = value; }
}
...
}
In main class the instantiation can be made with this design as follows
DataAccessHolder dataAccessHolder = new DataAccessHolder();
dataAccessHolder.DaoFactory = new NHibernateDaoFactory();
dataAccessHolder.Loader = new XMLLoader();
...
SamplePresenterClass s = new SamplePresenterClass(dataAccessHolder);
What do you think about this design or can you suggest me a different one?
Thanks for all repliers...
IMO, it would be cleaner to use a "global" or static daoFactory and make it generic.
DaoFactory<SamplePresenterClass>.Create(); // or
DaoFactory<SamplePresenterClass>.Create(id); // etc
Then, you can define DaoFactory<T> to take only, say, IDao's
interface IDao
{
IDaoProvider GetProvider();
}
interface IDaoProvider
{
IDao Create(IDao instance);
void Update(IDao instance);
void Delete(IDao instance);
}
Basically instead of passing every constructor your DaoFactory, you use a static generic DaoFactory. Its T must inherit from IDao. Then the DaoFactory class can look at the T provider at runtime:
static class DaoFactory<T> where T : IDao, new()
{
static T Create()
{
T instance = new T();
IDaoProvider provider = instance.GetProvider();
return (T)provider.Create(instance);
}
}
Where IDaoProvier is a common interface that you would implement to load things using XML, NHibernate, Web Services, etc. depending on the class. (Each IDao object would know how to connect to its data provider).
Overall, not a bad design though. Add a bit more OO and you will have a pretty slick design. For instance, each file for the XmlEnums could be implemented as IDao's
class Cat : IDao
{
IDaoProvider GetProvider()
{
return new XmlLoader(YourEnum.Cat);
}
// ...
}