WCF and JSON format - anyone have a good solution?

WCF and JSON format - anyone have a good solution?

FredButtersFredButters Posts: 3Questions: 0Answers: 0
edited September 2012 in General
I've seen this example (http://datatables.net/forums/discussion/828/x) but I'm trying to use $.ajax() to get my JSON, then use that object in my dataTables() jQuery ie I'm not using any client side code behind. I can get this to work if I use the sample JSON found on this site, so I've narrowed the problem down to the JSON returned from the service

I'm trying to use a WCF service with AspNetCompatibilityRequirementsMode.Allowed, but the JSON format returned from the service isn't working with the DataTables plugin. I've tried

- Returning a custom Object and relying on the WCF service to handle converting it to JSON via the JavaScript proxy built by the service
- Using JavaScriptSerializer and converting a List to JSON within my service implementation
- Creating a string array using StringBuilder and a for loop

All of these solutions feel like a hack, but more importantly they're just not working.
- When returning a custom object the JSON includes the name/value ex [code][ { "FullName" : "Jim Smith", "Address" : "123 Main St." } ][/code]
- The JavaScriptSerializer returned JSON but all the quotes were escaped ex [code]\"FullName\" : \"Jim Smith\"...[/code]
- The StringBuilder was just a hassle to get working but once I got something that looked like JSON I realized it was just a big string... not really JSON

Is there a good solution for this?



Thanks

[code]
/* The sample JSON works with my jQuery */
"aaData" : [
/* Reduced data set */
[ "Trident", "Internet Explorer 4.0", "Win 95+", 4, "X", "something", "something" ], etc...
[/code]

[code]
function getRewards(event) {
var company = tbCompany.val();
var year = tbYear.val();
$.ajax({
type: "POST",
url: "RewardScriptService.svc/getRewards",
data: '{ "CompanyPRI" : "' + company + '", "PlanYear" : "' + year + '" }',
contentType: "application/json",
success: onSuccess,
error: function (jqXHR, exception) {
alert(exception);
}
});
};
function onSuccess(Rewards) {
$('#tRewards').dataTable({
"aaData" : Rewards.d
});
}
[/code]

Replies

  • FredButtersFredButters Posts: 3Questions: 0Answers: 0
    Nevermind. It looks like this might work for me:

    http://rantdriven.com/post/Using-Datatablesnet-JQuery-Plug-in-with-WCF-Services.aspx
  • FredButtersFredButters Posts: 3Questions: 0Answers: 0
    edited September 2012
    In case anyone is wondering, this is how I implemented DataTables.net with a WCF REST Service. I'm using the code found in a post by KJM (http://datatables.net/forums/discussion/828/keyvalue-json-serialization/p1) rather than the link I have in the post above. However I changed the return type to System.IO.Stream so I can return an actual JSON object (rather than a string of JSON).

    It was a pretty lengthy process to get this working because of the JSON format issue, but it works great now. I wouldn't mind if DataTables.net would work with JSON containing name/value pairs *hint hint* :) but this is working pretty well, doesn't require a ton of extra code and overall this plugin is amazing so I can't complain!

    [code]
    [ServiceContract]
    public interface IMyInterface
    {
    [OperationContract]
    [WebInvoke(
    Method = "GET",
    BodyStyle = WebMessageBodyStyle.Bare,
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    UriTemplate = "getmytable?value1={val1}&value2={val2}")]
    Stream GetMyTable(int val1, int val2);
    }
    [/code]

    [code]
    public class MyService : IMyInterface
    {
    public Stream GetMyTable(int val1, int val2)
    {
    string returnValue = string.Empty;
    try
    {
    List list = new List();
    // populate your List<> object here however you want.
    // list = myController.GetMyTableList(val1, val2)

    var jsonObj = new
    {
    sEcho = 1,
    iTotalRecords = list.Count,
    iTotalDisplayRecords = list.Count,
    aaData = new List()
    };
    foreach (ITableDataSource ds in list)
    {
    jsonObj.aaData.Add(ds.GetTableData());
    }
    JavaScriptSerializer jScriptSerializer = new JavaScriptSerializer();
    returnValue = jScriptSerializer.Serialize(jsonObj);
    }
    catch (Exception ex)
    {
    throw new WebFaultException(HttpStatusCode.ServiceUnavailable);
    }

    //returns a JSON object, rather than a string of JSON
    WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
    MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(returnValue));

    return memoryStream;
    }
    }
    [/code]


    [code]
    public interface ITableDataSource
    {
    IList GetTableData();
    }

    public class MyTableFields : ITableDataSource
    {
    public string FullName { get; set; }
    public string Position { get; set; }
    public int UserID { get; set; }
    public DateTime? DateOfBirth { get; set; }

    public IList GetTableData()
    {
    return new List()
    {
    this.FullName,
    this.Position,
    this.UserID.ToString(),
    this.DateOfBirth.ToShortDateFormat() //extension method
    };
    }
    }
    [/code]

    [code]
    var oTable;

    $(document).ready(function () {
    var val1 = $('#tbMyvalue1').val();
    var val2 = $('#tbMyvalue2').val();
    var url = "http://mysite.com/MyService.svc/getmytable?value1=" + val1 + "&value2=" + val2 + "";

    oTable = $('#example').dataTable({
    "bProcessing": true,
    "sAjaxSource": url
    });
    });
    [/code]
  • allanallan Posts: 63,522Questions: 1Answers: 10,473 Site admin
    Thanks for sharing your code with us :-)

    > I wouldn't mind if DataTables.net would work with JSON containing name/value pairs

    It does. DataTables can work with almost any data feed through the use of the mData and sAjaxDataProp options - see: http://datatables.net/blog/Extended_data_source_options_with_DataTables

    Allan
  • ppttypptty Posts: 2Questions: 0Answers: 0
    I get the data from wcf service:

    {"sEcho":1,"iTotalRecords":5,"iTotalDisplayRecords":5,"aaData":[{"Title":"Task1","Detail":"Do Something 1","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task2","Detail":"Do Something 2","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task3","Detail":"Do Something 3","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task4","Detail":"Do Something 4","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task5","Detail":"Do Something 5","CreatedDate":"\/Date(1365682773875)\/"}]}

    How can I binding to the datatables?

    Thansks!
  • allanallan Posts: 63,522Questions: 1Answers: 10,473 Site admin
    Use the mData option: http://datatables.net/blog/Extended_data_source_options_with_DataTables

    Allan
  • ppttypptty Posts: 2Questions: 0Answers: 0
    Allan, thank you !

    I use the mData, but cannot slove it !

    I slove it by return string and change the webget attribute .

    The WebGet setting:

    [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]


    The method :
    [code]
    public string GetTaskInfoToStr(Task task1,
    int sEcho)
    {


    JavaScriptSerializer serialiser = new JavaScriptSerializer();
    return serialiser.Serialize(new
    {
    sEcho,
    iTotalRecords = 2,
    iTotalDisplayRecords = 2,
    aaData = GetData()
    });

    }

    private static List GetData()
    {
    return new List
    {
    new Task { Title="Task1", Detail="Do Something 1", CreatedDate=DateTime.Now },
    new Task { Title="Task2", Detail="Do Something 2", CreatedDate=DateTime.Now },
    new Task { Title="Task3", Detail="Do Something 3", CreatedDate=DateTime.Now },
    new Task { Title="Task4", Detail="Do Something 4", CreatedDate=DateTime.Now },
    new Task { Title="Task5", Detail="Do Something 5", CreatedDate=DateTime.Now }
    };
    }

    [/code]

    I capture the return data by HttpWatch tool.
    If I want to binding to the datatables, The data format return from wcf must correct! For example:

    The error return data:
    [code]

    jQuery18206780284146947606_1365733052536("{\"sEcho\":0,\"iTotalRecords\":2,\"iTotalDisplayRecords\":2,\"aaData\":[{\"Title\":\"Task1\",\"Detail\":\"Do Something 1\",\"CreatedDate\":\"\\\/Date(1365733052703)\\\/\"},{\"Title\":\"Task2\",\"Detail\":\"Do Something 2\",\"CreatedDate\":\"\\\/Date(1365733052703)\\\/\"},{\"Title\":\"Task3\",\"Detail\":\"Do Something 3\",\"CreatedDate\":\"\\\/Date(1365733052703)\\\/\"},{\"Title\":\"Task4\",\"Detail\":\"Do Something 4\",\"CreatedDate\":\"\\\/Date(1365733052703)\\\/\"},{\"Title\":\"Task5\",\"Detail\":\"Do Something 5\",\"CreatedDate\":\"\\\/Date(1365733052703)\\\/\"}]}");

    [/code]



    The correct return data:
    [code]

    {"sEcho":1,"iTotalRecords":5,"iTotalDisplayRecords":5,"aaData":[{"Title":"Task1","Detail":"Do Something 1","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task2","Detail":"Do Something 2","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task3","Detail":"Do Something 3","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task4","Detail":"Do Something 4","CreatedDate":"\/Date(1365682773875)\/"},{"Title":"Task5","Detail":"Do Something 5","CreatedDate":"\/Date(1365682773875)\/"}]}

    [/code]
  • allanallan Posts: 63,522Questions: 1Answers: 10,473 Site admin
    Your 'error' example is JSONP, not plain JSON.

    Allan
This discussion has been closed.