How to transfer objects through the header in WCF - wcf

I'm trying to transfer some user information in the header of the message through message inspectors.
I have created a behavior which adds the inspector to the service (both client and server).
But when I try to communicate with the service I get the following error:
XmlException:
Name cannot begin with the '<' character, hexadecimal value 0x3C.
I have also get exception telling me that DataContracts where unexpected.
Type
'System.DelegateSerializationHolder+DelegateEntry'
with data contract name
'DelegateSerializationHolder.DelegateEntry:http://schemas.datacontract.org/2004/07/System'
is not expected. Consider using a
DataContractResolver or add any types
not known statically to the list of
known types - for example, by using
the KnownTypeAttribute attribute or by
adding them to the list of known types
passed to DataContractSerializer.
The thing is that my object contains other objects which are marked as DataContract and I'm not interested adding the KnownType attribute for those types.
Another problem might be that my object to serialize is very restricted in form of internal class and internal properties etc.
Can anyone guide me in the right direction. What I'm I doing wrong?
Some code:
public virtual object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var header = MessageHeader.CreateHeader("<name>", "<namespace>", object);
request.Headers.Add(header);
return Guid.NewGuid();
}

Don't put the angle brackets into the actual strings. Remember, the serialization format may not even be text based, all you're doing is specifying the name of the element and the namespace. So your code should look more like this:
var header = MessageHeader.CreateHeader("name", "urn:myNamespace", object);
request.Headers.Add(header);

To close this question, I never solved the exception. Instead I implementated ISerializable which worked great for me.

Related

Locating the parameter of an Operation in System.ServiceModel.Channels.Message in WCF

Suppose we have the following Service contract:
[ServiceContract]
public interface IPing
{
[OperationContract]
string Ping(string parameter1, string parameter2);
}
I'm wondering, how it would be possible to find a particular parameter value, say the value of parameter1 for example, in the System.ServiceModel.Channels.Message created server side.
Thanks!
It's the task of the IDispatchMessageFormatter to convert between the operation parameters and the Message object. Usually the message is created with a XML body, and the parameters are XML elements, but that's just one possible implementation (it's perfectly valid for a formatter to completely disregard the message and assign whatever values it sees fit for the operation parameters).
You can learn more about message formatters in the blog post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx.

WCF Serialised List object giving strange names for objects

Here is the Method signature in the WCF service:
APIMessageList<APISimpleContact> GetMembers(string apiKey, APIContactSearchFilter filter);
APIMessageList inherits from IList. Once I have built a proxy against this WCF service the class name is APIMessageListOfAPISimpleContactjHldnYZV.
Why do I not get: APIMessageListOfAPISimpleContact?
It adds random text to the end of every APIMessageList object in the interface (there are several) They all end with the same few chars - jHldnYZV. I have looked online for possible causes, but I can't find any posts of people having this problem.
This is a purely cosmetic issue but this interface is exposed to our external customers so its appearance is important.
Anybody know why I am getting this problem?
Many thanks
Joe
Your solution will be at http://msdn.microsoft.com/en-us/library/ms731045.aspx. Basically, since you could have multiple "SimpleContract" classes (in different namespaces), WCF will add a disambiguation hash to the end of the contract name, which is what you have in the 8 chars at the end of the contract name. But you can control that, by using the CollectionDataContract and its Name property:
[CollectionDataContract(Name = "APIMessageListOfSimpleContract")]
public class APIMessageList : IList<SimpleContract> { ... }
We had a similar problem while using Generic types for return values. If we are not specifying a concrete type, the default data contract serializer or the WCF serializer is unable to infer the exact type of the returned entity. Hence it generates a random class name for the returned type.
In our project we overcame this problem by building a data contract which was of specific type and returned the same as a result of a WCF operation call.
My guess is that you are using a generic type and the serializer is unable to infer the type of the returned object.
I suggest you create a Data Transfer Object (DTO) and return the same from the WCF service. That should solve your problem.

WCF Service Contract

I have a problem using an custom data type in a WCF service method, below is my sample code
[ServiceContract()]
public class SampleServise : ISampleServise
{
void object GetSomething(ICustomData objectData)
{
// Do Something
}
}
What shall I do with ICustomData class interface?
Thanks
Afshin
WCF is based on message passing, and that message passing is modelled using XML schema (XSD). As such, whatever can be expressed in XML schema can be used in WCF.
This also means: interfaces are not supported. You need to use actual, concrete types for the parameters in your WCF service methods.
In your case, create a concrete class that implements ICustomData and then use that class as the parameter type.
For a good reference, read MSDN Designing Service Contracts which states for parameters:
Parameters and Return Values
Each operation has a return value and a parameter, even if these are
void. However, unlike a local method, in which you can pass references
to objects from one object to another, service operations do not pass
references to objects. Instead, they pass copies of the objects.
This is significant because each type used in a parameter or return
value must be serializable; that is, it must be possible to convert an
object of that type into a stream of bytes and from a stream of bytes
into an object.

Error using WCF and DataContractSerializer

I have a fairly complex object model that I'm trying to serialize using WCF. I'm running into a problem where I can create a new instance on the server and return it to the client, then trying to pass that same object back or even serialize it using the DataContractSerializer throws an exception.
Test method Server.Service.Test.SerializationTest.TestFilingSerialization threw exception: System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type MyNameSpace.MyObject. No set method for property '' in type ''
It's not giving me any info on a setter I'm supposedly missing, even though I've tried looking through the inheritance hierarchy for missing setters, I can't seem to get passed this. MyObject is a type of property on the object I'm trying to serialize, here's the funny part. In the setter for that property, I have code that looks like this:
set
{
_backingField = value;
_backingField.IsDirtyManager.SetIsDirty();
NotifyPropertyChanged("MyProperty");
if (!ContainsType(_backingField.GetType()))
{
Aggregates.Add(_backingField);
}
}
If I comment out the Aggregates.Add it goes onto the next property and throws the same exception there, the kicker is, it get's through other properties with the same code, before it hits this one and dies, so I don't know what the problem could be.
Anyone have experience where the real error is, because the Property name and Type are not filled out in the exception so it seems like the error has to be something else. If I just create a new instance on the client I can deserialize and serialize no problems, so there's gotta be something I'm missing here. Any ideas on what to look for?
EDIT
I am literally doing only this:
Create instance
Serialize
De-serialize
Re-serialize
Die here
I am assuming that the "Aggregates" is a list in your class.
If your class constructor does not create an Aggregates list, then it is null when you try to add items to it.
This does not match the error you are getting, but worth checking.
EDIT
In Visual Studio go into "Tools" -> "Options" -> "Debugging" -> "General" uncheck the option "Enable Just My Code". Then run it again, you may get a better error message.
Ok, figured it out. The last developer had set the Order property on the DataMember attribute. It was the property with the order before the property in the error message that was causing the problems. There were a couple read-only properties that I missed in that class.
You might see this if your setter is protected or private. If it's not marked public the serializer will not be able to set it. How do you have your Aggregates collection exposed?

Why am I getting this WCF Error Message?

I am getting the error below when I call my WCF service. What am I missing here?
'System.String[]' with data contract name
'ArrayOfstring:http://schemas.microsoft.com/2003/10/Serialization/Arrays'
is not expected. Add any types not known statically to the list of known
types - for example, by using the KnownTypeAttribute attribute or by adding
them to the list of known types passed to DataContractSerializer.'. Please
see InnerException for more details.
{"There was an error while trying to serialize parameter
http://tempuri.org/:myEntity. The InnerException message was
'Type 'System.String[]' with data contract name
'ArrayOfstring:http://schemas.microsoft.com/2003/10/Serialization/Arrays'
is not expected. Add any types not known statically to the list of known
types - for example, by using the KnownTypeAttribute attribute or by adding
them to the list of known types passed to DataContractSerializer.'.
Please see InnerException for more details."}
From what I gather, you have a WCF function that has a parameter named 'myEntity'. I'm assuming that the type of myEntity is a user-defined class and is adorned with the DataContract attribute, as it should be. I'm also assuming that the type of myEntity has a member field that is a string array. Let's assume that all of this is true (again, it'd be really helpful if you could post your code).
Ordinarily, string arrays, i.e., string[], will serialize just fine. But, in some cases (see here and here), you may have to add it to the list of known types in order for WCF to serialize everything correctly.
To do this, add the following:
[DataContract]
[KnownType(typeof(string[]))]
public class YourClassNameHere
{
}
You haven't posted the code, so my answer is based on the assumption that you have a class myEntity which you are trying to serialize. Try using a KnownTypeAttribute for the class
e.g.
[KnownType(typeof(myEntity))]
You can refer to the following MSDN link:
KnownTypeAttribute
Yes. As explained in the previous post, The issue occurs if you pass an array of a Type(which is defined as a DataContract]). you will need to define the array of this class as a seperate type and mark it as data contract.
Wont Work`
[DataContract]
Public class ABC{
}
...
SendData(ABC[])
`
What will work:
Public class Data{ public ABC[] prop{get;set;}}
...
SendData(Data);
In my case, after adding [Serializable] attribute to the MyEntity class. And then the issue came with serialization of the roles string array.
[Serializable]
[KnownType(typeof(string[]))]
public class MyEntity
{
.........
public string roles[]
.........
}
[KnownType(typeof(string[]))] worked like magic!