JQuery

SharePoint Rich Content Editor with CKEditor Widgets

0

In this article, we build a CKEditor widget representing a SharePoint document link. This introduces a SharePoint Rich Content Editor alternative, which provides features to build a variety custom widgets. At the same time, we demonstrate the ability to leverage SharePoint data and the 2013 REST API.

The following image displays a standard CKEditor control, which includes a toolbar containing various features to deliver rich content without requiring the author to understand HTML or CSS.

The first step is create the CKEditor widget, which is the JavaScript plugin.js located in the widget folder. 

 Javascript |  copy code |? 
01
CKEDITOR.plugins.add('documentlinkwidget', {
02
    requires: 'widget',
03
    icons: 'documentlinkwidget',
04
    init: function(editor) {
05
       editor.widgets.add('documentlinkwidget', {
06
           button: 'Add document link',
07
           template:
08
               '<div class="documentlinkwidget" title="">' +
09
               '<a href="" class="doclinkwidget" style="width: 200px;"></a>' +
10
               '</div>',
11
           requiredContent: 'div(documentlinkwidget); a(doclinkwidget)',
12

In the init, we add the widget to the CKEditor. The template defines the widget markup structure. The requiredContent represents the mandatory widget content, which is a div and a element.

 Javascript |  copy code |? 
01
            init: function() {
02
                var width = this.element.getStyle('width');
03
                if (width)
04
                    this.setData('width', width);
05
                else
06
                    this.setData('width', '200px'); //default
07
 
08
                var id = this.element.getAttribute('title');
09
                if (id)
10
                    this.setData('docid', id);
11
            },
12

Next, add an init function to set the data. The width value is retrieved from the div element style attribute. If the style does exist then width is set to “200px” as the default. The id is retrieved from the title attribute, which is the docid value.

 Javascript |  copy code |? 
1
           data: function() {
2
                var width = this.data.width;
3
                if (width == '')
4
                    this.element.removeStyle('width');
5
                else
6
                    this.element.setStyle('width', width);
7

In the data function above, we build the widget markup. The div element style attribute is set to the appropriate width value. Next, we will retrieve the SharePoint document information using a REST API call.

 Javascript |  copy code |? 
01
               var spQuery = {
02
                    element: '',
03
                    url: '',
04
                    init: function(element) {
05
                        spQuery.element = element;
06
                        spQuery.url = _spPageContextInfo.webAbsoluteUrl + "/_api/lists/getByTitle('" + encodeURIComponent(spQuery.element.data.sourcelistname) + "')/items(" + spQuery.element.data.docid + ")/File?$select=Title,Name,Exists,Length,Level,ServerRelativeUrl";
07
                    },
08
                    load: function() {
09
                        $.ajax(
10
                            {
11
                                url: spQuery.url,
12
                                method: "GET",
13
                                headers: { "accept": "application/json;odata=verbose" },
14
                                success: spQuery.onSuccess,
15
                                error: spQuery.onError
16
                            }
17
                        );
18
                    },
19
                    onSuccess: function(data) {
20
                        spQuery.element.element.setAttribute('title', spQuery.element.data.docid);
21
 
22
                        var link = spQuery.element.element.findOne('a');
23
                        if (link) {
24
                            link.setText(data.d.Title || data.d.Name); //title is not required so set to name if missing
25
                            link.setAttribute('href', data.d.ServerRelativeUrl);
26
                            link.setAttribute('class', 'doclinkwidget');
27
 }
28
                    },
29
                   onError: function(err) {
30
                        api.openMsgDialog('', JSON.stringify(err));
31
                    }
32
                };
33
 
34
                //get data if docid is set
35
                if (this.data.docid) {
36
                    spQuery.init(this);
37
                    spQuery.load();
38
                }
39
            }
40

SPQuery contains our initialize and JQuery logic, so we can retrieve the SharePoint document file information to build the widget markup. The init sets the SPQuery.element and SPQuery.url values, which will be used in the load function. The SPQuery.onSuccess and SPQuery.onError are the callbacks to handle the logic based on the response. The link.setText will set the value to Title or Name from the JSON result. The ServerRelativeUrl  result value is the href attribute. You can retrieve the icon and file size, which can also be included in the markup.

The final section will conditionally make the SPQuery call when a docid value is present. This is accomplished with SPQuery.init(this) and SPQuery.load() calls.

We also add logic to support a widget configuration dialog, which  allows the user to select a document and set the width. The following is the additional plugin.js code required to define a dialog.

 Javascript |  copy code |? 
1
init: function(editor) {
2
        CKEDITOR.dialog.add('documentlinkwidget', this.path + 'dialogs/documentlinkwidget.js');
3
 
4

We will cover the CKEditor widget dialog in the next post. The following is the complete widget plugin.js.

 Javascript |  copy code |? 
01
CKEDITOR.plugins.add('documentlinkwidget', {
02
    requires: 'widget',
03
 
04
    icons: 'documentlinkwidget',
05
 
06
    init: function(editor) {
07
        CKEDITOR.dialog.add('documentlinkwidget', this.path + 'dialogs/documentlinkwidget.js');
08
 
09
        editor.widgets.add('documentlinkwidget', {
10
            button: 'Add document link',
11
 
12
            template:
13
                '<div class="documentlinkwidget" title="">' +
14
                '<a href="" class="doclinkwidget" style="width: 200px;"></a>' +
15
                '</div>',
16
 
17
            allowedContent:
18
                'div(!documentlinkwidget); a(!doclinkwidget)',
19
 
20
            requiredContent: 'div(documentlinkwidget); a(doclinkwidget)',
21
 
22
            dialog: 'documentlinkwidget',
23
 
24
            upcast: function(element) {
25
                return element.name == 'div' && element.hasClass('documentlinkwidget');
26
            },
27
 
28
            init: function() {
29
                var width = this.element.getStyle('width');
30
 
31
                if (width)
32
                    this.setData('width', width);
33
                else
34
                    this.setData('width', '200px'); //default
35
 
36
                var id = this.element.getAttribute('title');
37
                if (id)
38
                    this.setData('docid', id);
39
            },
40
 
41
            data: function() {
42
                var width = this.data.width;
43
 
44
                if (width == '')
45
                    this.element.removeStyle('width');
46
                else
47
                    this.element.setStyle('width', width);
48
 
49
                var SPQuery = {
50
                    element: '',
51
                    url: '',
52
                    init: function(element) {
53
                        SPQuery.element = element;
54
                        SPQuery.url = _spPageContextInfo.webAbsoluteUrl + "/_api/lists/getByTitle('" + encodeURIComponent(SPQuery.element.data.sourcelistname) + "')/items(" + SPQuery.element.data.docid + ")/File?$select=Title,Name,Exists,Length,Level,ServerRelativeUrl";
55
                    },
56
                    load: function() {
57
                        $.ajax(
58
                            {
59
                                url: SPQuery.url,
60
                                method: "GET",
61
                                headers: { "accept": "application/json;odata=verbose" },
62
                                success: SPQuery.onSuccess,
63
                                error: SPQuery.onError
64
                            }
65
                        );
66
                    },
67
                    onSuccess: function(data) {
68
                        SPQuery.element.element.setAttribute('title', SPQuery.element.data.docid);
69
                        var link = SPQuery.element.element.findOne('a');
70
                        if (link) {
71
                            link.setText(data.d.Title || data.d.Name); //title is not required so set to name if missing
72
                            link.setAttribute('href', data.d.ServerRelativeUrl);
73
                            link.setAttribute('class','doclinkwidget');
74
                        }
75
                    },
76
                   onError: function(err) {
77
                        api.openMsgDialog('', JSON.stringify(err));
78
                    }
79
                };
80
 
81
                //get data if docid is set
82
                if (this.data.docid) {
83
                    SPQuery.init(this);
84
                    SPQuery.load();
85
                }
86
            }
87
        });
88
    }
89
});
90
 
91

ASP.NET MVC and Kendo UI Grid

0

A grid provides a common presentation to represent a collection of data, which is a table containing rows and columns. Although creating this experience is not difficult, the features to deliver a quality user experience will require a significant investment. The alternative is a widget library, which provides advanced features requiring minimal effort.

In this post, I will demonstrate a few features of the Kendo UI Grid, which is one of many widgets included in the Kendo UI products. After several years of experience with Telerik products, the next generation Kendo UI is HTML5 and CSS3. I also elected to include the Kendo UI Complete, which packages convenient server extensions for the JavaScript framework. You can learn more about the products and better understand the licensing, which is a huge obstacle for many budget conscious organization. And yes…many alternatives exist including the JQuery.UI library.

Kendo UI provides a handy Visual Studio plugin, which can convert and prepare projects for Kendo UI. I converted an existing ASP.NET MVC4 project, which saves several manual steps. I was also able to select one of the Kendo themes, which will be applied to all Kendo widgets.

You can read several of my previous posts, which discuss design patterns to build enterprise applications. In this article, my goal is to provide a quick start for the Kendo UI Grid implementation. So…I will not create a fully functioning repository, but instead a static memory based to provide the basics for the demonstration.

I will modify the standard ASP.NET MVC4 starter project and add a new menu option called Contacts. This will require a controller, view model and service - all the basics. We’ll start with a simple read-only grid, which will display the current contacts with paging, filtering and sorting features. The following is the read-only Contacts grid.

Contacts Read-Only Grid

The grid is a table containing the Name, Mode of Contact, Phone and Email columns. The sort, filter and paging features are enabled, so the user can interact with the grid and data using several helpful options. So…let’s look at the view containing the grid configuration.

 C# |  copy code |? 
01
@using MvcKendoUIGrid.Models
02
 
03
@(Html.Kendo().Grid<Contact>()
04
      .Name("contactGrid")
05
      .Columns(columns =>
06
 
07
          {
08
               columns.Bound(c => c.Name).Title("Name").Width(150);
09
              columns.Bound(c => c.PreferredContactMode).Title("Mode of Contact").Width(150);
10
              columns.Bound(c => c.Phone).Title("Phone").Width(120);
11
              columns.Bound(c => c.Email).Title("Email").Width(120);
12
          })
13
      .Pageable()
14
      .Filterable()
15
      .Sortable()
16
      .Scrollable()
17
      .AutoBind(true)
18
      .HtmlAttributes(new {style = "height:250px;"})
19
      .DataSource(dataSource => dataSource
20
                                    .Ajax()
21
                                    .ServerOperation(false)
22
                                    .Model(model =>
23
                                        {
24
                                            model.Id(c => c.Id);
25
                                            model.Field(c => c.PreferredContactMode).Editable(true).DefaultValue(new ContactMode {Id = 0, Name = string.Empty});
26
                                        })
27
                                    .Read(read => read.Action("Read", "Contact"))
28
)      )

The Pageable, Sortable, Filterable and Scrollable provide the advanced grid features with just one line of code. The DataSource defines the data and actions to read. The model is the Contact, so the fields and id are defined. The Read action is an ajax call to the Contact controller and Read method, which will return a collection of Contact objects. The Columns define the layout of columns, headers and binding to the model.

The Contact model contains the Id, NamePhone and Email properties. It also includes the ContactMode, which is a complex object including an Id and Name. We’ll see more on the complex object in the next section.

 C# |  copy code |? 
01
using System.Collections.Generic;
02
using System.Web.Mvc;
03
using Kendo.Mvc.Extensions;
04
using Kendo.Mvc.UI;
05
using MvcKendoUIGrid.Models;
06
using MvcKendoUIGrid.Services;
07
 
08
namespace MvcKendoUIGrid.Controllers
09
{
10
    /// <summary>
11
    /// Contact controller providing support for views
12
    /// </summary>
13
    public class ContactController : Controller
14
    {
15
        private readonly IContactService _service;
16
 
17
        /// <summary>
18
        /// Default Constructor
19
        /// </summary>
20
        public ContactController()
21
        {
22
            _service = new ContactService();
23
        }
24
 
25
        /// <summary>
26
        /// Default action to render Contact grid
27
        /// </summary>
28
        /// <returns></returns>
29
        public ActionResult Index()
30
        {
31
            TempData["ContactMode"] = new List<ContactMode>
32
                {
33
                    new ContactMode {Id = 1, Name = "Phone"},
34
                    new ContactMode {Id = 2, Name = "Email"}
35
                };
36
 
37
            return View();
38
        }
39
 
40
        /// <summary>
41
        ///     Read action to populate grid
42
        /// </summary>
43
        /// <param name="dsRequest">Kendo Datasource Request</param>
44
        /// <returns>ActionResult</returns>
45
        [HttpPost]
46
        public ActionResult Read([DataSourceRequest] DataSourceRequest dsRequest)
47
        {
48
            try
49
            {
50
                return Json(_service.GetAllContacts().ToDataSourceResult(dsRequest));
51
            }
52
            catch
53
            {
54
                ModelState.AddModelError("Contacts", "Unable to load contacts.");
55
                return Json(ModelState.ToDataSourceResult());
56
            }
57
        }
58

The Index action is called on the initially, which will save the possible ContactMode selections as TempData. The Read action invokes the service GetAllContacts method to return a collection of Contacts.

The next step is providing the ability to edit the contacts. The following is the revised view, which includes the changes to enable editing.

 C# |  copy code |? 
01
@using MvcKendoUIGrid.Models
02
 
03
@(Html.Kendo().Grid<Contact>()
04
      .Name("contactGrid")
05
      .Columns(columns =>
06
 
07
          {
08
              columns.Command(command =>
09
                  {
10
                      command.Edit();
11
                   }).Width(180);
12
              columns.Bound(c => c.Name).Title("Name").Width(150);
13
              columns.Bound(c => c.PreferredContactMode).Title("Mode of Contact").Width(150);
14
              columns.Bound(c => c.Phone).Title("Phone").Width(120);
15
              columns.Bound(c => c.Email).Title("Email").Width(120);
16
          })
17
      .Pageable()
18
      .Filterable()
19
      .Sortable()
20
      .Scrollable()
21
      .AutoBind(true)
22
      .HtmlAttributes(new {style = "height:250px;"})
23
      .Editable(ed => ed.Mode(GridEditMode.InLine))
24
      .DataSource(dataSource => dataSource
25
                                    .Ajax()
26
                                    .ServerOperation(false)
27
                                    .Model(model =>
28
                                        {
29
                                            model.Id(c => c.Id);
30
                                            model.Field(c => c.PreferredContactMode).Editable(true).DefaultValue(new ContactMode {Id = 0, Name = string.Empty});
31
                                        })
32
                                    .Read(read => read.Action("Read", "Contact"))
33
                                    .Update(update => update.Action("Edit", "Contact"))
34
      )
35
      )

The DataSource now includes the Update, which calls the Contact controller Edit method. The Editable supports inline and popup edit modes, so we will select inline to allow editing within the grid. We also add a column command, which injects the edit button in the first column. We also add the Edit method to the controller, which is responsible for calling the service to update the contract.

 C# |  copy code |? 
01
        /// <summary>
02
        /// Edit action to update existing contact
03
        /// </summary>
04
        /// <param name="dsRequest">Kendo Datasource Request</param>
05
        /// <param name="viewmodel">Contact model containing values to update</param>
06
        /// <returns>ActionResult</returns>
07
        [HttpPost]
08
        public ActionResult Edit([DataSourceRequest] DataSourceRequest dsRequest, Contact viewmodel)
09
        {
10
            try
11
            {
12
                if (ModelState.IsValid && viewmodel != null)
13
                    _service.Update(viewmodel);
14
                else //model error
15
                    ModelState.AddModelError("Contacts", "Unable to edit contact - not a valid contact.");
16
            }
17
            catch
18
            {
19
                ModelState.AddModelError("Contacts", "Unable to edit contact.");
20
            }
21
 
22
            return Json(ModelState.ToDataSourceResult());
23
        }
24

If we test the changes then we see the addition of the edit button. Clicking the edit button will allow the editing of the selected row.

Contact Grid Edit

You will notice the Mode of Contact column displays the Id and Name textbox, which is not the best experience for selecting the contact mode.

Contact Grid Edit Complex Object

Since ContactMode is a complex object, the editor includes the Id and Name. We would like to provide a dropdown list of available contact modes, so the user must select a valid option. We previously saved a collection of ContactMode objects representing the valid options in the TempData, so this will be the dropdown list source. The solution is creating a new editor for the ContactMode type, so when the correct editor is presented. The following is the ContactMode editor, which should be added to the Shared Editor Templates folder.

 C# |  copy code |? 
1
@model MvcKendoUIGrid.Models.ContactMode
2
@(Html.Kendo().DropDownList()
3
      .Name("PreferredContactMode")
4
      .BindTo((System.Collections.IEnumerable)TempData["ContactMode"])
5
      .OptionLabel("Select a Mode")
6
      .DataTextField("Name")
7
      .DataValueField("Id")
8
      .HtmlAttributes(new { required = true })
9
      )

We are using the Kendo UI DropDownList widget, which is a dropdown list. The BindTo is the list data source, which is referencing the TempData we populated in our initial Index method. The DataTextField and DataValueField are the value and text property names. We also set the required attribute, which ensures the contact mode is required. It is important to note the Name must be the name of the grid model property, so the two-way binding is correct. Let’s see the results of the changes to the edit mode.

Contacts Grid Edit Dropdown

The final features are Add and Delete. The following is the view containing the updates for Add and Delete. You will also notice the ClientTemplate applied to the ContactMode, which forces the view to include the Name property in the display.

 C# |  copy code |? 
01
@using MvcKendoUIGrid.Models
02
 
03
@(Html.Kendo().Grid<Contact>()
04
      .Name("contactGrid")
05
      .Columns(columns =>
06
 
07
          {
08
              columns.Command(command =>
09
                  {
10
                      command.Edit();
11
                      command.Destroy();
12
                  }).Width(180);
13
              columns.Bound(c => c.Name).Title("Name").Width(150);
14
              columns.Bound(c => c.PreferredContactMode).Title("Mode of Contact").ClientTemplate("#=PreferredContactMode.Name#").Width(150);
15
              columns.Bound(c => c.Phone).Title("Phone").Width(120);
16
              columns.Bound(c => c.Email).Title("Email").Width(120);
17
          })
18
      .ToolBar(toolbar => toolbar.Create().Text("Add new contact"))
19
      .Pageable()
20
      .Filterable()
21
      .Sortable()
22
      .Scrollable()
23
      .AutoBind(true)
24
      .HtmlAttributes(new {style = "height:250px;"})
25
      .Editable(ed => ed.Mode(GridEditMode.InLine))
26
      .DataSource(dataSource => dataSource
27
                                    .Ajax()
28
                                    .ServerOperation(false)
29
                                    .Model(model =>
30
                                        {
31
                                            model.Id(c => c.Id);
32
                                            model.Field(c => c.PreferredContactMode).Editable(true).DefaultValue(new ContactMode {Id = 0, Name = string.Empty});
33
                                        })
34
                                    .Read(read => read.Action("Read", "Contact"))
35
                                    .Update(update => update.Action("Edit", "Contact"))
36
                                    .Destroy(delete => delete.Action("Delete", "Contact"))
37
                                    .Create(create => create.Action("Create", "Contact"))
38
      )
39
      )

We add the Destroy to the command, which provides the Delete button. The DataSource Destroy defines the Contact controller delete action, which will be responsible for deleting the contact. We add the create command to the Toolbar, which is positioned above the grid. The DataSource Create is the action invoked when the “Add new contact” button is clicked.

The Create and Delete controller methods appear below.

 C# |  copy code |? 
01
        /// <summary>
02
        /// Create action to add new contact
03
        /// </summary>
04
        /// <param name="dsRequest">Kendo Datasource Request</param>
05
        /// <param name="viewmodel">Contact model containing values to add</param>
06
        /// <returns>ActionResult</returns>
07
        [HttpPost]
08
        public ActionResult Create([DataSourceRequest] DataSourceRequest dsRequest, Contact viewmodel)
09
        {
10
            try
11
            {
12
                if (ModelState.IsValid && viewmodel != null)
13
                {
14
                    _service.Add(viewmodel);
15
                    return Json(new[] {viewmodel}.ToDataSourceResult(dsRequest, ModelState));
16
                }
17
                ModelState.AddModelError("Contacts", "Unable to add contact - not a valid contact.");
18
            }
19
            catch
20
            {
21
                ModelState.AddModelError("Contacts", "Unable to add contact.");
22
            }
23
 
24
            return Json(ModelState.ToDataSourceResult());
25
        }
26
 
27
        /// <summary>
28
        /// Delete action to remove existing contact
29
        /// </summary>
30
        /// <param name="dsRequest">Kendo Datasource Request</param>
31
        /// <param name="viewmodel">Contact model containing values to delete</param>
32
        /// <returns>ActionResult</returns>
33
        [HttpPost]
34
        public ActionResult Delete([DataSourceRequest] DataSourceRequest dsRequest, Contact viewmodel)
35
        {
36
            try
37
            {
38
                if (viewmodel != null)
39
                    _service.Delete(viewmodel);
40
                else
41
                    ModelState.AddModelError("Contacts", "Unable to delete contact - not a valid contact.");
42
            }
43
            catch
44
            {
45
                ModelState.AddModelError("Contacts", "Unable to delete contact.");
46
            }
47
 
48
            return Json(ModelState.ToDataSourceResult());
49
        }
50

The final version with the Edit, Add and Delete actions enabled.

Contacts Grid Complete

Contacts Grid AddContacts Grid Delete

I hope this provides a quick overview of the Kendo UI Grid widget and Kendo UI MVC server extensions, which together provide powerful features with minimal effort.

ASP.NET and JQuery Ajax

1

After my recent series of design pattern articles, this post will introduce an alternative ASP.NET Ajax implementation using JQuery. The result is lightweight with a smaller payload than ASP.NET Ajax. In this example, we will setup a simple web page with an Ajax call to display the current date and time. This is not an exciting demonstration, but the objective is providing the basics for a more complex implementation and evidence the data is changing for each request.

First, create a page method using the WebMethod attribute to return the current date/time as a string. The Ajax client will define the data type within the request, which our example will be JSON.

1
        [WebMethod(EnableSession = false)]
2
        public static string GetDateString()
3
        {
4
            return string.Format("{0}-{1}-{2} {3}",
5
                                 DateTime.Now.Month.ToString(),
6
                                 DateTime.Now.Day.ToString(),
7
                                 DateTime.Now.Year.ToString(),
8
                                 DateTime.Now.ToLongTimeString());
9
        }

Alternatively, you could elect to return markup and inject into the current page. In this scenario, you are performing the formatting server-side. You could also apply style on the client-side.

The Default.aspx page contains a button with the click event to trigger the Ajax call to the page method. The following is the Default.aspx body fragment with the btnCurrentDateString button and divDate elements.

1
<body>
2
  <button id="btnCurrentDateString">Get Date As String</button>
3
  <div id="divDate"></div>

We replace the ASP.NET Ajax with JQuery Ajax script, which will define the click event of the btnCurrentDateString button. We will bind the results to a div element, which is handled by the JQuery success option. As discussed previously, we set the dataType option to “json” as the data type.

01
  
02
      $('#btnCurrentDateString').click(function () {
03
          $.ajax({
04
              type: "POST",
05
              url: "Default.aspx/GetDateString",
06
              data: "{}",
07
              contentType: "application/json",
08
              dataType: "json",
09
              success: function (msg) {
10
                  $("#divDate").text('String: ' + msg.d);
11
              }
12
          });
13
      });

When you launch the page and click the button, the current date and time is displayed on the page. The IE9 browser Developer tools capture the network traffic, so you can see the response from the Ajax call.

What if you need to return a more complex object? So…let’s create the DataInfo object as a container for our properties including month, day, year and time.

01
    public class DateInfo
02
    {
03
        public DateInfo(int month,
04
                        int day,
05
                        int year)
06
        {
07
            this.Month = month;
08
            this.Day = day;
09
            this.Year = year;
10
        }
11
 
12
        public int Month { get; set; }
13
        public int Day { get; set; }
14
        public int Year { get; set; }
15
        public string Time 
16
        { 
17
            get { return DateTime.Now.ToLongTimeString(); } 
18
        }
19
    }

We will add a new page method to handle this request, which will return the DataInfo object using JSON. There is no additional processing required, since the WebMethod attribute instructs the page to handle the details.

1
        [WebMethod(EnableSession = false)]
2
        public static DateInfo GetDateObject()
3
        {
4
            return new DateInfo(DateTime.Now.Month,
5
                         DateTime.Now.Day,
6
                         DateTime.Now.Year);
7
        }

We will also add a new button to call the GetDateObject page method. The HTML fragment appears below.

1
<body>
2
  <button id="btnCurrentDateObject" >Get Date As Object</button>
3
  <div id="divDate"></div>

The following is the JQuery script to make the call and bind the response to the divDate element. The script can access the individual fields by name, so it is very easy to bind the values to one or more page elements.

01
  
02
      $('#btnCurrentDateObject').click(function () {
03
          $.ajax({
04
              type: "POST",
05
              url: "Default.aspx/GetDateObject",
06
              data: "{}",
07
              contentType: "application/json",
08
              dataType: "json",
09
              success: function (msg) {
10
                  $("#divDate").text('Object: ' + msg.d.Month + '-' + msg.d.Day + '-' + msg.d.Year + ' ' + msg.d.Time);
11
              }
12
          });
13
      });

Again the response is displayed using browser tools, so you can view the raw data format.  In this example, you can see the DataInfo fields are defined with the associated value. The serialize/deserialize process is handled for you, so no additional client or server code is necessary to manage a more complex object.

As you can see, JQuery provides a very simple and clean Ajax implementation to consume a service. I hope you find this information helpful as an alternative to ASP.NET Ajax.

Source Code

Go to Top