WCF - Complex Objects - KnownTypes - c#

Ok, not really sure how to word, but will try my best.
I have a number of WCF services that are setup and run awaiting an object to come in for processing.
WCFServiceA
WCFServiceB
WCFServiceC
Service A will run some processing and decide to send the object onto Service B or C.
So my object has [DataContract] attribute on all classes in it and [DataMember] on all properties.
So so far so good.
But now I well lose all the functionality from my object, as this is now basically a serialised version of the object.
So is it best practice if I want to use a full complex object to include the same assembly in all 3 services as a reference and send things across as "KnownTypes"?? Providing the basic DataContract and DataMember for anything using the services that does not know these types so they can still create these object for the services to run with?
Hope I have worded this correctly and you understand my question here.
:EDIT:
To try and clarify.
The object I am sending can have a "Policy" attached to it, this policy object is a class and can be one of several types, vehicle, house, life, pet policy etc.
But the actual type will not be known by the receiving service. Hence the need for KnownTypes.
I think I just answered my own question!! :)

That was a good explanation of the problem. The draw back I see in this approach is if you are going to update the object , say adding new properties or removing some , all the 3 service needs to be updated with the new assembly.
Using of the known types can sometimes lead to backward compatibility issues when you want to upgrade the objects in live depending on the setup.
Or create a DTO (Data transfer object) with just the properties and pass it across the services as a data contract and strip the complex logic in to a helper class which can be referenced by the services.

Related

Pattern Help: Passing Object from DAL to Contract. Two Classes, One Interface

I have many projects in my solution representing the different layers of the application. The Data Access Layer (DAL) has a model of the database in it and more importantly --for my issue-- a Plain Old Class Object (POCO). I want to send an instance of this POCO to an external requester via a WCF contract. As you know, I must define the Operations Contract and Data Contract at the contract layer. It is here were my problem lies, how do I declare the data contract and its data members when the POCO is situated in another layer?
I have tried defining an interface and have both classes implement it, but I come up against a problem when I am getting the objects from the database and then passing them through the contract, the contract does not know the object being passed to it - even though it shares an interface.
Anyway, hope that is clear (as mud!), and if anyone can advise me on a suitable solution I would be much obliged.
P.S. Using C# in VS2015
Looks to me like what you need is another class specifically built for the WCF layer that contains all the properties and attributes you need to use and then use something like AutoMapper to copy to contents across to your WCF object.
Making use of the Factory Design Pattern could also be of helper here.

Prevent WCF exposing my whole class?

I've just begun learning WCF, and I'm coming from a total non-web background.
I have built a 3-tier desktop application, which compiles into one exe, which runs locally.
Now I want to move the whole business logics layer to a centric server, and make the GUI a client application.
As far as I understand, WCF should be my solution, as indeed, it helped me achieved what I wanted.
I mange to run remote functions, which is the basic of what I need.
My problem now, is that I don't quite understand the architecture.
For example, one of my services, returns a data type (class), from my Business Logics layer.
This class automatically becomes available to the client through the WCF mechanism.
But the problem is, this class contains some methods, which i definitely do not want to expose to the client.
For example a Save method (saves to the db).
Further more, sometimes I don't even want to allow the client to change all the properties of the class, since this class might be sent to one of my services.
I do not want to re-validate the class instance in the service.
What should I do? Should I build another layer, restricted version of the Business Logics, which I expose to the client? Or is there any way expose only part of my class to the client, without restricting the server it self?
I know this is a basic question, but honestly i've searched a lot before asking here. My problem is I don't quite know what to search.
My second question is then, do you have any recommendation for any resource that can explain me this architecture...?
Typically, if you want to encapsulate your business layer, you would not want to expose the business objects directly. This is because you now have a de-coupled client and you don't necessarily want to have to update the client every time the business logic/properties change.
This is where Data Transfer Objects (DTO) come into play nicely. Usually, you want to have control over your contract (data and methods) that you expose. Therefore, you would explicitly make other objects (DTOs) that make up the transfer layer. Then, you can safely change your client and server code independently (as long as both still fulfill the contract objects).
This usually requires a little more mapping (before you send or receive on each side) but it is often worth it.
For WCF, your interfaces and classes marked with [ServiceContract] and your classes marked with [DataContract] usually make up this transfer layer.
In WCF to expose method to client you have to mark it with OperationContractAttribute. So if you don't want clients to use your Save method, just don't mark them with with this attribute.
More info here: http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.aspx
Pretty much same thing with properties, but different attribute: DataMemberAttribute. If you don't wont client to see it, just don't mark them with it (DataMember attribute)
But the problem is, this class contains some methods, which i definitely do not want to expose to the client.
Are you able to provide an example of your class and interface code? If so I'm sure you might be able to get more specific answers.
For example a Save method (saves to the db).
One possible approach would be to separate your class into 2 classes. Define the properties in the first class and then use that class as the base class of your second class. Then use the second class to define the methods. This would allow you to return only the properties while allowing you to keep your code DRY.
Further more, sometimes I don't even want to allow the client to change all the properties of the class, since this class might be sent to one of my services.
I do not want to re-validate the class instance in the service.
While you are able to define logic in the get and set methods for each property I would highly recommend revalidating any input received between services simply because any future changes or errors in one service could potentially lead to larger problems across your application. In addition this also helps to ensure your application is more secure against any potential attacks.
Should I build another layer, restricted version of the Business Logics, which I expose to the client? Or is there any way expose only part of my class to the client, without restricting the server it self?
I agree with the above answers that you should be able to limit access to the different properties and methods using the data and method attributes within your interfaces.
My second question is then, do you have any recommendation for any resource that can explain me this architecture...?
If you are looking for inexpensive but highly valuable video based training I've found the courses that Pluralsight offers to be quite good for both architecture as well as WFC services (btw, I am not associated with them, just enjoyed their training).

DataSets vs DataClasses as return type from WCF services

I need to path information from BL layer to the presentation layer via WCF services .
I thought to do it via DataSets but I saw that people tell that it's a bad practice and it's recommended to use dataclasses.
Can someone explain the difference and the advantages .
Thanks for help.
DataSet is an old-school, outdated like-an-OR/M solution which worked fine for a long time in drag&drop developments.
Once you want to expose some logic over a service using WCF or any other framework, you need to take in account that these should transport no useless data and just what client needs to consume, and a client could be an user interface or just another service or backend engine.
In services like WCF the best approach is DTO (data-transfer objects, also known as value objects), which are a light-weight versions of business objects, absolutely unlinked from any layer (it doesn't depend on business, UI, data...) which can be easly serialized into XML or JSON and deserialized in any platform, not only in strongly-typed environments, but also interpreted, dinamically-typed ones, like JavaScript, PHP, Python or Ruby (or many others).
Think about DTO as a class which has the exact number of properties that some consumer needs to work with your service layer.
Practical example: You've a Person class having a Name, SecondName and Age. In your user interface, you need to query some service for a list of Person and there you need to show SecondName only. In this case, you're going to design a class having a single property SecondName and you'll avoid giving a full Person to the user interface through your service layer, because it's cheaper and, obviously, optimal.
If this service layer returns PersonDto objects, a JSON-serialized list of 3 persons would be [{ "SecondName": "Blah" }, { "SecondName": "Bleh" }, { "SecondName": "Blih" }]. I don't think a DataSet would be that lighty serialization.
Check these articles about DTO:
http://en.wikipedia.org/wiki/Data_transfer_object
http://msdn.microsoft.com/en-us/library/ff649585.aspx
I blogged about this here
Try that - a WCF service should be platform independant, and a DataSet is not. You do not transfer defined documents with DataSets but the internal representation of a .NET specific object.
Try that - a DataSet has a lot of crappy functionality that needs representation in the XML form (change information etc.) but that is totally irrelevant in a properly designed API (which a web servie is).
Try that - no project I have known in the last 10 years from any person I do not consider a junior had a DataSet anywhere, WCF or not. Most people with knowledge went over to OR mappers many many years ago.
With untyped datasets, you can't really shape the data you are passing to clients, including your presentation layer. For internal apis this is less of an issue, but if you're planning on expanding your api usage, you should consider the benefits if using statically typed models rather that a broad data container. This counts for both inputs and outputs. With a typed model, you can better define the intended shape of your data, its behaviour and with shared contracts you can take advantage of a shared validation model.

WCF with multiple services and namespace issues

I have created a number of WCF Services, for arguments sake they are called Service1 and Service2.
Both of the services return (at some point, possibly through a relationship inside an object) a Customer object.
For testing sake, I have added a GetCustomer() method to both Service1 and Service2 and I have added a service reference to both services in a basic WinForms application.
Service1Client proxy1 = new Service1Client();
Customer customer1 = proxy1.GetCustomer(); //
^^^^^^ Ambiguous reference, requires me to name as WcfTestClient.Service1.Customer
Service2Client proxy2 = new Service2Client();
Customer customer2 = proxy2.GetCustomer();
^^^^^ Ambiguous reference, requires me to name as WcfTestClient.Service2.Customer
The problem is, the Customer object returned by Service1 and Service2 are both the same type of Customer (WcfTestService.Customer). To remedy this I need to include the full assembly name rather than just Customer.
I have read a few posts on Stack Overflow stating that it is possible to compile the Data Contracts into a separate assembly, I don’t particularly like this idea as it may still cause problems with clients using other languages, such as Java.
Another solution I have seen is the SvcUtil.exe method, but from what I have seen this solution doesn’t address my namespace issue as I need to run the Util for each service individually?
If anyone has any helpful suggestions, please get in touch!
Both of the services return (at some point, possibly through a relationship inside an object) a Customer object.
Here's where you're wrong. WCF doesn't return objects, REST doesn't return objects, SOAP doesn't return objects. They all pass messages.
Now what happens when you add a reference to a web service is Visual Studio happily creates a wrapper class for these messages, exposing their contents as properties, nothing more. Because you are adding two services these wrapper classes have no knowledge of each other and thus you end up with two namespaces and two wrapper classes.
Yes, as you say you could move the message classes to a separate assembly, link that and avoid Add Reference and that will then act as a proper object, but still behind the scenes it's messages being passed and serialized and deserialized into this shared object. Stop thinking in terms of object passing and start thinking in terms of messages and you'll realise you're either stuck with two wrapper objects, or you need to link an external assembly.

Can strong naming cause problems with object serialization in C#?

I serialize some configuration objects and store the result bytes within a database.
new BinaryFormatter().Serialize(memoryStream, instance);
Convert.ToBase64String(memoryStream.ToArray());
These objects will be deserialized later.
new BinaryFormatter().Deserialize(memoryStream);
It's possible, that the Application has some new assembly versions at the time of deserialization. In general it works well, but sometimes I get a file load exception:
"The located assembly's manifest definition does not match the assembly reference.". The assemblies work all with strong naming, can that be the problem and how could I avoid this problem?
Thanks for help
Absolutely, using BinaryFormatter with database (i.e. long-term) storage is a bad idea; BinaryFormatter has two three big faults (by default):
it includes type metadata (shucks if you move/rename your types... this can mean strong name/versioning too)
it includes field names (fields are private details!)
it is .NET specific (which is a pain if you ever want to use anything else)
My blog post here raises two specific issues with this - obfuscation and automatically implemented properties... I won't repeat the text here, but you may find it interesting.
I recommend the use of a contract based serialization. XmlSerializer or DataContractSerializer would suffice normally. If you want small efficient binary, then protobuf-net might be of interest. Unlike BinaryFormatter, the binary from this is portable between implementations, extensible (for new fields), etc. And it is quicker and smaller, too.
I think WCF might be your best bet. It can handle passing unknown fields through to it's consumer even if it doesn't know how to deserialize them.
Example:
Service A: Knows about version 2 of the Widget class which has a Description field
Service B: Knows about version 1 of the Widget class which doesn't have a Description field
Service C: Knows about version 2 of the Widget class which has a Description field
If service A calls service B passing a Widget object and then service B calls service C passing on the same Widget object then service C will get the Description field as it was passed from service A. Service B won't have any Description field but when it deserializes it and re-serializes it it will just pass the Description field through without knowing what it is.
So, you could use WCF services with in-proc communication.
See this link for more on versioning wcf contracts.

Categories