Can't access public class from web service - c#

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.
The web service old ASMX
Web service client is being created through VS add service reference
Using VS 2017 pro - version 15.6.7.
After publish if I de-compile the dll then the PathNames class is there. So it's clearly in the dll.
I have look at this but still no luck.

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://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-data-contracts
To understand the various Limitation of Data Contracts please refer : -https://learn.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.

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
}
}
}

You can see how creating a Custom ASP.NET Web Service.
Might you need to rebuild web service ASP.Net and add your assembly to the global assembly cache (GAC).
I hope this help you.

Related

How can I override or add an attribute to a method in a separate class so that refreshing a WCF service doesn't blow away my changes?

I have many WCF services that I'm wrapping with a proxy and I use the automatically generated contract classes for each service.
I see there are some stubs (ex. static partial void ConfigureEndpoint) that I can put in a separate class, but I've made other contract changes that get blown away when I update/refresh the WCF service. I'm very new to C#/ASP.NET-Core for some context.
A sample change in the contract is below where I added an attribute to default the company...how can I persist this attribute somehow through WCF refreshes?
[DefaultValue(Constants.DefaultCompany), Required] // I added this because I want to default a company
public string Company
{
get
{
return this.companyField;
}
set
{
this.companyField = value;
}
}
Another sample change I made was changing public to internal for this method because I don't want it displayed in Swagger and this field is a constant. When I refresh the WCF it comes back as public.
internal string PartitionKey // I changed public to internal
{
get
{
return this.partitionKeyField;
}
set
{
this.partitionKeyField = value;
}
}
Let's say you've added a service reference and Visual Studio generated a proxy called MyServiceClient. It might look a little like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class MyServiceClient : System.ServiceModel.ClientBase<MyService>
{
As you have found, if you modify MyServiceClient, your modifications will get overwritten if you refresh the service reference. To get around this, do not modify it directly. Instead, subclass it.
public class MyModifiedServiceClient : MyServiceClient
{
//Make changes here
}
Now in the rest of your c#, instead of using MyServiceClient, always use MyModifiedServiceClient. The derived class will not get overwritten when you refresh the service reference.

Web API converted to Azure Mobile Service not serializing all properties

I have a working Web API that i am converting to a .Net Azure Mobile Service. The API returns a complex model - objects with properties - some of which are collections of other objects. This works as expected with plain Web API but with Azure Mobile Services I have an issue where one of my models does not have all it's properties serialized.
When i set a break point on the return statement in the controller, I see that all the properties and their values are present. This leads me to believe that the issue is with serialization (JSON).
return Request.CreateResponse(HttpStatusCode.OK, myModel);
Examples of properties that are being serialized:
public Guid Id { get; set; }
public IEntityDto ModelDto { get; set; } //this is an object with many properties all of which serialize
Examples of properties that are NOT being serialized:
public ItemStatus Status { get; set; } //this is an enum
public string Message { get; set; }
public string TestProp { get; set; } //this is a simple string property I added to help debug
How can I go about further debugging this so that i can see why these properties are being excluded?
Note: At the moment I am still running this locally not off Azure. This is with Visual Studio 2013 Update 2 RTM.
UPDATE: Upon closer inspection it appears that the properties not being serialized are properties that are either enums or have a value of null.
As #carlosfigueira mentioned in a comment to the original question, the default behavior of the JSON serializer is to exclude properties with null and default values. To address this I changed the following settings:
httpConfig.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Include;
httpConfig.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
...where httpConfig is of type HttpConfiguration. You can make these changes on app start - in a config file like WebApiConfig.cs or directly in Global.asax.cs.

Maintain a Dictionary with WCF RESTful Service

I need to write a RESTful WCF service that maintains a dictionary (or any other suitable data structure) with userId:userData as key:value pairs.
For that I first need to implement an interface for getting and setting userData (the specific configuration is enclosed):
GetConfiguration() : returns default config when user hasn’t set a config yet
GetConfiguration(string id)
SetConfiguration(string id, Configuration configurationSchema)
Then I'll need to write a service that implements this interface.
As a newbie in WCF I'm not sure how to do it. I tried to look for relevant references but didn't found any.
Appreciate any help/relevant references, Thanks !
The userData object:
public class ConfigurationSchema
{
public string MobileNumber { get; set; }
public List<string> Habits { get; set; }
public ConfigurationSchema(string mobileNumber, List<string> habits)
{
this.MobileNumber = mobileNumber;
this.Habits = habits;
}
}
may be below video will help you to create a WCF service. Once create simple WCF service after that add your code.
https://www.youtube.com/watch?v=GzN1vHWlJjA
If you did not find references to help you, I'd suggest you learn to google before you tackle programming problems. It's worth it. For your problem:
Open Visual Studio
Chose WCF project
Replace example complex data structure by your own class
Rename methods
Rename interface
Press F5

Why do my WCF class names have the parent class as part of their name?

I've been experimenting with Silverlight-Enabled WCF services and I'm getting a strange behavior that doesn't happen in the tutorial I was using. I create a simple operation contract like such: (yes, I know there is no interface with everything defined, it's something that the Silverlight-enabled template does)
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TestService1
{
public class TestResponse
{
public string Hello { get; set; }
}
[OperationContract]
public TestResponse TestCall()
{
return new TestResponse();
}
}
Then I go and create a reference to it like I would a regular WCF service. But when I go to use my defined classes:
ServiceReference2.TestService1TestResponse test = new ServiceReference2.TestService1TestResponse();
Whereas I'm expecting ServiceReference2.TestResponse. Any idea why my parent class name is being concatenated onto the front of my datamember class names? I added a service reference to a plain console application and the same thing happens, so it's not a silverlight related thing.. maybe some setting in Silverlight-enabled WEC services? I watched this tutorial https://www.youtube.com/watch?v=8ln2LyWvf6Q to see if it happened for others, but it looks like the class names work fine there.
Out of luck I discovered what the issue was. I need to have the TestResponse class declared outside of the TestService1 class. I'm a little surprised the code generator for creating service references creates the classes in this way. I'd expect a ServiceReference2.TestService1.TestResponse instead, which is what threw me off so much.

How do I configure log4net such that properties of an object can be mapped to the log output?

I am attempting to provide a means to log errors that occur in our Flex client by providing a SOAP web service which takes as a single parameter a LogMessage object.
public class LogMessage
{
public string Message { get; set; }
public string Exception { get; set; }
public string Version { get; set; }
public string User { get; set; }
}
This object is populated by the Flex client should a client side error surface and the LogClientError method is invoked which logs the error via log4net.
[WebMethod()]
public void LogClientError(LogMessage message)
{
rollingLogger.Error(message);
}
Currently this prints the fully qualified name of the LogMessage class, so my current assumption is that log4net simply calls .ToString() on the object that is passed in.
However, what I really want to be able to do is map each property in the LogMessage class to a pattern so that log4net will correctly write out the desired information. I would like to do this in such a manner that the typical appenders (DB, File, SMTP) are all still supported.
How do I configure log4net such that properties of an object can be mapped to the log output?
log4net has two paths you can take. The first would be to create a custom object renderer for LogMessage instances. You need to implement the IObjectRenderer interface and register the implementation.
The other route, which would be more reusable, is to subclass the patternlayout class. Your custom pattern layout could then support a special syntax for naming properties which the layout could use to reflect on the incoming message object.
If LogMessage is partial you could create a ToString() method on LogMessage.

Categories

Resources