DataContract in a project other than WCF - c#

I have been developing a WCF service for my project. I have multiple projects in my solution, explained below:
WCF Service - WCF Service Project
Business Logic - project contains domain logic
Data Access Layer - for accessing data
Core - project contains the business objects only (Many of them are sent as a response of service call - This contains the classes which are to be shared with client)
Log - project to log errors and activities
Service project puts call to Business project for the respective operation and the Business Logic project intializes the objects of the classes defined in Core object. And these objects are sent as the response of service call.
This is done successfully, i am able to share all public properties of the class defined in Core project. But i am unable to use DataContract/DataMember attributes in the core project as this is a non-WCF project. I need to achieve few tasks for which i have to use DataMember attributes like i dont want to share a property in case of null value, i don't want to share few properties of some objects with the client.
Please tell me if i am mistaken with the approach. And please help me achieving the above, i couldn't find any similar question on the forum.
Edit: (Let me try explaining it better)
All the projects are referenced in the WCF Service Project which consumes those project. This was to keep logical separation.
For Example, The Core project contains a class named User and this class is the return type of a service api. When this API is called, the logic initializes an object of User. And the object is returned as a result to that call.
In this case, i haven't used any [DataContract] attribute for the User class. And it works fine. Now i want to stop sharing few properties of this class, for this i needed to use [DataContract]/[DataMember] attributes, which are not being resolved in the Core project.

Ok, let me start by pointing out that data contracts and data members are not directly related to WCF. Actually, these attributes reside in a namespace that has nothing to do with services directly...theyre rather related to serialization and it's just a matter of adding a reference to the required assembly...i think it's System.Runtime.Serialization. I don't see why you can't add a reference to this assembly in your project.
The second question related to "hiding" members...i dont think you have to many options here. If you decorate a property with the DataMember attribute it will be serialized with the data contract, so there's no way you can't "hide" it. At best, what you can do is not to decorate a property with the DataMember attribute, but in this case the property will not be serialized, in other words, it will be ignored during the serialization process.

Related

How to create a WCF Data Services OData with with the Reflection Provider using model classes from different project?

Following the instructions to use the Reflection Provider (http://msdn.microsoft.com/en-us/library/dd728281.aspx) everything works well, until I move the classes Order and Item to a Class Library and reference the class library from the web project with the SVC file.
Move the POCO classes into the WCF project all goes well.
Move the POCO classes out of the WCF project into separate assembly, I get a 500 with no explanation.
I want to be able to keep my poco classes in a separate project and expose them with an OData endpoint. What am I doing wrong?
--UPDATE--
The scenario described above is meant to illustrate a problem I have found using the WCF OData Reflection Provider. It is not my real problem, but is easier to explain for illustrative purposes.
Try upgrading to the latest version of WCF Data Services (currently 5.3), if you aren't already on it. I reproduced your issue using the version of WCF Data Services that ships with .Net 4.5, but once I upgraded the references in both assemblies to the latest release of Microsoft.Data.Services using NuGet, the problem went away.
If you're already using the most up-to-date version of WCF Data Services, make sure that both assemblies are referencing the exact same version of WCF Data Services.
If neither of these fix your problem, add the following attribute to your DataService class to get a more detailed error message and stack trace:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class YourService : DataService<...>
And then please update your question with the results of that (if the solution doesn't immediately jump out from the stack trace).
(disclaimer: I usually don't like answers of the kind that don't help you with your problem but rather explain why your problem isn't the correct problem, but I think it's justified in this case :))
If you think about it, you don't really want to do that:
The Order and Item classes aren't really POCOs at all; they're not 'plain' C# objects; they have data attributes on them, which make them data transfer objects (DTOs).
They belong to the interface between your service and its clients;
The domain entities (or POCOs) Item and Order will, most likely, be a bit more complex, and contain other things besides data, such as operations and business logic.
I believe the correct way to go is to have a rich domain model, in which Order and Item contain a full set of attributes and operations, and on top of that, a DTO layer, which contains only those attributes that your service client needs.
Sending your POCOs over the wire was termed 'the stripper pattern', and I believe it's best avoided.

WCF ServiceKnownType design issue

I'm designing a new solution that will consist of three projects:
"Server" - a WCF service
"Client" - a winforms app that will call the WCF service
"ServiceContract" - a class lib containing some base classes plus the WCF service contract (interface). This will obviously be referenced by the Server, and also by the Client (I'm using a ChannelFactory rather than have VS generate a service reference). The service contract looks something like this:-
[ServiceContract]
[ServiceKnownType("GetCommandTypes", typeof(CommandTypesProvider))]
public interface INuService
{
[OperationContract]
bool ExecuteCommand(CommandBase command);
}
It's a very basic operation - the client creates a "command" object and sends it to the server to be executed. There will be many different commands, all inheriting from CommandBase (this base class resides in the "ServiceContract" project). As I'm using the base class in the WCF operation signature, I have to specify the known types which I'm doing dynamically using the ServiceKnownType attribute. This references a helper class (CommandTypesProvider) that returns all types deriving from CommandBase.
I've created a simple proof of concept with a couple of derived command classes that reside in the "ServiceContract" project. The helper class therefore only has to reflect types in the executing assembly. This all works fine.
Now in my "real" solution these command classes will be in different projects. These projects will reference the ServiceContract project, rather than vice-versa, which makes it difficult (or impossible?) for the helper to reflect the "command" assemblies. So my question is, how can I provide the known types?
Options I've thought about:-
The "Server" and "Client" projects will reference both the "ServiceContract" project and the various "command" projects. My helper could reflect through AppDomain.CurrentDomain.GetAssemblies(), but this fails because the "command" assemblies are not all loaded (I could force this by referencing a type in each, but that doesn't feel right - I want it to be a dynamic, pluggable architecture, and not have to modify code whenever I add a new command project).
Specify the known types in config. Again it would be nice if the app was dynamic, rather than have to update the config each time I add a command class.
Is there any way to access the underlying DataContractSerializer on both the client and server, and pass it the known types? I guess I'll still have the same issue of not being able to reflect the assemblies unless they've been loaded.
Refactor things to enable the ServiceContract project to reference the various command projects. I can then reflect them using 'Assembly.GetReferencedAssemblies()'. I guess the various command classes are part of the service contract, so perhaps this is the way to go? Edit: looks like this has the same problem of only finding loaded assemblies.
Any ideas greatly appreciated! Is it something that can be achieved or do I need to rethink my architecture?!
Thanks in advance.
One thing to consider is using the DataContractResolver.
Few resources:
WCF Extensibility – Data Contract Resolver by Carlos
Building Extensible WCF Service Interfaces With DataContractResolver by Kelly
Configuring Known Types Dynamically - Introducing the DataContractResolver by Youssef
Thanks for the replies regarding the Data Contract Resolver guys. I probably would have gone down this route normally but as I was using Windsor I was able to come up with a solution using this instead.
For anyone interested, I added a Windsor installer (IWindsorInstaller) to each of my "command" projects, which are run using Windsor's container.Install(FromAssembly.InDirectory.... These installs are responsible for registering any dependencies needed within that project, plus they also register all the command classes which my known types helper can resolve from the container.

Portable class library for shared [DataContract] class

This is probably a real simple one. I wished to create some code inside a [DataContract] class which is used to communicate information between a WCF service and consuming application.
I created a new Portable Class Library project and created inside it my [DataContract] class. It's really simple - it has a few easy attributes (strings mostly). I added a reference to the DLL in my WCF service and republished it. I then deleted the service reference from my consumer project and re-added it. It adds fine, no problems there.
The problem comes when I want to actually use it. See, the type is called 'Eval'. Some of the WCF methods return this 'Eval' type. So I have this serialized version of 'Eval' in the Reference.cs file within my service reference. Obviously this doesn't contain the method I'm looking for since it's just the serialized version. I can add the dll to the client project as well, but then I have two different Eval objects in two namespaces, and only the one from reference.cs is valid to be returned from the service calls.
So how do I ... erm... merge the two? So as the Eval objects that come back from the WCF service calls also have access to the method in question?
Thanks for reading, and stay safe on those roads.
When generating service reference you can specify what classes should be reused and what classes should be generated from service

Adding WCF Service Reference doesn't generate code

Scenario:
Web Site project under .NET 3.5
Visual Studio 2010
WCF Service reference
Problem:
I'm trying to extend a class marked with the DataContract attribute. I though the generated class was declared partial, so that i could easily extend it. I tried declaring a partial class within the same namespace with the same name, but it doesn't seem to recognize what class it's extending. I tried locating the generated code file (Reference.cs) which i thought existed after reading this article inside the reference folder, but it wasn't there. When trying to navigate to the class's definition, i found out it was in a compiled library, and the biggest problem is that it wasn't declared as partial.
Question:
Is this difference related to the fact that i'm using a Web Site and not a Web Project?
If so, is there a way that i could make the code generator (which also seems to compile the generated code) to declare class as partial?
Yes there is a way you can declare your DataContract classes as Partial.
For this you'd want to use the DTO pattern. Basically this means defining "shared" Classes in a different assembly, and having both the Service, and the App which consumes the Service, both reference the assembly with your common classes.
So for example your "DTOs" assembly might contain a DTO called "Product". Ok, so you make them Partial, and next you decorate Product, and which ever other Class with the WCF attributes, like DataContract, and DataMember etc.
Now, you reference you DTO assembly with you Service project, and your Web Project.
Now, when you go to your web project and click on "Add Service Reference", click on the "Advanced", and you'll notice you can enable an option to "resuse referenced assemblies". do that and you'll have full control over you DataContracts.
Empty client reference proxy classes can indeed be a most frustrating problem to solve.
I would recommend that you use the WCF Test Client or command line svcutil.exe. against the service - you can often get a much more detailed error description with these tools than with Visual Studio service reference wizard.
In my case the issues are invariably related to serialization or namespacing issues of the entity / graph - typically mismatched get and set on DataMember properties, missing KnownType on polymorphic entities, or circular references in the graph.
Partial shouldn't be a problem. Just make sure that any additional properties that you want serialized are marked as DataMember.
If all else fails, would recommend that you run a serialization / deserialization unit test against your entity / entity graph.

Is it possible to create read only elements in SOAP web services?

I have a class with a read-only property defined. In my code I define this as a property with a getter only.
I want to be able to send this object back and forth across a web service. When I call a "Get" method in the service, it would be populated with a value on the service side. Once I define this property, I don't want the consumer of the web service to be able to set/change this property.
When I add a reference to this web service to a project, the object has the property serialized a few different ways depending on how I try to define the object on the service side:
internal setter: Creates the property in the WSDL. Visual Studio generates a class with both a getter & a setter for this property.
no setter: Does not create the property in the WSDL. Visual Studio then obviously does not define this property at all.
Read-only public member variable - Does not create the property in the WSDL. Again, Visual Studio will not do anything with this property since it doesn't know about it.
Allowing the consumer of the web service to set a value for this property will not cause any harm. If the value is set, it is ignored on the web service side. I'd just prefer if the consumer can't change/set the property to begin.
Is there any way to define a property as read-only? Right now we're using C#/.NET 2.0 for the web service, and (for now at least) we have control over all of the consumers of this service, so I can try changing configurations if needed, but I prefer to only change things on the web service and not the consumers.
I can be wrong, but I think the problem here is how serialization works - in order to deserialize an object the serializer creates an empty object and then sets all the properties on this object - thats why you need a setter for the properties to be included in serialization. The client code has the same "interface" to the object as the deserializer.
Caveat, I am a Java guy so the first part of my answer focuses on what may be possible in C#.
Firstly, with a custom serializer in Java, you can do almost anything you want, including directly setting values of a protected or private field using reflection so long as the security manager doesn't prevent this activity. I don't know if there are analogous components in C# for the security manager, field access, and custom serializers, but I would suspect that there are.
Secondly, I think there is a fundamental difference in how you are viewing Web services and the Web service interface as part of your application. You are right-click generating the Web service interface from existing code - known as "code first". There are many articles out there about why WSDL first is the preferred approach. This one summarizes things fairly well, but I would recommend reading others as well. While you are thinking in terms of a shared code library between the client side and server side of your Web service and maintaining object structure and accessibility, there is no such guarantee once you publish an API as a Web service and don't have control over all of the consumers. The WSDL and XSD serve as a generic description of your Web service API and your server and client can be implemented using different data binding configurations, object classes, or languages. You should think of your Web service interface and the XML that you pass in and out of it as describing the semantics of the exchange, but not necessarily the syntax of the data (your class structure) once it is internalized (deserialized) in your client or server.
Furthermore, it is advisable to decouple your transport related structures from your internal business logic structures lest you find yourself having to refactor both your server implementation, your Web service API, and your (and other's) client implementations all at the same time.
There's no built-in way to do this in .NET 2.0 as far as I know. In cases where I wanted to serialize a read-only property, I've implemented the IXmlSerializable interface so that I could control the ReadXml() and WriteXml() methods.
In later versions of the .NET framework, you can serialize read-only properties by setting an attribute on the backing field.

Categories

Resources