I have a Composite type DataContact and one of the DataMember is a decimal? return type
[DataMember]
public decimal? ExchangeRate { get; set; }
When a value is assigned to the ExchangeRate property from the client, the serialized value across the wire at the service end is null. Why is this happening as WCF 4.5 fully supports Nullable types according to MSDN. Any pointers would be greatly appreciated.
If you have not already, I suggest you enable WCF tracing on the client and service, so you have a better understanding of the serialized values. At least you could confirm the client parameter values and serialization and then compare to the result received by the WCF Service.
For reference: WCF tracing provides diagnostic data for fault monitoring and analysis. You can use tracing instead of a debugger to understand how an application is behaving, or why it faults.http://msdn.microsoft.com/en-us/library/ms733025(v=vs.110).aspx
Related
I have a WCF service that has an operation that takes any .net serializable client data.
[OperationContract]
void SaveMyData(long id, string name, object serializableData);
[OperationContract]
object LoadMyData(long id, string name);
The server doesn't need to know what the data is, it just stores it or returns what is stored. And the server doesn't even know the types being serialized so of course this contract would result in deserialization exceptions.
I know that I could serialize/deserialize this independently of the WCF contract, for example:
[OperationContract]
void SaveMyData(long id, string name, byte[] serializedData);
[OperationContract]
byte[] LoadMyData(long id, string name);
But this requires additional code on the client to serialize and deserialize. I'd like to avoid that and have the client code as simple as possible.
I know that I could create a pre-build proxy in a client dll that would wrap the WCF calls and perform the additional serialization/deserialization. But I'd rather be able to rely on the clients generated from the WSDL.
Ideally, a RawAttribute could be placed on the parameters or return value which would suppress serialization/deserialization (of the universal root object type) and instead supply or expect an (object)byte[] (or (object)Stream?) from the operation.
[OperationBehavior]
public void SaveMyData(long id, string name, [Raw] object serializableData){ ... }
[OperationContract, Raw]
object LoadMyData(long id, string name);
I've looked at DataContractSurrogate and DataContractResolver but I'm not seeing how to achieve this. DataContractSurrogate seems too late in the deserialization pipeline as the type and deserialized object are already supplied. The resolver doesn't give the data, just the type info. Neither gives information about the parameter being deserialized for which to find the RawAttribute.
Does WCF offer an appropriate extensibility point for this? Or a built-in way?
I would also like to know what the declared type is, as extracted from the serialized data, but that isn't necessary.
Thanks!
Instead to fighting WCF's serialization mechanism, you should drop one level of abstraction and work at the message level of WCF. What you're looking for is a kind of "universal" service that can accept messages from any client. Read through this old but still applicable MSDN article on WCF Messaging. Toward the bottom of the article (figure 8) is sample code for a generic WCF service. That should at least give you a start in creating a service that bypasses serialization.
WCF Newbie alert. I'm reading "Learning WCF" and "Programming WCF Services" where both books recommend throwing FaultException<T>. If T is .NET type "DivideByZeroException" and assuming a FaultContract exists with
[FaultContract(typeof(DivideByZeroException))]
on method "Divide", will a non-.NET client consuming that WCF service and method be able to understand and process that .NET exception? If yes, is it because the type info (DivideByZeroException) is part of the metadata (because of the FaultContract) that the client has access to and uses?
Thanks for any help.
You can throw a FaultContract<DivideByZeroException>, but in general you shouldn't do that, exactly for the reason you mentioned (*). What is usually recommended is to have a data contract with the information from the exception, such as the exception message, and then have a FaultContract of that type.
[DataContract]
public class MyErrorDetails
{
[DataMember]
public string ErrorCode { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
}
And then use
[FaultContract(typeof(MyErrorDetails))]
(*) Another reason to avoid returning exceptions as faults is that they disclose more information to the client than the client needs; things such as the stack trace are serialized by the exception, but that's some information internal to the service and shouldn't be sent to clients.
I am very confused about the DataContract attribute in WCF. As per my knowledge it is used for serializating user defined type like classes. I wrote one class which is exposed at client side like this.
[DataContract]
public class Contact
{
[DataMember]
public int Roll { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Address { get; set; }
[DataMember]
public int Age { get; set; }
}
It is working properly but when I remove DataContract and DataMember it also works properly. I can't understand why it is working properly. Can any one tell me what is the actual use of DataContract?
My service contract looks like this
[ServiceContract]
public interface IRestServiceImpl
{
[OperationContract]
Contact XmlData(string id);
}
Since a lot of programmers were overwhelmed with the [DataContract] and [DataMember] attributes, with .NET 3.5 SP1, Microsoft made the data contract serializer handle all classes - even without any of those attributes - much like the old XML serializer.
So as of .NET 3.5 SP1, you don't have to add data contract or data member attributes anymore - if you don't then the data contract serializer will serialize all public properties on your class, just like the XML serializer would.
HOWEVER: by not adding those attributes, you lose a lot of useful capabilities:
without [DataContract], you cannot define an XML namespace for your data to live in
without [DataMember], you cannot serialize non-public properties or fields
without [DataMember], you cannot define an order of serialization (Order=) and the DCS will serialize all properties alphabetically
without [DataMember], you cannot define a different name for your property (Name=)
without [DataMember], you cannot define things like IsRequired= or other useful attributes
without [DataMember], you cannot leave out certain public properties - all public properties will be serialized by the DCS
So for a "quick'n'dirty" solution, leaving away the [DataContract] and [DataMember] attributes will work - but it's still a good idea to have them on your data classes - just to be more explicit about what you're doing, and to give yourself access to all those additional features that you don't get without them...
In terms of WCF, we can communicate with the server and client through messages. For transferring messages, and from a security prospective, we need to make a data/message in a serialized format.
For serializing data we use [datacontract] and [datamember] attributes.
In your case if you are using datacontract WCF uses DataContractSerializer else WCF uses XmlSerializer which is the default serialization technique.
Let me explain in detail:
basically WCF supports 3 types of serialization:
XmlSerializer
DataContractSerializer
NetDataContractSerializer
XmlSerializer :- Default order is Same as class
DataContractSerializer/NetDataContractSerializer :- Default order is Alphabetical
XmlSerializer :- XML Schema is Extensive
DataContractSerializer/NetDataContractSerializer :- XML Schema is Constrained
XmlSerializer :- Versioning support not possible
DataContractSerializer/NetDataContractSerializer :- Versioning support is possible
XmlSerializer :- Compatibility with ASMX
DataContractSerializer/NetDataContractSerializer :- Compatibility with .NET Remoting
XmlSerializer :- Attribute not required in XmlSerializer
DataContractSerializer/NetDataContractSerializer :- Attribute required in this serializing
so what you use depends on your requirements...
A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged. That is, to communicate, the client and the service do not have to share the same types, only the same data contracts. A data contract precisely defines, for each parameter or return type, what data is serialized (turned into XML) to be exchanged.
Windows Communication Foundation (WCF) uses a serialization engine called the Data Contract Serializer by default to serialize and deserialize data (convert it to and from XML). All .NET Framework primitive types, such as integers and strings, as well as certain types treated as primitives, such as DateTime and XmlElement, can be serialized with no other preparation and are considered as having default data contracts. Many .NET Framework types also have existing data contracts.
You can find the full article here.
A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged.
Data contract can be explicit or implicit. Simple type such as int, string etc has an implicit data contract. User defined object are explicit or Complex type, for which you have to define a Data contract using [DataContract] and [DataMember] attribute.
A data contract can be defined as follows:
It describes the external format of data passed to and from service operations
It defines the structure and types of data exchanged in service messages
It maps a CLR type to an XML Schema
It defines how data types are serialized and deserialized. Through serialization, you convert an object into a sequence of bytes that can be transmitted over a network. Through deserialization, you reassemble an object from a sequence of bytes that you receive from a calling application.
It is a versioning system that allows you to manage changes to structured data
We need to include System.Runtime.Serialization reference to the project. This assembly holds the DataContract and DataMember attribute.
Data contract: It specifies that your entity class is ready for Serialization process.
Data members: It specifies that the particular field is part of the data contract and it can be serialized.
Also when you call from http request it will work properly but when your try to call from net.tcp that time you get all this kind stuff
DataMember attribute is not mandatory to add to serialize data. When DataMember attribute is not added, old XMLSerializer serializes the data. Adding a DataMember provides useful properties like order, name, isrequired which cannot be used otherwise.
The data is to be transferred and processed within service and they store the values, so in the WCF terminology they are called “Data Contract”.
Where each member of the Class; i.e., The data contract is called “Data Member” and they are also to be decorated with the Attributes.
Source
We are trying to figure out a way to modify WCF service behavior to catch all exceptions and instead of returning faults to the client, it will populate a custom return object with exception data and return that. So far, we haven't had much luck. I found this example: Catching custom faults
However, it doesn't return custom types as we would like it to. What other options are there?
Thanks!
If you want to have an interoperable and "by-the-standard" service, you should always return FaultException<T> SOAP faults from your service to the client.
Since that type takes a generic <T>, you can basically put anything into that type there to report back your errors. That type needs to be decorated with a [DataContract], and its members that need to be passed back with [DataMember] attributes.
[DataContract]
public class MyErrorInfo
{
[DataMember]
public int ErrorCode { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
}
When you catch those execptions on the service side and return a FaultException<MyErrorInfo> (or whatever you'll end up calling your error class), you also need to decorate your operations with a
[FaultContract(typeof(MyErrorInfo))]
[OperationContract]
public SomeType SomeMethodCall(SomeType parameter);
so that your clients will be able to catch the FaultException<MyErrorInfo> and handle it.
I referred to this article in another answer, but it may help you as well..
WCF Exception Handling
the article is Simplifying WCF: Using Exceptions as Faults
I wrote a blog post on this exact topic after we encountered this in our own project. Basically, we chose to return the same object type so we can attach a single listener delegate to all events to globally handle certain errors (like a user losing the permissions to an org.)
I hadn't thought of using FaultException but I will examine how we might do that. This design was WCF Service (.NET 3.5) running inside SharePoint 2007 and consumed by Silverlight 4.
I have a Silverlight application with a Silverlight-enabled WCF service. The service passes along a small POCO class with a few string properties, and a List<> of an enum defined in the class. Everything works fine when running using the ASP.NET development server, but when I move the service over to an IIS server (Windows 2003) I get the following error when I try to browse the .svc file:
Type 'MyProject.Web.MyClass' cannot be
serialized. Consider marking it with
the DataContractAttribute attribute,
and marking all of its members you
want serialized with the
DataMemberAttribute attribute.
Even though it's working development side, I've tried adding the decorations... but so far without effect.
Any ideas as to what might be causing this difference of outcomes between development workstation and server?
Make sure that (1) the .NET Framework 3.5 SP1 is installed on the server and (2) that the website is running in ASP.Net 2.0 mode and not 1.1 mode.
The Web Platform Installer is an easy way to install the updated framework if it isn't already installed.
Your data elements (POCO classes) ought to be marked as DataContracts for WCF, so that WCF knows explicitly what it'll need to serialize to send across the wire.
Contrary to the Xml Serializer, the DataContractSerializer in WCF uses an "opt-in" model - only things that you explicitly mark as [DataContract] and [DataMember] will be serialized - anything else will be ignored.
[DataContract]
class YourPocoClass
{
[DataMember]
private int _ID;
[DataMember]
string CustomerName { get; set; }
public decimal CustomerOrderAmount { get; set; }
}
In this example, from YourPocoClass, you'll have both the _ID field and the CustomerName property be serialized into the WCF message - but the CustomerOrderAmount will not be serialized - public or not.
So, best practice is: explicitly mark all your complex types that you need to send around in WCF with [DataContract] (for the class) and [DataMember] (for each member to be sent across inside that class).
Marc