Reputation: 2503
I have created a WCF Rest API Service using wcf rest starter kit preview 2 which automatically return JSON or XML data depending on the requested content type. everything is working fine but as my service methods return multiple data type some methods returns a object of a class or collection of class, bool, int or collection type. so I planed to return a same Response in all methods for this I Create a new class as following:
[DataContract(Namespace = "")]
public class ServiceResponse
{
[DataMember]
public bool IsError
{ get; set; }
[DataMember]
public string ResponseMessage
{ get; set; }
[DataMember]
public Object ResponseData
{ get; set; }
}
and User class as following:
[DataContract(Namespace = "")]
public class User
{
[DataMember]
public string UserName
{ get; set; }
[DataMember]
public int UserID
{ get; set; }
}
In ServiceResponse Class I have declared an Object Type property ResponseData and my all method has return type of ServiceResponse. My problem is that when I set any string,bool,int type as ResponseData it is serialized but when I set collection type or an object of another class which also has DataContarct attribute this class is not serialized see below code :
public ServiceResponse GetUser(int userID)
{
User user = getUser(userID); get user data from database
ServiceResponse response=new ServiceResponse();
var response = new ServiceResponse
{
IsError = false,
ResponseMessage = string.Empty,
ResponseData = user; // Setting Result Data here
};
return response;
}
when I called above method(GetUser) I got Null response due to serialization problem, but following code works fine
public ServiceResponse TestMethod(string testMessage)
{
ServiceResponse response=new ServiceResponse();
var response = new ServiceResponse
{
IsError = false,
ResponseMessage = string.Empty,
ResponseData = testMessage; // Setting Result Data here
};
return response;
}
can anyone help me?
Upvotes: 1
Views: 7893
Reputation: 28701
The problem that you're having is due to the fact that in your DataContract
, you are declaring the ResponseData
as an Object
, but not telling WCF what types are valid known types. You need to explicitly tell WCF what known types are valid for your service, and you can do this by using the ServiceKnownType
attribute. I've taken your code and made a few modifications to demonstrate this:
[DataContract(Name="ServiceResponse")]
public class ServiceResponse
{
[DataMember(Name="IsError", Order=1)]
public bool IsError
{ get; set; }
[DataMember(Name="ResponseMessage", Order=2)]
public string ResponseMessage
{ get; set; }
[DataMember(Name="ResponseData", Order=3)]
public Object ResponseData
{ get; set; }
}
[DataContract(Name="User")]
public class User
{
[DataMember(Name="UserName", Order=1, IsRequired=true)]
public string UserName
{ get; set; }
[DataMember(Name="UserID", Order=2, IsRequired=true)]
public int UserID
{ get; set; }
}
[DataContract(Name = "User2")]
public class User2
{
[DataMember(Name = "UserName", Order = 1, IsRequired = true)]
public string UserName
{ get; set; }
[DataMember(Name = "UserID", Order = 2, IsRequired = true)]
public int UserID
{ get; set; }
}
[ServiceContract(Namespace = "WebApplication1")]
[ServiceKnownType(typeof(User))]
[ServiceKnownType(typeof(User2))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[OperationContract(Name="GetUser")]
[WebGet(UriTemplate = "GetUser/{userID}", ResponseFormat = WebMessageFormat.Json)]
public ServiceResponse GetUser(String userID)
{
User theUser = new User()
{
UserID=Convert.ToInt32(userID),
UserName="bob"
};
ServiceResponse sr = new ServiceResponse()
{
IsError = false,
ResponseMessage = "",
ResponseData = theUser
};
return sr;
}
[OperationContract(Name = "GetUser2")]
[WebGet(UriTemplate = "GetUser2/{userID}", ResponseFormat = WebMessageFormat.Json)]
public ServiceResponse GetUser2(String userID)
{
User2 theUser = new User2()
{
UserID = Convert.ToInt32(userID),
UserName = "bob"
};
ServiceResponse sr = new ServiceResponse()
{
IsError = false,
ResponseMessage = "",
ResponseData = theUser
};
return sr;
}
}
What I did:
That's pretty much it. Using the ServiceKnownType attributes is kind of ugly - there are some solutions out there to get around it (here).
Let me know if you have additional questions. Hope this helps!
Upvotes: 2