I am developing a wcf web service. It was working correctly during unit testing. A few days back, I changed the default namespace from 'tempuri' as explained in this link: http://blog.rebuildall.net/2010/11/10/wcf_service_namespaces and also added 'Order' Property to the datamembers i.e. like [DataMember(Order = 1)] of both request and response classes. Now in one OperationContract, some parameters are being read as null at server side even though value is passed at client side. I also noticed that the responses of a couple of OperationContracts were showing empty tags when there should have been value in those tags.
On searching, I found blog with a similar problem, but what caused their problem was a name mismatch of a parameter in client and server side. The link to the blog is : http://blog.functionalfun.net/2009/09/if-your-wcf-service-is-unexpectedly.html
Can anyone guide me here. Thanks in advance
I dunno if anyone else manages to get this error the way I did, but this was the problem:
I had defined my classes like below:
public class CompositeType
{
private bool boolValue;
private string stringValue = "";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
By removing those variable declarations and using auto-property syntax, I was able to get past the issue. i.e like :
public class CompositeType
{
[DataMember]
public bool BoolValue
{
get;
set;
}
[DataMember]
public string StringValue
{
get;
set;
}
}
Related
I am writing a proxy to wrap a WCF service with ASP.net Core and this is my first time using ASP.Net core.
I am using an auto-generated WCF service contract, and the issue is my WCF service changes frequently, so I must update/refresh the WCF service, and whenever I update my contract, I lose my minor tweaks.
I'm only trying to:
Hide some properties - via changing public string Property to internal string Property. I've tried [IgnoreDataMember] and [JsonIgnore] but those don't seem to work
Make some properties required - via RequiredAttribute
Default some property values - via DefaultValueAttribute
I've tried two approaches so far but they're not working fully.
This represents the automatically generated WCF Contract where I want to require & default MyProperty1 and hide MyProperty2:
// This is the automatically generated WCF Contract
public partial class MyClass
{
private string myPropertyField1;
private string myPropertyField2;
public string MyProperty1
{
get { return this.myPropertyField1; }
set { this.myPropertyField1 = value; }
}
public string MyProperty2
{
get { return this.myPropertyField2; }
set { this.myPropertyField2 = value; }
}
}
Method 1:
ModelMetadataType to override the contract metdata. This partially works, but not for all attributes for some reason? It feels like a bug.
[ModelMetadataType(typeof(MyClassMetadata))]
public partial class MyClass { }
public partial class MyClassMetadata
{
[Required] // This does not work
[DefaultValue("SomeValue")] // This DOES work?
public string MyProperty1 { get; set; } // I want this required & defaulted
[IgnoreDataMember] // This does not work to hide
[JsonIgnore] // This does not work to hide
public string MyProperty2 { get; set; } // I want this hidden from Swagger view
}
Which works to default values, but it doesn't appear to make it required or hidden?
Method 2:
I tried creating derived class, and then using the derived class instead of MyClass for the controller api arguments, but then when I try to call it I receive an error that says something like Type MyClassDerived was not expected. Use XmlInclude to specify unexpected types...
public partial class MyClassDerived : MyClass
{
[Required] // This puts "*" next to it in Swagger
[DefaultValue("SomeValue")] // This defaults the value in Swagger
public new string MyProperty1
{
get { return base.MyProperty1; }
set { base.MyProperty1 = value; }
}
internal new string MyProperty2 // This works to hide from Swagger
{
get { return base.MyProperty2; }
set { base.MyProperty2 = value; }
}
}
How can I hide/default/require contract properties without directly modifying an auto-generated WCF contract service class?
I'm new to working with WCF and i'm struggling to understand whats happening.
I'm trying to retrieve data from my service, which in turn grabs it from the database. To simplify things I wanted to return an object containing the data so that it could just be used immediatly within the UWP app. However, I'm running into the following error when I try to consume the service:
Cannot implicitly convert type 'MBCMobile.ServiceReference1.TaskBreakdown_GetDataResponse' to 'MBCMobile.ServiceReference1.JobTestObject'
The following code is what I'm using:
[ServiceContract]
public interface IService1
{
[OperationContract]
JobTestObject TaskBreakdown_GetData(int task, int appliance, int job);
}
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Service1 : IService1
{
public JobTestObject TaskBreakdown_GetData(int task, int appliance, int job)
{
JobTestObject jobData = data.TaskBreakdown_GetData(task, appliance, job); //object returned from sql query
return jobData;
}
}
To consume my service im using the following:
private async void GetString()
{
ServiceReference1.Service1Client service = new ServiceReference1.Service1Client();
JobTestObject datalist = await service.TaskBreakdown_GetDataAsync(6153, 18876, 18111);
}
JobTestObject has the same format in both the service and the UWP app. The service version literally exists as a collection of get/set methods and nothing else. The app version has additional methods, but the exact same get/set methods. I've tried using ServiceReference1.JobTestObject instead to see if that helps but to no avail. I expect that it might be a little naive of me to think an object can be passed to the client this way.
I also tried just returning a list of strings and got a similar error.
I've managed fine in the past with retrieving single values from the service, but now that I want to get multiple values at once I can't understand what I'm doing wrong. Sadly most of the solutions I've found don't relate to UWP apps
Update: As requested
[DataContract]
public class JobTestObject
{
int appliance_id, manu_id, model_id, landlord_app, applianceType_id,
[DataMember]
public int ApplianceType { get { return applianceType_id; } set { applianceType_id = value; } }
[DataMember]
public int Appliance_ID { get { return appliance_id; } set { appliance_id = value; } }
[DataMember]
public int ApplianceManufacturer { get { return manu_id; } set { manu_id = value; } }
[DataMember]
public int ApplianceModel { get { return model_id; } set { model_id = value; } }
}
The issue is with the following class:
[DebuggerDisplay("{Kind}: {Identifier}")]
public class SocialConnection
{
public virtual Guid UniqueId
{
get { return Id; }
set { Id = value; }
}
// SocialConnectionKind is an enumeration
public virtual SocialConnectionKind Kind { get; set; }
public virtual string Identifier { get; set; }
}
Kind property never gets serialized: when I request an object which has an associated SocialConnection I never get the whole property.
BTW, if I manually call JsonConvert.SerializeObject it gets serialized. It should be something with the default media-type formatter but I can't figure out the solution so far.
The issue which was causing this serialization problem was very simple. Check SocialConnectionKind enumeration:
public enum SocialConnectionKind
{
Skype,
Facebook,
Twitter,
LinkedIn,
Hangouts
}
Did you already notice what could be the problem? The issue wouldn't be reproduced if the value would be any excepting Skype!
Why? Enumerations start with 0 and see how I've configured my WebAPI's HttpConfiguration:
config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling =
DefaultValueHandling.Ignore;
Which is the default value of the Enum default underlying type int? Yes, it's 0.
So, what solved the issue?
public enum SocialConnectionKind
{
Skype = 1, // <--- The issue was solved starting the enumeration from 1!
Facebook,
Twitter,
LinkedIn,
Hangouts
}
Another approach
As #Avner Shahar-Kashtan have pointed out in some comment, I could also solve this issue using [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] attribute:
[DebuggerDisplay("{Kind}: {Identifier}")]
public class SocialConnection
{
public virtual Guid UniqueId
{
get { return Id; }
set { Id = value; }
}
// SocialConnectionKind is an enumeration
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
public virtual SocialConnectionKind Kind { get; set; }
public virtual string Identifier { get; set; }
}
...and this way there's no need of starting an enumeration from 1.
Anyway, in my particular case, I prefer to stay with the start from 1 approach, because I find cleaner avoid polluting my POCOs with serialization-specific attributes because SocialConnection class lives in a shared library and this serialization issue is an implementation issue in a concrete project.
I'm working on a self hosting rest api used to monitor de status of several servers.
I was tasked that, when everything is working correctly, I should only return
{"response":"ok"}
But, when there's an error on queried server, or servers, I must return
{ "response" : [ {"agent":"<server>:<port>","port":"<port>" ,"Error":"<Description of the error>"} ] }
I was thinking on building a helper class to build object on this schema and returning them over the rest api
public class HelperErrorResponseClass
{
public string agent { get; set; }
public string port { get; set; }
public string Error { get; set; }
}
This is no problem, the issue is, how to deal when everything it ok. I have this Api response helper class
public class Response
{
public string response { get; set; }
}
But I'm seeing that I'll need to change the response property to List<HelperErrorResponseClass> in order to send the error response. Do you think that, if I stringify the List<HelperErrorResponseClass> object with Json.Net it will be returned in the desired format?
Edit: Forgot to add that, I-m using Web Api to build the rest service.
UDPATE:
After further research, I found a way to work this out.
Following this post, I was able to rewrite the helper classes like this
[DataContract]
[KnownType(typeof(List<HelperErrorResponseClass>))]
public class Response
{
[DataMember]
public object response { get; set; }
}
[DataContract]
public class HelperErrorResponseClass
{
[DataMember(EmitDefaultValue = false)]
public string agent { get; set; }
[DataMember(EmitDefaultValue = false)]
public string port { get; set; }
[DataMember(EmitDefaultValue = false)]
public string error { get; set; }
}
This work to fulfill my and my client needs... except for one little thing. When I get the result from a List, and given that I added the KnownTypes directive, my response is now this
{"response":[{"__type":"HelperErrorResponseClass:#AppCommonLib","Error":"ERROR","InstanceId":"<InstanceId> : <Port>","PortType":"<PortType>"},{"__type":"HelperErrorResponseClass:#AppCommonLib","Error":"ERROR","InstanceId":"<InstanceId> : <Port>","PortType":"<PortType>"}]}
Any idea how to get rid of that __type property of the response? make that it must be explicit to only return the declared properties of the helper class?
Simplest way to deal with this is to set the return type on the handling function to string, then you can check for errors and do something like;
//pseudo code to give an idea
if (errorsList.Count() > 0)
{
return JsonConvert.SerializeObject(errorsList);
}
else
{
return JsonConvert.SerializeObject(new Response("ok"));
}
Now this being said... Unless the people providing requirements aren't at all flexible you should just redo the design. How about just returning the errors array and the person calling the API can infer that if it's length is 0 then everything is working OK. Seems pretty straight forward, right? You could also just put all the properties on one object and those fields would just come back as null or empty strings. Or you could change you serializer settings to exclude them if they don't have a value.
Keep things simple and use an anonymous type.
if (condition)
{
return JsonConvert.SerializeObject(new { response = new { agent = "x", port = "y", error = "z" }});
}
else
{
return JsonConvert.SerializeObject(new { response = "ok"});
}
More info:
https://msdn.microsoft.com/en-us/library/bb397696.aspx
I personally don't think you need a Response class, especially that it is of object type. IMHO, you've overcomplicated the very simple issue that you have. It is not only the __type, but also other info like HelperErrorResponseClass:#AppCommonLib that isn't supposed to be there.
Another Issue you have is the incorrect name of the HelperErrorResponseClass class. This is not a helper class. It is a standard data-object class.
A helper class is a class filled with static methods. It is usually used to isolate a "useful" algorithm.
This is how I would do it:
I'd get rid of the Response class.
I'd use your original simple HelperErrorResponseClass class, but rename it to something more meaningful like ErrorDetails.
I'd return the response like this:
.
if (errorsList.Count() > 0) {
return JsonConvert.SerializeObject(new { response = errorsList});
}
else {
return JsonConvert.SerializeObject(new { response = "ok"});
}
However, if you really want to stick to your updated solution, an easy way to get rid of the __type is simply removing it from the final serialized string:
if (errorsList.Count() > 0) {
string r = JsonConvert.SerializeObject(new { response = errorsList});
return r.Replace("__type", "");
}
else {
return JsonConvert.SerializeObject(new { response = "ok"});
}
I have MVC project that relies on webservices to provide data and those webservices are based on CMIS specification with custom functionality. I have several classes used as DataContracts, which were created by Visual Studio when I added references to services I am calling. I am using that class as a model to ensure I am able to send instances to the service and process correctly those sent back to me.
I also have views to edit instances of those classes and I would like to use DataAnnotations to validate the forms (usually [Required] atribute and sometimes display name change).
I do not want to put those atributes in service reference files because updating the reference would mean I will loose those atributes (at least I could not be sure everything is still the same after reference update).
My thought was to create child class that would only serve as tool to introduce DataAnnotations to atributes I know for sure I will be using (those that will not dissapear from DataContract class for sure). How would I accomplish such inheritance with code?
Example - I have this class created by VS in reference.cs file:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="LibraryRequest", Namespace="http://schemas.datacontract.org/2004/07/Agamemnon.Models")]
[System.SerializableAttribute()]
public partial class LibraryRequest : DocuLive.RepositoryServiceExt.Library {
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string PasswordField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string ServerField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private bool UseDefaultField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string UserNameField;
[System.Runtime.Serialization.DataMemberAttribute()]
public string Password {
get {
return this.PasswordField;
}
set {
if ((object.ReferenceEquals(this.PasswordField, value) != true)) {
this.PasswordField = value;
this.RaisePropertyChanged("Password");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string Server {
get {
return this.ServerField;
}
set {
if ((object.ReferenceEquals(this.ServerField, value) != true)) {
this.ServerField = value;
this.RaisePropertyChanged("Server");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public bool UseDefault {
get {
return this.UseDefaultField;
}
set {
if ((this.UseDefaultField.Equals(value) != true)) {
this.UseDefaultField = value;
this.RaisePropertyChanged("UseDefault");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public string UserName {
get {
return this.UserNameField;
}
set {
if ((object.ReferenceEquals(this.UserNameField, value) != true)) {
this.UserNameField = value;
this.RaisePropertyChanged("UserName");
}
}
}
}
I want to make sure that no matter what changes in reference.cs file (even that class itself), I will always have Username, Password and Server marked as [Required] in my "Edit" and "Delete" forms.
Thanks in advance
Honza
I would stay away from inheriting an autogenerated class. It would not solve your problem with the attributes - you would have to override every single property so you can add attributes to it.
One solution is to use hand-coded datacontracts instead of autogenerated references. You will have full control over when they change, and you can put the attributes you need in them.
Another solution is wrapping the contract in your view model. Like this:
public class LibraryRequestViewModel {
private LibraryRequest request;
public LibraryRequestViewModel(LibraryRequest request){
this.request = request;
}
[Required]
public string Password {
get { return this.request.Password; }
set { this.request.Password = value; }
}
// do this for all fields you need
}