Showing posts with label Ajax. Show all posts
Showing posts with label Ajax. Show all posts

Thursday, January 26, 2017

SharePoint Custom WCF Service with Automatic Formatting



Recently I was writing a custom SharePoint WCF service for using in client side JavaScript libraries (jquery, angular) and C# server side call HttpWebRequest without worrying adding references and proxy classes. Majority of the articles I referred to were only showing JSON output; I wanted this service to provide both JSON and Xml data formats. If the requirement is to output both JSON and Xml formats, I found people writing two method calls:one for each JSON  and Xml. Also, I have seen articles where response was driven through method or query string parameter to get requirement format (WebMessageFormat.Xml, WebMessageFormat.Json) If I follow the former approach as shown below, the amount of code will grow twice the code that I actually need which is very inefficient and demand more maintenance. 

[ServiceContract]
interface IPersonService

    {
         [WebGet(UriTemplate = "person/{id}",  ResponseFormat = WebMessageFormat.Json)]
          Person GetPersonJSON(int id); //get JSON output

         [WebGet(UriTemplate = "person/{id}",  ResponseFormat = WebMessageFormat.Xml)]
          Person GetPersonXml(int id);  //get Xml output
    }

All I wanted was automatic formating based on some configuration or flag set through code. While searching for options. I found this technet article. helpful.
WCF Web HTTP Automatic and Explicit  Formatting options
https://msdn.microsoft.com/en-us/library/ee476510(v=vs.110).aspx

(snippet from technet)

Automatic Formatting

The WCF Web HTTP programming model allows you to dynamically determine the best format for a service operation to return its response in. Two methods for determining an appropriate format are supported: automatic and explicit.
When enabled, automatic formatting chooses the best format in which to return the response. It determines the best format by checking the following, in order:
  1. The media types in the request message’s Accept header.
  2. The content-type of the request message.
  3. The default format setting in the operation.
  4. The default format setting in the WebHttpBehavior
(/snippet from technet)

Solution:
  1. Added web.config file to my custom wcf custom service. 
  2. C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\isapi\<MyCustomWCFService>
  3. Added System.ServiceModel section as show below.
         <configuration>
     <system.serviceModel>
      <behaviors>  
        <endpointBehaviors>        

          <behavior>          

            <webHttp automaticFormatSelectionEnabled="true" />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      </system.serviceModel>
    </configuration>

     
Have only service contract method.


[ServiceContract]
interface IPersonService
    {
         [WebGet(UriTemplate = "person/{id}")]
          Person GetPerson(int id);
   }

Now I can the call same method through jquery/ajax by specifying the ContentType or Accept Header and get the output format that I need. 

JavaScript - JSON Output 


function getPerson() {
            var serviceUri = _spPageContextInfo.webAbsoluteUrl" + "/_vti_bin/<MyCustomService>/PersonService.svc/person/" + id;
            $.ajax({
                type: "GET",
                contentType: "application/json",
                url: serviceUri,
                dataType: "json"
            }).done(function (data) {
                //do something here
            }).fail(function (error) {
            });

        }

JavaScript - Xml Output

function getPerson() {
            var serviceUri = _spPageContextInfo.webAbsoluteUrl" + "/_vti_bin/<MyCustomService>/PersonService.svc/person/" + id;
            $.ajax({
                type: "GET",
                contentType: "application/xml",
                url: serviceUri,
                dataType: "xml"
            }).done(function (data) {
                //do something here
            }).fail(function (error) {
            });

        }

Server Side C# - HttpWebRequest - JSON Output


HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/json;odata=verbose";



Server Side C# - HttpWebRequest - Xml Output


HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/xml;odata=verbose";

Tuesday, October 8, 2013

Charting is easy with JqPlot, LINQ, ASP.NET, C#


This post shows a simple approach to render charts using JQPlot javascript plugin in an ASP.NET page. I have created sample data here but in actual case you could get it from database or a SharePoint list or any other data source. I am using Page.ClientScript.RegisterClientScriptBlock approach to inject the JSON object through client script block and later using JQuery document ready event to read the JSON object. The other approach could be making an Ajax call to the server side method [WebMethod] and directly fetch the data. It's up to the requirement.

Download the JQPlot here. It's free.
Assuming we already have an ASPX page in ASP.NET web application. 


Code-behind (cs)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 using System.Web.Script; 8 using System.Web.Script.Serialization; 9 10 public partial class jqplots : System.Web.UI.Page 11 { 12 protected void Page_Load(object sender, EventArgs e) 13 { 14 if (!Page.IsPostBack) 15 { 16 //collect the data 17 List<Issue> listIssues = new List<Issue>(); 18 listIssues.Add(new Issue() { Title = "Page loads very slow", Priority = "Medium" }); 19 listIssues.Add(new Issue() { Title = "Page validation error", Priority = "High" }); 20 listIssues.Add(new Issue() { Title = "Date format showing 12:00:00 AM", Priority = "Low" }); 21 listIssues.Add(new Issue() { Title = "Table borders", Priority = "Low" }); 22 listIssues.Add(new Issue() { Title = "Some values not saving", Priority = "Low" }); 23 24 //LINQ Group by 25 var ipCounts = from i in listIssues 26 group i by i.Priority into g 27 select new { Category = g.Key, Value = g.Count() }; 28 29 //Anonymous type 30 var ip = new { issuePriority = ipCounts.ToList() }; 31 32 string issuePriorityTotals = "var issueTotals = " + new JavaScriptSerializer().Serialize(ip) + ";"; 33 34 //render javascript block to access the object from JQuery document ready function 35 Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "IP", issuePriorityTotals, true); 36 } 37 } 38 39 [Serializable] 40 public class Issue 41 { 42 public string Title { get; set; } 43 public string Priority { get; set; } 44 } 45 }

Page ViewSource (don't copy this)
If you check the browser view source after the page loads, you should see the script block like the one below. The JSON object issueTotals is the key here. You will have to read the object and construct an array and then use it JqPlot chart method. See the JavaScript code in HTML source in the next section. 

1 <script type="text/javascript">
2 //<![CDATA[
3 var issueTotals = {"issuePriority":[{"Category":"Medium","Value":1},{"Category":"High","Value":1},{"Category":"Low","Value":3}]};//]]>
4 </script>

HTML Source (aspx)


     
  • Print
  •  
  • About BlogTrog Code Window
 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="jqplots.aspx.cs" Inherits="jqplots" %>
 2 
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4 
 5 <html xmlns="http://www.w3.org/1999/xhtml">
 6 <head runat="server">
 7     <title>JQPlot Demo</title>
 8     <script src="Scripts/common/jquery.min.js" type="text/javascript"></script>
 9     <script src="Scripts/jqplot/jquery.jqplot.min.js" type="text/javascript"></script>
10     <script src="Scripts/jqplot/jqplot.canvasTextRenderer.min.js" type="text/javascript"></script>
11     <script src="Scripts/jqplot/jqplot.canvasAxisTickRenderer.min.js" type="text/javascript"></script>
12     <script src="Scripts/jqplot/jqplot.categoryAxisRenderer.min.js" type="text/javascript"></script>
13     <script src="Scripts/jqplot/jqplot.pointLabels.min.js" type="text/javascript"></script>
14     <script src="Scripts/jqplot/jqplot.barRenderer.min.js" type="text/javascript"></script>
15     <script src="Scripts/jqplot/jqplot.pieRenderer.min.js" type="text/javascript"></script>
16     <link href="Scripts/jqplot/jquery.jqplot.min.css" rel="stylesheet" type="text/css" />
17 
18 
19     <script type="text/javascript">
20         $(document).ready(function () {
21             var data = [];            
22             if (issueTotals) {
23                 if (typeof issueTotals.issuePriority != "undefined") {
24                     var obj = issueTotals.issuePriority;
25                     for (var i = 0; i < obj.length; i++) {
26                         data.push([obj[i].Category, obj[i].Value]);
27                     }
28                 }
29             }
30 
31             $('#chart1').jqplot([data], {
32                 title: 'Issue Priority Totals - Bar chart',
33                 // Provide a custom seriesColors array to override the default colors.
34                 seriesColors: ['#85802b', '#00749F', '#73C774', '#C7754C', '#17BDB8'],
35                 seriesDefaults: {
36                     renderer: $.jqplot.BarRenderer,
37                     rendererOptions: {
38                         // Set varyBarColor to true to use the custom colors on the bars.
39                         varyBarColor: true,
40                         barWidth: 60,
41                         barMargin: 5
42                     }
43                 },
44                 axesDefaults: {
45                     tickOptions: { formatString: '%d' }
46                 },
47                 axes: {
48                     xaxis: {
49                         renderer: $.jqplot.CategoryAxisRenderer
50                     }
51                 }
52             });
53 
54             $.jqplot('chart2', [data], {
55                 grid: {
56                     drawBorder: true,
57                     drawGridlines: false,
58                     background: '#ffffff',
59                     shadow: false
60                 },
61                 title: 'Issue Priority Totals - Pie chart',
62                 axesDefaults: {
63 
64             },
65             seriesDefaults: {
66                 renderer: $.jqplot.PieRenderer,
67                 rendererOptions: {
68                     showDataLabels: true
69                 }
70             },
71             legend: {
72                 show: true,
73                 rendererOptions: {
74                     numberRows: 2
75                 },
76                 location: 's'
77             }
78         });
79 
80         });
81     </script>  
82     
83 </head>
84 <body>
85     <form id="form1" runat="server">
86     <div>
87         <div id="chart1" style="margin-top:20px; margin-left:20px; width:400px; height:400px; float:left; margin-right:10px;"></div>
88         <div id="chart2" style="margin-top:20px; margin-left:20px; width:400px; height:400px; float:left"></div>        
89     </div>   
90     </form>
91 </body>
92 </html>




Output




References