Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't access public class from web service

I have a very weird scenario which I can't seem to figure out what's going on. I have a web service which is written in C# and the target framework is 3.5. I have many Classes and Methods but for simplicity I will make use of only two classes in the question.

public class PathNames
{
   private string _pathA = "Some Path";
   private string _pathB = "Another Path";
   public string BaseDirectoryPath
   {
        get
        {
            return Path.Combine(_pathA, _pathB); 
        }
   }
}

The second class is as follows:

public class UserInformation
{
   public string UserName { get; set; }
   ...//more properties 
}

Both of the above classes are in the same namespace.

The web service is referenced in a WebForm Application with the target framework being 4.0. Everything seems to be working fine and I can see the UserInformation class when I view it in Object Browser. However the PathNames class does not seem to be visible in the Object Broswer.

Both of the source files in question are set to Compile in the File Properties windows. I have 5 classes similar to that of UserInformation and same settings in the File Properties window where they are just simple POCO and only have public auto propteries. These all seem to be coming through and I can access them and see them in the Object Browser. For some strange reason I cannot PathNames class to come through. I have tried to add some new dummy classes and have the same issue as PathNames class. Can someone tell me what I am doing wrong please.

  1. The web service old ASMX

  2. Web service client is being created through VS add service reference

  3. Using VS 2017 pro - version 15.6.7.

  4. After publish if I de-compile the dll then the PathNames class is there. So it's clearly in the dll.

  5. I have look at this but still no luck.

like image 306
Izzy Avatar asked Apr 27 '18 13:04

Izzy


2 Answers

Using Data Contracts in web service

Service can't expose private/read-only properties. DataMember attribute is used for marking public members or properties (with public getter and setter) of class marked with DataContract attribute. DataContract can be used as parameter or return value of operation.

Windows Communication Foundation (WCF) uses a serialization engine called the Data Contract Serializer by default to serialize and deserialize data (convert it to and from XML), and XML serialization (by default) doesn't serialize read=only properties.

For More Information you can read the MS Docs for Data Contracts :- https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-data-contracts

To understand the various Limitation of Data Contracts please refer : -https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/types-supported-by-the-data-contract-serializer

Solution :

Anyway. What are you trying to do? Exposing properties means that you expect some stateful behavior. If you going to use this property in operation contract, which is seems to be, then you you must define the properties with public getter and setter so it can be serialized.

As the @Nikosi stated in previous answer, you have to define public setter for your BaseDirectoryPath property.

like image 58
Tapas Thakkar Avatar answered Sep 27 '22 18:09

Tapas Thakkar


The only difference based on the example provided that one property is readonly while the other can be modified.

In order to make the class serializable consider rafactoring the property

public class PathNames {
    private string _pathA = "Some Path";
    private string _pathB = "Another Path";

    public PathNames() {
        BaseDirectoryPath = Path.Combine(_pathA, _pathB);
    }

    public string BaseDirectoryPath { get; set; }
}

You can use a default constructor to set the default value of the property

or just have an empty setter on the property

public class PathNames {
    private string _pathA = "Some Path";
    private string _pathB = "Another Path";

    public string BaseDirectoryPath { 
        get {
            return Path.Combine(_pathA, _pathB);
        }
        set {
            //No OP
        }
    }
}
like image 40
Nkosi Avatar answered Sep 27 '22 19:09

Nkosi