Wcf DataMember field is list<string> - wcf

In a WCF class (with [DataContract] attribute) I have this field:
[DataMember]
public List<string> XYZ;
But when I add a reference to the url of this service, in the Reference.cs file this field becomes
private string[] XYZ;
There must be, as usual, a very subtle reason for this, and I really would like to understand it!

There is an option for it in Visual Studio. While you are adding new service reference, click Advanced... button in Add Service Reference dialog and select how do you want to represent collection types:

In your case, you need to select collection type as System.Collections.Generic.List and Dictionary collection type as System.Collections.Generic.Dictionary

Related

WCF proxy always showing an array and not a List<T>

I'm using WSSF in Visual studio 2010 sp1 and I'm having an issue with WCF collections. It seems that when I create a service reference and change the advanced setting to use a Generic list instead of an array. I still get arrays when trying to use the collections. I would have to convert the array back and forth to a list whenever i want to add or remove objects.
Does anyone know why? or what i need to change for it to work ok. In the data contract designer, i have two types of collections. One is a "Data Contract Collection", another one is "Primitive Data Type Collection".
Any help is appreciated.
I haven't used WSSF but at a base level WCF ILists are handled as arrays. You would have to manually serialise the DTO as a List. Perhaps that's what's happening underneath the covers?
[DataMember]
public IList<Blah> BlahList
{
get { return blah; }
set { blah= new List<Blah>(value);
}
private List<Blah> blah;

Change datamember name based on method

[DataContract()]
public class Contract
{
.........
Some Properties with DataMembers Attribute.
............
..............
[DataMember(Name = "FirstName")]
public string Name { get; set; }
}
I have above class and I have two web methods (operations)
In 1st web method I want to expose Name as FirstName and in 2nd web method expose Name as LastName.
I don't want to create separate data contracts.
Please tell me how to achieve this?
You can use reflection and change the value of the attribute at runtime depending on which method you in currently. Check out these links on StackOverflow:
How to set attributes values using reflection
Change Attribute's parameter at runtime
But I think the best way would be to either have 2 separate contracts or create a contract with both properties.
You can also implement a surrogate to special-case this type during serialization. As an example, see the Data Contract Surrogate sample.

An alternative way to use Azure Table Storage?

I'd like to use for table storage an entity like this:
public class MyEntity
{
public String Text { get; private set; }
public Int32 SomeValue { get; private set; }
public MyEntity(String text, Int32 someValue)
{
Text = text;
SomeValue = someValue;
}
}
But it's not possible, because the ATS needs
Parameterless constructor
All properties public and
read/write.
Inherit from TableServiceEntity;
The first two, are two things I don't want to do. Why should I want that anybody could change some data that should be readonly? or create objects of this kind in a inconsistent way (what are .ctor's for then?), or even worst, alter the PartitionKey or the RowKey. Why are we still constrained by these deserialization requirements?
I don't like develop software in that way, how can I use table storage library in a way that I can serialize and deserialize myself the objects? I think that as long the objects inherits from TableServiceEntity it shouldn't be a problem.
So far I got to save an object, but I don't know how retrieve it:
Message m = new Message("message XXXXXXXXXXXXX");
CloudTableClient tableClient = account.CreateCloudTableClient();
tableClient.CreateTableIfNotExist("Messages");
TableServiceContext tcontext = new TableServiceContext(account.TableEndpoint.AbsoluteUri, account.Credentials);
var list = tableClient.ListTables().ToArray();
tcontext.AddObject("Messages", m);
tcontext.SaveChanges();
Is there any way to avoid those deserialization requirements or get the raw object?
Cheers.
If you want to use the Storage Client Library, then yes, there are restrictions on what you can and can't do with your objects that you want to store. Point 1 is correct. I'd expand point 2 to say "All properties that you want to store must be public and read/write" (for integer properties you can get away with having read only properties and it won't try to save them) but you don't actually have to inherit from TableServiceEntity.
TableServiceEntity is just a very light class that has the properties PartitionKey, RowKey, Timestamp and is decorated with the DataServiceKey attribute (take a look with Reflector). All of these things you can do to a class that you create yourself and doesn't inherit from TableServiceEntity (note that the casing of these properties is important).
If this still doesn't give you enough control over how you build your classes, you can always ignore the Storage Client Library and just use the REST API directly. This will give you the ability to searialize and deserialize the XML any which way you like. You will lose the all of the nice things that come with using the library, like ability to create queries in LINQ.
The constraints around that ADO.NET wrapper for the Table Storage are indeed somewhat painful. You can also adopt a Fat Entity approach as implemented in Lokad.Cloud. This will give you much more flexibility concerning the serialization of your entities.
Just don't use inheritance.
If you want to use your own POCO's, create your class as you want it and create a separate tableEntity wrapper/container class that holds the pK and rK and carries your class as a serialized byte array.
You can use composition to achieve what you want.
Create your Table Entities as you need to for storage and create your POCOs as wrappers on those providing the API you want the rest of your application code to see.
You can even mix in some interfaces for better code.
How about generating the POCO wrappers at runtime using System.Reflection.Emit http://blog.kloud.com.au/2012/09/30/a-better-dynamic-tableserviceentity/

WCF exposing generic type 'T'

I write a WCF service for Insert and delete operation here we used generic method but it gives following error
"System.Runtime.Serialization.InvalidDataContractException: Type 'T' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types."
here "EntityBase2" is base class for all entities
[ServiceContract]
[ServiceKnownType(typeof(EntityBase2))]
public interface IBackupUtility
{
[OperationContract]
void Delete<T>(T entity) where T : EntityBase2;
[OperationContract]
void InsertORUpdate<T>(T entity) where T : EntityBase2;
}
Question is how i can expose generic type 'T'?
I think it is imposible, how could it generate the wsdl that way?
You have two options:
You could send the type as a parameter.
If you want to expose crud operations for entities I would recommend to use a code generator, maybe a T4 template for EF.
This post is old indeed, but maybe someone find this solution useful:
WCF and Generics
Answer to this question is both Yes and No. Yes for server prospective and No for client prospective.
We can create a generic Data Contract on server but while using that in any operation contract we have to specify a data type of the generic.
And at client end that data contract will be exposed only as a strongly data type not generic.
[DataContract]
public class MyGenericObject<T>
{
private T _id;
[DataMember]
public T ID
{
get { return _id; }
set { _id = value; }
}
}
[OperationContract]
MyGenericObject<int> GetGenericObject();
This is what we have in Server we can see while using generic data contract we have to specify the type otherwise it’ll give compile time error.
On client what we get from WSDL is a follow:
[DataContract]
public class MyGenericObjectOfint
We can see here what we get from WSDL is not a generic data contract WSDL proxy generate a class with a new name using some convention.
Convention used is
Generic Class Name + "Of" + Type Parameter Name + Hash
Hash is not always generated, it’ll be generated only when there is a chance of name collision.

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!