0

I have a Restful WCF method that is returning 2 object(2 different class) base on condition inside the method.

This is my method:

public Model.BaseType returnPayment_Gateway()
{
    IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
    WebHeaderCollection headers = request.Headers;

    Model.Payment_Gateway payment_Gateway=null;
    if (headers["ServiceAuthentication"] != null)
    {
     string   ServiceAuthentication = headers["ServiceAuthentication"].ToString();
      bool  serviceAuth = Service_Authentication(ServiceAuthentication);

      DAL.DataManager dal = new DAL.DataManager();

        if (serviceAuth == true)
        {
            payment_Gateway = dal.Get_Payment_Gateway();
        }
    }
    else
    {
            // Create a new response to return
          return new Model.ReturnResponse() { StatusCode = 201, StatusDescription = "Authentication Fails" };
    }

     return payment_Gateway;
}

This is my base class that contains both of objects:

[Serializable]
[DataContract]
[KnownType(typeof(Payment_Gateway))]
[KnownType(typeof(ReturnResponse))]

public class BaseType 
{

}

this is one of the derived classes:

[DataContract]
public class Payment_Gateway:BaseType
{
    [DataMember]
    public string Gateway { get; set; }

and this is another drived class:

[DataContract]
public class ReturnResponse:BaseType
{
    [DataMember]
    public int StatusCode { get; set; }

    [DataMember]
    public string StatusDescription { get; set; }

This is in my .SVC how I call this method:

public   Model.BaseType Payment_Gateway()
{
   return GetCustomerInfo.Instance.returnPayment_Gateway();
}

and this is my service interface:

[WebInvoke(Method = "GET",
                            ResponseFormat = WebMessageFormat.Json,
                            BodyStyle = WebMessageBodyStyle.Bare,
                           UriTemplate = "Payment_Gateway")]
Model.BaseType Payment_Gateway();

My question:

The Json response that I am getting has 1 extra line that I am not sure where it comes from and how to remove it. this line:

 "__type": "Payment_Gateway:#CustomerPortal.Model",

This is complete response I am getting in Soap UI.

 {
  "__type": "Payment_Gateway:#CustomerPortal.Model",
"Gateway": "[\r\n        {\"Payment_Gateway_ID\":\"40\",\"Payment_Gateway_Name\":\"Speedpay\",\"Payment_Gateway_URL\":\"https:\\/\\/paynow7.speedpay.com\\/CarFinance\\/index.asp\",\"Payment_Gateway_Description\":\"Speedpay is a Third-party bill payment vendor that provides CarFinance.com's customers the convenience and flexibility of making electronic payments, along with the security and peace-of-mind that comes from retaining total control over your bills. Western Union Speedpay charges a convenience fee of $10. CarFinance.com does not receive any portion of the convenience fee. The fee, which is in addition to your car payment, is paid directly to Western Union Speedpay for providing this service to our customers.\"},\r\n    {\"Payment_Gateway_ID\":\"41\",\"Payment_Gateway_Name\":\"Western Union - Quick Collect\",\"Payment_Gateway_URL\":\"https:\\/\\/www.westernunion.com\\/us\\/en\\/home.html\",\"Payment_Gateway_Description\":\"Western Union Quick Collect service is a fast and convenient way to deliver funds -- especially on a due date! Within minutes of your completed payment transaction, Quick Collect delivers an electronic fund transfer notification to CarFinance.com. Western Union charges a $10 service fee that typically is less expensive than the cost of overnight delivery. Please note: This Western Union service will accept cash only.\"},\r\n    {\"Payment_Gateway_ID\":\"42\",\"Payment_Gateway_Name\":\"MoneyGram\",\"Payment_Gateway_URL\":\"http:\\/\\/moneygram.com\\/us\\/en\",\"Payment_Gateway_Description\":\"MoneyGram Bill Payments Services is set up to allow consumers make payments to CarFinance.com. MoneyGram charges a fee of $9.99 for this service. CarFinance.com does not receive any portion of the convenience fee. The fee, which is in addition to your car payment, is paid directly to MoneyGram for providing this service to our customers. Bill Payment Services also enable consumers to load and reload prepaid debit cards. To find an agent near you or pay online, go to \"},\r\n    {\"Payment_Gateway_ID\":\"43\",\"Payment_Gateway_Name\":\"Mail your payment\",\"Payment_Gateway_URL\":\"\",\"Payment_Gateway_Description\":\"Payments are processed and posted to accounts Monday through Friday (excluding holidays). Please allow 10 days for mailing if you're mailing your payment.\\r\\n\\r\\nCarFinance\\r\\nPO Box 660057\\r\\nDallas, TX 75266-0057\"}\r\n]"

}

Alma
  • 3,780
  • 11
  • 42
  • 78
  • JSON doesn't really have "lines". It looks like there's an extra property to indicate which type was actually returned. Why is that a problem? Any code that doesn't understand it should ignore it. – John Saunders Jan 10 '15 at 01:38

1 Answers1

1

When DataContractJsonSerializer serializes a polymorphic type, it adds a __type field to indicate the type being serialized. From the docs:

As stated earlier, polymorphism is supported in JSON with some limitations. JavaScript is a weakly-typed language and type identity is normally not an issue. However, when using JSON to communicate between a strongly-typed system (.NET) and a weakly-typed system (JavaScript), it is useful to preserve type identity. For example, types with data contract names "Square" and "Circle" derive from a type with a data contract name of "Shape". If "Circle" is sent from .NET to JavaScript and is later returned to a .NET method that expects "Shape", it is useful for the .NET side to know that the object in question was originally a "Circle" - otherwise any information specific to the derived type (for example, "radius" data member on "Circle") may be lost.

To preserve type identity, when serializing complex types to JSON a "type hint" can be added, and the deserializer recognizes the hint and acts appropriately. The "type hint" is a JSON key/value pair with the key name of "__type" (two underscores followed by the word "type"). The value is a JSON string of the form "DataContractName:DataContractNamespace" (anything up to the first colon is the name). Using the earlier example, "Circle" can be serialized as follows.

{"__type":"Circle:http://example.com/myNamespace","x":50,"y":70,"radius":10}

The type hint is very similar to the xsi:type attribute defined by the XML Schema Instance standard and used when serializing/deserializing XML.

In your case, your BaseType can be either a Payment_Gateway or a ReturnResponse, so this information is added.

Update

In .Net 4.5 and above, output of type information with DataContractJsonSerializer can be suppressed by setting DataContractJsonSerializerSettings.EmitTypeInformation to EmitTypeInformation.Never:

var settings = new DataContractJsonSerializerSettings { EmitTypeInformation = EmitTypeInformation.Never };
var serializer = new DataContractJsonSerializer(typeof(BaseType), settings); // No type hints will be emitted.

Once you have your serializer, you can use the following helper methods to generate JSON strings:

public static class DataContractJsonSerializerHelper
{
    private static MemoryStream GenerateStreamFromString(string value)
    {
        return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
    }

    public static string GetJson<T>(T obj, DataContractJsonSerializer serializer)
    {
        using (var memory = new MemoryStream())
        {
            serializer.WriteObject(memory, obj);
            memory.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(memory))
            {
                return reader.ReadToEnd();
            }
        }
    }

    public static string GetJson<T>(T obj) where T : class
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
        return GetJson(obj, serializer);
    }
}

And then call it like

var json = DataContractJsonSerializerHelper.GetJson(obj, serializer);

Alternatively, if you switch to Json.NET, its JsonSerializerSettings.TypeNameHandling setting allows you to suppress output of its type information.

Community
  • 1
  • 1
dbc
  • 104,963
  • 20
  • 228
  • 340
  • 1
    I removed the "(v=vs.100)" from your link to make it independent of .NET Framework version. – John Saunders Jan 10 '15 at 01:48
  • @dbc Thanks for your response, where I have to add this code? – Alma Jan 12 '15 at 19:24
  • @nikoom - I added sample code for serializing a class into a JSON string. Is that what you need? – dbc Jan 12 '15 at 20:30
  • @dbc thanks for your reply, what I have in this line payment_Gateway = dal.Get_Payment_Gateway(); payment_Gateway is already json as I am returnign jason from database query. Do I still need the class above? for thsi reason I dont have idea where I put the 2 lines that you mentioned before. – Alma Jan 12 '15 at 21:15
  • @nikoom - `returnPayment_Gateway()` returns a `Model.BaseType` not a JSON string. I don't know how your code is structured; where do you serialize that to JSON? – dbc Jan 12 '15 at 21:23
  • @dbc you are right, it returns Model.BaseType, all the related code I have is at the top(I actually made changes so , I am not serializing any where I thought this line in service Interface take care of it! ResponseFormat = WebMessageFormat.Json – Alma Jan 12 '15 at 21:27
  • I edited my question so you can see what I am getting in response in soap UI. – Alma Jan 12 '15 at 21:32
  • @nikoom - I'm familiar with JSON but not putting together WCF REST services so I don't know where you would configure these settings. You might want to ask another question titled "How can I make DataContractJsonSerializerHelper use EmitTypeInformation = EmitTypeInformation.Never in a WCF Rest service"? – dbc Jan 12 '15 at 21:37
  • @nikoom - possibly add a [custom formatter](http://wcf.codeplex.com/discussions/255870) that invokes `DataContractJsonSerializer` with the necessary settings? – dbc Jan 12 '15 at 21:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/68683/discussion-between-nikoo-m-and-dbc). – Alma Jan 12 '15 at 21:40
  • @nikoom - no, sorry. Anyway, while i can tell you how to generate the desired json with `DataContractJsonSerializer`, I don't know the appropriate way to integrate this into your WCF RESTful service. That's why I suggest asking another question. – dbc Jan 12 '15 at 21:44