locked
Datatype not understood by webservice RRS feed

  • Question

  • User670644709 posted

    Hi, 

    I have created a web service interface with method like,

    Hide   Copy Code
    [OperationContract]
    
           
            string Log(string COMMENTS, string product, Dictionary<string, List<string>> analysisComp);



    The issue here is if i try to consume this webservice and try to pass the values to Dictionary <string , List<string>> variable it gives me the following error:

    Hide   Copy Code
    cannot convert from 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>' to ArrayOfKeyValueOfstringArrayOfstringty7Ep6D1KeyValueOfstringArrayOfstringty7Ep6D1[]	



    CAn you please advise if i cant use this datatype of Dictionary in my webservice method what would be the best alternate for it..

    Thanks,.

    Thursday, September 27, 2018 8:33 AM

Answers

All replies

  • User1120430333 posted

    You should be using a DTO for transmission of data, which can be a known datacontract.

    Why a DTO? 

    https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)

    <copied>

    Encapsulation is one of the fundamentals of OOP (object-oriented programming). It refers to the bundling of data with the methods that operate on that data. Encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties' direct access to them. Publicly accessible methods are generally provided in the class (so-called getters and setters) to access the values, and other client classes call these methods to retrieve and modify the values within the object.

    <end>

    https://en.wikipedia.org/wiki/Data_transfer_object

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    string COMMENTS, string product, Dictionary<string, List<string>> analysisComp

    All of it should be public properties inside a DTO traveling between client and service.

    Thursday, September 27, 2018 1:00 PM
  • User1724605321 posted

    Hi mmazeemahmad ,

    Could you please provide client code which call the WCF service ? 

    Best Regards,

    Nan Yu

    Friday, September 28, 2018 5:45 AM
  • User670644709 posted

    Hi Nan Yu, 

    Here are more details:

    I created two C# solutions 1 from where i am hosting the Web service and the other one is consuming it, for the first solution i write the code to accept the parameters as follows:

      [OperationContract]
    
           
            string LogSS(string priority, string Reason,  string COMMENTS,  Dictionary<string, List<string>> analysisComp);

    While at consumption side, i added a web reference with the succeeding mapping: 

    Then i clicked Add web reference button to add the reference to the hosted service. 

    The code i write to access the webservice is as follows:

                string priority = "3";
                string Reason = "Reason";
                string COMMENTS = "COMMENTS";
                Dictionary<string, List<string>> analysisComp = new Dictionary<string, List<string>>()
                {
                    ["CHEM"] = new List<string> { "Water", "Liquid" },
                    ["Basse"] = new List<string> { "Acid", "Calcium", "Magnesium" }
                    
                };
                string ID = consume.LogSS(priority, Reason, COMMENTS, analysisComp);
                Console.WriteLine(ID, true);
    
                Console.ReadLine();

    While executing it gives the following error:

    Error	CS1503	Argument 13: cannot convert from 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>' to 'WebSeriveConsumeWCF.Service.ArrayOfKeyValueOfstringArrayOfstringty7Ep6D1KeyValueOfstringArrayOfstringty7Ep6D1[]'	WebSeriveConsumeWCF

    Please Advise Thanks. 

    Note: without Dictionary <string>... parameter the web service is working absolutely fine. 

    Tuesday, October 2, 2018 7:23 AM
  • User-1629691846 posted

    WCF is strongly typed. It will not understand if you pass dictionary from your client. You should create a class that internally uses dictionary or create your own key-value pair class. That is called as DTO (Data Transfer Object). 

    You will get the type of DTO at your client side. Just fill that type object with your data and send it to your service.

    Tuesday, October 2, 2018 11:14 AM
  • User670644709 posted

    Thanks Rohit for your prompt reply..

    But as my dictionary contains alot of data which needs to be inject to the hosted c# class. How can i make DTO around it.

     Dictionary<string, List<string>> analysisComp = new Dictionary<string, List<string>>()
                {
                    ["CHEM"] = new List<string> { "Water", "Liquid" },
                    ["Basse"] = new List<string> { "Acid", "Calcium", "Magnesium" }
                    
                };

    Tuesday, October 2, 2018 11:21 AM
  • User-1629691846 posted
    Dictionary is not by default serializable. You need to create a serializable dictionary. You can just create a wrapper around .net dictionary type and use that type in your application. See below:

    https://weblogs.asp.net/pwelter34/444961
    Tuesday, October 2, 2018 12:15 PM
  • User670644709 posted

    Is there any other simple way to avoid this such as using any other datatype that can hold the values exactly as Dictionary does, key-pair. 

    I have seen the following List 

     List<KeyValuePair<string, List<string>>> list = new List<KeyValuePair<string, List<string>>>() 
    {
    ["CHEM_AMINE"] = new List<string> { "Water", "Flexorb" },


    };

    but its not working for me if i want it list string inside a List datatype. 

    Tuesday, October 2, 2018 12:35 PM
  • User475983607 posted

    Try using the SerializableDictionary type.

    https://msdn.microsoft.com/en-us/library/gg496181.aspx?f=255&MSPPError=-2147217396

    This issue is fairly well known issue and there's are a lot of code out there on the interwebs that a Google search will turn up.

    However, I would stay away from .NET types like a dictionary, data table, namevalue pair, etc and just create an array using standard types.

    A basic object model example that you can modify to fit your needs.

        [DataContract]
        public class CustomDictionaryItem
        {
            [DataMember]
            public string Key { get; set; }
            [DataMember]
            public string[] Value { get; set; }
        }
    
        [DataContract]
        public class CustomDictionary
        {
            [DataMember]
            CustomDictionaryItem[] Items { get; set; }
        }

    General information

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/types-supported-by-the-data-contract-serializer

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, October 2, 2018 1:56 PM