Search code examples
c#wcfdatacontract

Return different Object (List or error class) from WCF service


I am trying to build a WCF service which has a single method getPersonList which returns list of person like this

[
  {"personId":121, "personName":"John Smith"},
  {"personId":953, "personName":"Maggie Johnson"}
]

If there is some error, I want to return an error response like this from the same method.

{"errorCode":4002,"errorMessage":"invalid request token"}

Now I have my Service Contract as below:

    [ServiceContract()]
    public interface IPersonContract
    {
        [OperationContract()]
        Object GetPersonList(int requestParam);
    }

and my sample GetPersonList method

Object GetPersonList(int requestParam)
{
  if (requestParam == 1)
  {
    ErrorResponse error = new ErrorResponse();
    error.ErrorCode = 4002;
    error.ErrorMessage = "invalid request token";

    return error;
  }else
  {
    List<Person> returnList = new List<Person>();
    // add Person to returnList
    return returnList;
  }

}

Person Class

[DataContract()]
public class Person
{

    [DataMember(Name = "personName")]
    String PersonName{   get;   set;  }

    [DataMember(Name = "personId")]
    String PersonID {   get;   set;  }

}

Error Class

[DataContract()]
public class ErrorResponse
{

    [DataMember(Name = "errorCode")]
    int ErrorCode{   get;   set;  }

    [DataMember(Name = "errorMessage")]
    String ErrorMessage{   get;   set;  }

}

I looked up KnownTypes for DataContract classes but how do I apply that on Object.

If I add fields from ErrorReponse and add List<Person> in a single class and return that object, I get a response like this in success case which is not what I want.

{
"Person":[{"personId":121, "personName":"John Smith"},
      {"personId":953, "personName":"Maggie Johnson"}]
}

Solution

  • change your service contract definition like -

        [OperationContract]
        [WebInvoke(Method = "GET",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "/get/{id}")]
        [ServiceKnownType(typeof(RootObject1))]
        [ServiceKnownType(typeof(RootObject2))]
        object GetOrder(string id);
    

    service implementation -

        public object GetOrder(string id)
        {
            if (id.Length == 1)
            {
                return new RootObject1 { errorCode = 4002, errorMessage = "invalid request token" };
            }
            return new RootObject2 { personId = 121, personName = "John Smith" };
        }
    

    enter image description here

    enter image description here


    Updated on 12/27/2016 for List type

        [OperationContract]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, Method = "GET", UriTemplate = "GetOrdersJSON?ClientID={ClientID}&SenderEmail={SenderEmail}&VersionNumber={VersionNumber}")]
        [ServiceKnownType(typeof(List<MyCustomErrorDetail>))]
        [ServiceKnownType(typeof(List<ShipToDetails>))]
        object GetOrdersJSON(int ClientID, string SenderEmail, string VersionNumber);
    
    
    [DataContract]
    public class MyCustomErrorDetail
    {
        public MyCustomErrorDetail(string errorInfo, string errorDetails)
        {
            ErrorInfo = errorInfo;
            ErrorDetails = errorDetails;
        }
    
        [DataMember]
        public string ErrorInfo { get; private set; }
    
        [DataMember]
        public string ErrorDetails { get; private set; }
    }
    

    Return the below object from GetOrdersJSON when there are no records or when any other error occurs depending on your need!

                    MyCustomErrorDetail myCustomErrorObject = new MyCustomErrorDetail("There are no records available", string.Format("There are no records available for user {0}", fstr_UserName));
                    List<MyCustomErrorDetail> myCustomErrorList = new List<MyCustomErrorDetail>();
                    myCustomErrorList.Add(myCustomErrorObject);
                    return myCustomErrorList;