0

Add wcf reference: the file Reference.cs can not generate [System.Runtime.Serialization.DataContractAttribute(Name="ClassName", Namespace="..."] but generate [System.Xml.Serialization.XmlTypeAttribute(Namespace="...")] on top of a className(DataContract). For example: enter image description here but I want to let Reference.cs generate the below code:

enter image description here

How to do it? if it is [System.Xml.Serialization.XmlTypeAttribute(Namespace="...")] , wcf transfer parameter ClassName's instance cause ClassName's Int32 FieldName = 0. but if it is [System.Runtime.Serialization.DataContractAttribute(Name="ClassName", Namespace="..."], wcf transfer parameter ClassName's instance can get correct value.

How to resolve it?

My server interface:

enter image description here

My model :

enter image description here

Superman
  • 285
  • 5
  • 17
  • Your WSDL is not "compatible" with DataContractSerilizer. https://msdn.microsoft.com/en-us/library/ms731923(v=vs.110).aspx - it falls back on XmlSerializer – tom redfern Mar 13 '17 at 11:55
  • Thanks for your reply! But My Model is [DataContract], why auto-generate XmlTypeAttribute, how to resolve it ? – Superman Mar 14 '17 at 05:53
  • 1
    Also, please remove the screenshots of code and put the actual code in the question. It's very difficult to read. – tom redfern Mar 15 '17 at 12:11
  • The specific reason `XmlSerializer` is getting used instead of `DataContractSerializer` for your `UserPrivilegeInfo` type when contained in a `DataTable` inside a `DataSet` is explained in [Cannot serialize member … of type System.Collections.Generic.Dictionary`2 because it implements IDictionary](https://stackoverflow.com/a/34445868/3744182). – dbc Mar 19 '17 at 20:50
  • @dbc, thank you very much! – Superman Mar 20 '17 at 01:33

2 Answers2

3

DataContract serializer is the default for WCF. There are several possible reasons why XML serializer is used in your case:

  1. If the schema is not compatible with the DataContractSerializer, the XmlSerializer is selected. Check this article for details.

  2. Attribute XmlSerializerFormat is applied on the service

Could you check whether one of above points is your case? If it doesn't work for you, please provide definitions for UserPrivilegeInfo and your service contract (both interface and implementing class)

UPDATE:

Ok, now we've identified that forced use of XmlSerializer was caused by returned DataSet.

It's generally a bad practice to return DataSet from WCF service. These articles explain why:

Returning DataSets from WebServices is the Spawn of Satan and Represents All That Is Truly Evil in the World

Why returning dataset or data table from WCF service is not a good practice? What are the Alternatives?

Consider returning DTO (Data transfer object) instead of messy DataSet. You just fill DTO fields from the DataSet and transfer DTO to the client. The client accesses the data through strongly typed DTO by fields like Id, Name, etc.

In your case redefine method GetCenterWebUser() in the following way:

    [DataContract]
    public class CenterWebUser
    {
        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public string Email { get; set; }

        //  Other fields for the user
    }

    public class SomeService : ISomeService
    {
        public CenterWebUser GetCenterWebUser()
        {
            DataSet ds = ...;

            var userTable = ds.Tables["Users"];
            var userRow = userTable.Rows[0];

            return new CenterWebUser()
            {
                Name = userRow.Field<string>("Name"),
                Email = userRow.Field<string>("Email")
                // ...
            };
        }
    }
}
Community
  • 1
  • 1
CodeFuller
  • 30,317
  • 3
  • 63
  • 79
  • I have upload my server interface and model? could you help me?Thanks! – Superman Mar 15 '17 at 08:37
  • In the picture, UserPrvilegeInfo info is cut. Is DownloadNum the last field in this DataContract? Is it possible to copy/paste real code snippets, not the code screenshots? – CodeFuller Mar 15 '17 at 09:49
  • Thnak you very much! – Superman Mar 16 '17 at 00:50
  • @CodeFuller - so my initial suspicion was correct. Go me! However, I +1'd you because your answer is clearly superior, and because you linked to the spawn of satan article. Apples, or a box with a picture of apples on it? – tom redfern Mar 16 '17 at 08:28
  • @tom redfern, Thanks for all of you! I have learned a lot about all of you! – Superman Mar 20 '17 at 01:41
2

You are using a DataSet as a return type. This is almost certainly the reason why WCF is falling back to the XmlSerializer rather than using the DataContractSerializer.

The DataContractSerializer has a strict set of rules about the types it supports for serialisation, and an even stricter set of rules around what XSD it supports. By including exposing a DataSet across your service boundary you are almost certainly violating these rules.

  1. Remove the DataSet.
  2. You're golden!

The other thing - why does it even matter to you whether the declarative attribute on your service reference says XmlTypeAttribute or DataContractAttribute? This should not matter to a consumer.

Do you have access to the service code? If I were you I would drop the service reference altogether and just consume the service directly using ChannelFactory<T>. Service references are complex, unpredictable, indirect, and often do not work.

Once you've removed the ludicrous DataSet from the return type, of course.

Community
  • 1
  • 1
tom redfern
  • 30,562
  • 14
  • 91
  • 126