DataContract attribute -WCF - wcf

Is DataContract attribute is deprecated in ASP.NET 4.0 WCF ? I can see only DataContractFormat attribute.
I can't apply DataContractFormat attribute over struct.
example
[DataContractFormat]
public struct Contact
{
public string firstName;
public string lastName;
}
It throws an error saying that DataContractFormat artribute can only be used on class, interface and methods.

No, the .NET 4 still contains the DataContractAttribute:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute%28v=VS.100%29.aspx
and it should be able to be applied to class or struct.

You have to add a reference to the System.Runtime.Serialization assembly (right click References, add ref...)

DataContract is not deprecated - where the heck did you get that idea from?
DataCOntractFORMAT is something totally different. I suggest you please read the documentation ;) Helps a lot. Will also explain what DataContractFormat is for.
http://msdn.microsoft.com/en-us/library/system.servicemodel.datacontractformatattribute.aspx
As you can see in the example this attribute goes on the class/interface that defines the SERVICE CONTRACT. It controls how for that service data serializaton is (guess what) formatted.

Related

XML generated by WCF client is missing some elements

I am writing a WCF client to communicate with a JAX-WS web service. Basically communication with the service works. But when investigating the XML generated by the WCF client there are some elements missing. All the properties are correctly generated and I have set them in my code. I am new to WCF and web services in general so I have problems to analize what could be wrong here. What could cause the missing elements in the XML? The only thing I noticed all these missing properties have in common is that they are enumeration types. But other than that I found nothing. For example there is a enumeration for country codes. An entitity has 3 properties of that enumeration type. Only one of the 3 related elements is generated in the XML.
Thanks for your help.
As the OP discovered, when a WCF client (including proxy classes generated by the XSD.exe utility) imports an enumerator from the WSDL or XSD, the proxy also has a corresponding bool property. For an enumeration element named 'Foobar' there is also 'FoobarSpecified' which must be set to true or WCF will not serialize the data element.
This is still true 6 years after the question was asked, even when using the new WCF Client in .NET Core and Visual Studio 2017, and it isn't especially obvious, so I thought I'd promote the OP's comment response to wiki answer.
This is most likely occuring because WCF contracts treat enums differently. For data contracts you mark the class with a DataContract attribute and the members with a DataMember attribute. What's not as well known is that enums have their own attribute called EnumMember which WCF uses to serialize them properly.
There is an MSDN article called Enumeration Types in Data Contracts which goes over the usage in greater detail. The example code from the article shows how a contract with an enum should look:
[DataContract]
public class Car
{
[DataMember]
public string model;
[DataMember]
public CarConditionEnum condition;
}
[DataContract(Name = "CarCondition")]
public enum CarConditionEnum
{
[EnumMember]
New,
[EnumMember]
Used,
[EnumMember]
Rental,
Broken,
Stolen
}
Note that in their example (which I've included above) you can set just a subset of the enum values as part of the data contract if that's a requirement.
In addition to this any property that is not tagged with the DataMember attribute will not serialize over the wire. This should be the checklist to ensure that serialization works for WCF:
Check that classes are marked with the DataContract attribute.
Check that properties are marked with the DataMember attribute.
Check that the individual enum values are marked with the EnumMember attribute.

WCF Operation parameter and return type must have datacontract attribute (always)?

could some one please confirm whether I should always have a DataContract and datamember attribute for Operation Parameter and return types?
e.g.
ResponseMessage getOrderDetails(RequestMessage msg)
{
....
}
public class ResponseMessage
{
...
}
public class RequestMessage
{
...
}
It was required only in very first version of WCF (.NET 3.0). After that default data contract serialization was introduced so you don't have to place DataContract attribute on your classes and all public properties with getter and setter will be serialized. Once you want better control over serialization you will use DataContract and DataMember attributes or you will switch to Xml serialization.
The parameter types and return types need to be either serializable or treated in a special way by WCF.
For the first case, [DataContract] and [DataMember] is only one way to make a type serializable - the post at http://blogs.msdn.com/b/sowmy/archive/2006/02/22/536747.aspx describes the serialization programming model in WCF. As Ladislav mentioned, starting with .NET 3.5 SP1 WCF introduced a default (POCO) serialization so you don't need any annotation at all.
For the second case, there are some types which are treated as special cases by WCF, such as System.IO.Stream or System.ServiceModel.Channels.Message - and you can even add more such types if you use a custom message formatter (although this is an advanced scenario and not very common).

Why can I not use the KnownType attribute in my WCF class?

I am using WCF to retrieve a collection of objects. The objects are all of type ProcedureText but may be of child classes SuspensionText or ResumptionText, both of which inherit from ProcedureText.
public class ProcedureText { }
public class SuspensionText : ProcedureText { }
public class ResumptionText : ProcedureText { }
My OperationContract specifies a method returning an array of ProcedureText objects:
[OperationContract]
[WebGet(UriTemplate = "procedureTexts")]
ProcedureText[] GetProcedureTexts();
This works if I cast all my objects to ProcedureText but I want to keep the distinction of using the sub-types. I had hoped to use the KnownType attribute to do this and had expected to be able to do it by adding it to my ProcedureText class:
[System.Runtime.Serialization.KnownType(typeof(SuspensionTextDto))]
[System.Runtime.Serialization.KnownType(typeof(ResumptionTextDto))]
public class ProcedureText { }
This doesn't work because the compiler cannot resolve System.Runtime.Serialization.KnownType. I know from the document that the attribute is part of .NET Framework 4, but I am using .NET Framework 4 and that is the Target Frameweork for my project.
Why do I need to set to be able to use the attribute?
The relevant DLL containing that type is not added by default. You need to add a reference to:
System.Runtime.Serialization
The usage is described in the documentation:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx
Basically it is so that the serializer recognises the type. Your service contract returns an array of the base class, however the types in that array could be more derived. If the serializer is not told this, the serialization will fail I think.
Without explicitly adding the reference to the project, I was able to use " I was able to use "using System.Runtime.Serialization" in my code but when I used attributes like "KnownType" or "DataMember" the compiler gave an error.
I was able to overcome this issue by explicitly adding the reference. Go to "Add References" in your project and search for "System.Runtime.Serialization" under Assemblies and add the dll to the project.
Works in .net 4.5 and 4.5.1 so I assume this will work in 4.0 as well.

How can I implement a custom QueryStringConverter for RESTful WCF?

I've implemented a customized QueryStringConverter class and hooked it up using a customized WebHttpBehavior subclass. When I make a service call, it hits my breakpoint in the CanConvert override (and I return true for this parameter), but it never calls my ConvertStringToValue override, and ends up just passing null to the service call... why is ConvertStringToValue never called and how can I fix it?
This is not possible.
Microsoft were so sloppy with the implementation of this functionality that they merely newed up the standard QueryStringConverter instread of using the one configured in the configuration file.
There are no work arounds that actually work. The second one in the bug report doesn't actually work at all.
The short answer is that you cannot.
See the bug here: http://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost#tabs
It is still broken in framework 4.0.
My guess is that it's not important - so perhaps take the time to increase the counts on the bug.
Regards
Craig.
I know it is quite old question. For any one who looking for some answer, you should be able to add the TypeConverter to your class which can convert type to and from string representation
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.querystringconverter.aspx
Types that have a TypeConverterAttribute that can convert the type to
and from a string representation.
Do some thing like this:
In contract file
[OperationContract]
[WebGet(UriTemplate = "/TabelasAuxiliares?requestex={requestex}", ResponseFormat = WebMessageFormat.Xml)]
CadastrodeEscolasResponse TabelasAuxiliares(string requestex);
In the Service file
public CadastrodeEscolasResponse TabelasAuxiliares(string requestex)
{
XmlSerializer serializer = new XmlSerializer(typeof(CadastrodeEscolasRequest));
StringReader rdr = new StringReader(requestex);
CadastrodeEscolasRequest request = (CadastrodeEscolasRequest)serializer.Deserialize(rdr);
}
Conslusion:
Call the service by sending Xml format data to a string parameter. Then convert the xml to the required class object. This way you can avoid creating QueryStringConvertor which is quite cumbersome. Hope this will help! This help is for all and not just for this post.

WCF MessageContract Inheritance

I am fairly new to WCF and just have a question on how to correctly get MessageContract inheritance working. A simplified version of my setup is as follows - a "base" message type, and then another "test" message which inherits from it.
[MessageContract]
public abstract class BaseMessage
{ }
[MessageContract]
public class TestMessage : BaseMessage
{ }
I then have an asynchronous OperationContract on a ServiceContract defined as:
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginFindRequest(BaseMessage request, AsyncCallback callback, object asyncState);
The problem that I am getting is when calling the BeginFindRequest method, and passing in a TestMessage instance for the request parameter, the WCF framework is deserialising the TestMessage instance to BaseMessage on the service/server side. As this is defined as an abstract class, it results in the following error:
"The message cannot be deserialized
into MessageContract type BaseMessage
since it does not have a default
(parameterless) constructor."
From the limited information that I can find on MessageContract inheritance, it seems that it should just work.
So my question is - what am I missing in order to get this to work; or should I perhaps rather define a seperate OperationContract on the ServiceContract specifically for that type - the downside being that I could end up with many additional OperationContracts?
In the end I found this blog post which hit the nail on the head -
Unfortunately the way that contracts
are expressed in WCF makes is very
easy to forget what their purpose is:
to define the messages send to the
operation and being sent back from the
operation. In reality you have to
think “how would I express this data
in XML?”. XML doesn’t support
inheritance so whatever you put in the
contract is going to have to have some
way of mapping to XML. The data
contracts used to define the messages
are simply a .NET typed convenience
for generating the XML for the data
you want to pass – if you view them
any other way you are destined for a
world of pain. So think about the data
you want to pass, not how it may
happen to be represented in your
business layer and design your
DataContracts accordingly.
http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx
So I will be refactoring to provide an additional method with an explicit contract type. This will also allow me to clean up the service implementation by removing all the type checking.
Thanks for the assistance.
OK, first question is: why are you really using Message contracts? Do you really have a need for that??
Typically, message contracts are only ever used when you need to tightly control the layout of your SOAP message, e.g. to satisfy a legacy system you need to call which requires specific headers and such.
A "normal" WCF call should hardly ever need to use a message contract.
You define your service calls (the methods on your service) using [ServiceContract], and the data structures being passed around as [DataContract]. If you have a DataContract, you have more options as to how to deal with inheritance / polymorphism in your service (more than with the message contract construct).
Marc
Is that possible to change BaseMessage so that it is concrete class with parameterless constructor?
The error message tells that there is no way to initialize the object of type BaseMessage because it is abstract.
The error simply wants you to have a default empty contructor that it can use. However, I agree with marc_s; in the projects I've worked on I've rarely used message contract, the only case I can remember was as part of a file transfer service where file chunks were passed in messasges.
Try decorating your [ServiceContract] with the KnownType attribute. Since TestMessage is not 'visible' from a public operation, this helps the plumbing know how to treat it when it sees it.
If this should allow the [DataContract] to be serialized as a TestMessage your still likely to need to handle multiple messages differently via 'is a' or some other casting.
Well I had declared this default (parameterless) constructor for sure, but that was not still working fine for me, for me the issue was, the access modifier was protected while it should be public:
public constructor() { }
^^^^