开发者

Remove internal "__type" tags in ASP.NET Restful WCF

开发者 https://www.devze.com 2023-04-09 11:32 出处:网络
I\'m developing a RESTful WCF, and am currently having trouble getting nice, clean JSON-serialized return values.

I'm developing a RESTful WCF, and am currently having trouble getting nice, clean JSON-serialized return values.

A little while back, I got rid of "Key" and "Value" tags around each of my keys and values (caused by serializing a Dictionary<string, object> object) by using a wrapper.

But when I did that, "__type" tags started showing up. I managed to get rid of the "d" tag, along with the first "__type" tag by replacing WebScriptServiceHostFactory with WebServiceHostFactory in the ServiceHost tag of my svc file.

So my result looks like this:

{"Status":"Success","Data":{"__type":"SerializableDictionaryOfstringanyType:#MyNamespace.MyFolder","Key1":"Value1","Key2":"Value2","Key3":"Value3"}}

But I want it to look like this:

{"Status":"Success","Data":{"Key1":"Value1","Key2":"Value2","Key3":"Value3"}}

My test webservice code looks like this:

[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public SerializableDictionary<string, object> Test1(String Token, String Id)
{
    DataTable testTable = new DataTable();
    testTable.Columns.Add("Key1", typeof(System.String));
    testTable.Columns.Add("Key2", typeof(System.String));
    testTable.Columns.Add("Key3", typeof(System.String));

    DataRow testRow = testTable.NewRow();
    testRow["Key1"] = "Value1";
    testRow["Key2"] = "Value2";
    testRow["Key3"] = "Value3";

    testTable.Rows.Add(testRow);

    return SuccessfulResult(testTable);
}

EDIT: And the SuccessfulResult function looks like this (sorry for forgetting it):

private SerializableDictionary<string, object> SuccessfulResult(DataTable dt = null)
{
    SerializableDictionary<string, object> result = new SerializableDictionary<string, object>();
    result.Add("Status", "Success");

    if (dt == null || dt.Rows.Count != 1)
        return result;

    SerializableDictionary<string, object> dct = new SerializableDictionary<string, object>();
    foreach (DataColumn currCol in dt.Rows[0].Table.Columns)
        dct.Add(currCol.ColumnName, dt.Rows[0][currCol.ColumnName].ToStr开发者_如何学Going());

    result.Add("Data", dct);

    return result;
}

If anybody has any ideas on how I might get rid of that last little "__type" tag, I would love to hear them! Thanks very much, and let me know if there's anything else I can post that might be helpful.


Okay, fixed it up - but ended up doing things a little differently. WCF seems to insist on putting in those internal "__type" tags when it serializes Dictionaries, but for some reason, it doesn't do the same thing with Streams.

Here's the new webservice method code (just the return type has changed):

[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public Stream Test1(String Token, String StreamId)
{
    DataTable testTable = new DataTable();
    testTable.Columns.Add("Key1", typeof(System.String));
    testTable.Columns.Add("Key2", typeof(System.String));
    testTable.Columns.Add("Key3", typeof(System.String));

    DataRow testRow = testTable.NewRow();
    testRow["Key1"] = "Value1";
    testRow["Key2"] = "Value2";
    testRow["Key3"] = "Value3";

    testTable.Rows.Add(testRow);

    return SuccessfulResult(testTable);
}

And here's the new SuccessfulResult function (which is what made the difference):

private Stream SuccessfulResult(DataTable dt = null)
{
    Dictionary<string, object> returnDict = new Dictionary<string, object>();
    returnDict.Add("Status", "Success");

    Dictionary<string,object> dct = new Dictionary<string,object>();
    foreach (DataColumn currCol in dt.Rows[0].Table.Columns)
        dct.Add(currCol.ColumnName, dt.Rows[0][currCol.ColumnName].ToString());

    returnDict.Add("Data", dct);

    string sResponse = json.Serialize(returnDict);
    byte[] byResponse = Encoding.UTF8.GetBytes(sResponse);

    return new MemoryStream(byResponse);
}

Now the output looks exactly how I want it to look:

{"Status":"Success","Data":{"Key1":"Value1","Key2":"Value2","Key3":"Value3"}}

Anyway, I hope this example helps somebody else :)


In some case, the browser will treat response stream as binary, so, it will show download file popup. Then you should using:

string result = "Hello world";
byte[] resultBytes = Encoding.UTF8.GetBytes(result);
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return new MemoryStream(resultBytes);


I know that this was a long time ago, but I found a really simple way to make that possible.

In the Web.Config file you should change a line.

Use <webHttp/> instead of <enableWebScript/>

  <endpointBehaviors>
        <behavior>
          <webHttp />
        </behavior>
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号