December 2017 : Online courses in ASP.NET MVC and Angular 4. Conducted by Bipin Joshi. Read more...
Registration for December 2017 batches of ASP.NET MVC / Core and Angular 4 online courses have already started. Conducted by Bipin Joshi. Book your seat today ! Click here for more details.

Use XML Data Format In ASP.NET Web API

Modern web applications use JSON as the preferred data format for the sake of transferring data between a Web API and its client. However, at times you may want to use XML data format instead of JSON. Although the overall process to accomplish this task is same, there are certain subtle but important differences. To that end this article shows how XML data exchange can be done between an ASP.NET Web API and a jQuery driven client.

As an example let's assume that you wish to perform CRUD operations on the Employees table of the Northwind database. These operations are wrapped by a Web API - EmployeeManager. The EmployeeManager Web API is then invoked from the browser using jQuery code. The web page that allows the end user to perform the CRUD operations look like this:

Creating DbContext and Employee entity class

To begin developing this example, create a new ASP.NET MVC application based on the Empty project template. Then add Models, Views and Controllers as usual. Then add the Northwind DbContext class and the Employee entity class using the Entity Data Model wizard. This wizard is run when you add a new Entity Data Model into the Models folder.

Make sure to pick Code First from database open while running the wizard. At the end of this process you get two classes - Northwind.cs and Employee.cs. These classes are shown below:

public partial class Northwind : DbContext
{
    public Northwind()
        : base("name=Northwind")
    {
    }

    public virtual DbSet<Employee> Employees { get; set; }
}
public partial class Employee
{
    public int EmployeeID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string HomePhone { get; set; }
    public string Notes { get; set; }
}

Notice that the Employee class contains only five properties namely EmployeeID, FirstName, LastName, HomePhone and Notes whereas the Employees database table contains many more columns. We do this just for the sake of simplicity.

Creating the Web API controller

Then add a Web API 2 empty controller to the Controllers folder. Name the Controller as EmployeeManagerController. This controller will have five actions to perform the CRUD operations. These actions are shown below:

[HttpGet]
    public List<Employee> SelectAll()
    {
        using (Northwind db = new Northwind())
        {
            var query = from e in db.Employees
                        orderby e.EmployeeID ascending
                        select e;
            return query.ToList();
        }
    }

    [HttpGet]
    public Employee SelectByID(int id)
    {
        using (Northwind db = new Northwind())
        {
            return db.Employees.Find(id);
        }
    }

    [HttpPost]
    public string Insert(Employee obj)
    {
        using (Northwind db = new Northwind())
        {
            Employee emp = new Employee();
            emp.FirstName = obj.FirstName;
            emp.LastName = obj.LastName;
            emp.HomePhone = obj.HomePhone;
            emp.Notes = obj.Notes;
            db.Employees.Add(emp);
            db.SaveChanges();
            return "Employee added successfully!";
        }
    }

    [HttpPut]
    public string Update(int id, Employee obj)
    {
        using (Northwind db = new Northwind())
        {
            Employee emp = db.Employees.Find(id);
            emp.FirstName = obj.FirstName;
            emp.LastName = obj.LastName;
            emp.HomePhone = obj.HomePhone;
            emp.Notes = obj.Notes;
            db.SaveChanges();
            return "Employee modified successfully!";
        }
    }

    [HttpDelete]
    public string Delete(int id)
    {
        using (Northwind db = new Northwind())
        {
            Employee emp = db.Employees.Find(id);
            db.Employees.Remove(emp);
            db.SaveChanges();
            return "Employee deleted successfully!";
        }
    }
}

The SelectAll(), SelectByID(), Insert(), Update(), and Delete() actions are quite straightforward and hence we won't go into much details of their working.

The Index view markup

Then add HomeController to the Controller and also the Index view. The Index view will house the jQuery code that calls the EmployeeManager Web API you just created. The HTML markup of the Index view is shown below:

<h1>Employee Manager</h1>

<table cellpadding="11" border="1">

    <tr>
        <td>Employee ID :</td>
        <td>
            <select id="employeeid"></select>
        </td>
    </tr>

    <tr>
        <td>First Name :</td>
        <td>
            <input type="text" id="firstname" />
        </td>
    </tr>

    <tr>
        <td>Last Name :</td>
        <td>
            <input type="text" id="lastname" />
        </td>
    </tr>

    <tr>
        <td>Home Phone :</td>
        <td>
            <input type="text" id="homephone" />
        </td>
    </tr>

    <tr>
        <td>Notes :</td>
        <td>
            <textarea rows="4" cols="40" id="notes"></textarea>
        </td>
    </tr>

    <tr>
        <td colspan="2">
            <input type="button" value="Insert" id="insert" />
            <input type="button" value="Update" id="update" />
            <input type="button" value="Delete" id="delete" />
        </td>
    </tr>
</table>
<br />
<div id="msg"></div>

Add Scripts folder under the project root and place jQuery library in it (you can also use a CDN if you so wish). Open Index.cshtml and add a script reference to the jQuery library.

Invoking SelectAll() and SelectByID() Web API actions

Now it's time to add jQuery code that calls the Web API. Shown below is the calling of the SelectAll() action.

$(document).ready(function () {
    var settings = {};
    settings.url = "/api/EmployeeManager";
    settings.type = "GET";
    settings.contentType = "application/xml";
    settings.dataType = "xml";
    settings.success = function (employees) {
        $(employees).find("Employee")
         .each(function () {
            var empId = $(this).find
                        ("EmployeeID").text();
            $("#employeeid").append("<option>" 
             + empId + "</option>");
        });
    };
    settings.error = function () {
        $("#msg").append("Error while 
                  calling the Web API !!!");
    };
    $.ajax(settings);
}

The dataType is set to xml. This indicates that the response data from the Web API is going to be in XML format.

The success function receives XML data from the server. A sample data received in this method is shown below :

The jQuery find() method is then used to iterate through all the Employee nodes. For every Employee found, its EmployeeID is extracted using find() and text() methods. The EmployeeID is then added to the dropdown list.

On the same lines you can invoke SelectByID() action of the Web API :

$("#employeeid").change(function () {
    var settings = {};
    settings.url = "/api/EmployeeManager/" 
+ $("#employeeid").val();
    settings.type = "GET";
    settings.contentType = "application/xml";
    settings.dataType = "xml";
    settings.success = function (employee) {
        var firstName = $(employee)
.find("FirstName").text();
        var lastName = $(employee)
.find("LastName").text();
        var homePhone = $(employee)
.find("HomePhone").text();
        var notes = $(employee)
.find("Notes").text();
        $("#firstname").val(firstName);
        $("#lastname").val(lastName);
        $("#homephone").val(homePhone);
        $("#notes").val(notes);

    };
    settings.error = function () {
        $("#msg").append("Error while calling the Web API !!!");
    };
    $.ajax(settings);
});

Note a couple of differences. Firstly, the url also includes the EmployeeID whose details are to be fetched. Secondly, the success function extracts all the other elements - FirstName, LastName, HomePhone, and Notes.

Invoking Update() Web API action

So far so good. Now its time to deal with POST, PUT and DELETE. The PUT call is discussed below :

$("#update").click(function () {

    var settings = {};
    settings.url = "/api/EmployeeManager/" 
+ $("#employeeid").val();
    settings.type = "PUT";
    settings.contentType = "application/xml";
    settings.dataType = "xml";

    var empId = $("#employeeid").val();
    var firstName = $("#firstname").val();
    var lastName = $("#lastname").val();
    var homePhone = $("#homephone").val();
    var notes = $("#notes").val();

    settings.data = "<Employee 
xmlns='http://schemas.datacontract.org/2004/07/
XMLWebApi.Models' 
xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
<EmployeeID>" + empId + "</EmployeeID><FirstName>" + 
firstName + "</FirstName><HomePhone>" + homePhone + 
"</HomePhone><LastName>" + lastName + 
"</LastName><Notes>" + notes + "</Notes></Employee>";

    settings.success = function (msg) {
        $("#msg").html($(msg).text());
    };
    settings.error = function () {
        $("#msg").append("Error while calling the Web API !!!");
    };
    $.ajax(settings);
});

Observe the code marked in bold letters. This time the type is PUT. The contentType is application/xml because we will be sending data to be inserted in XML format.

See how the data property is set to an XML fragment representing an Employee to be modified. How did we get the structure of this XML markup? Fire up the browser and invoke /api/EmployeeManager/1.

If you switch to the Page Source you will get this :

The structure of this XML is important and must match with the one shown above. Ensure that your xmlns attribute includes correct namespace name (XMLWebApi.Models in above example). The success message returned by the Web API is displayed in the msg <div> element.

Invoking Insert() Web API action

On the same lines you can complete POST and DELETE calls. The POST call is given below for your reference:

$("#insert").click(function () {
    var settings = {};
    settings.url = "/api/EmployeeManager";
    settings.type = "POST";
    settings.contentType = "application/xml";
    settings.dataType = "xml";

    var firstName = $("#firstname").val();
    var lastName = $("#lastname").val();
    var homePhone = $("#homephone").val();
    var notes = $("#notes").val();

    settings.data = "<Employee 
xmlns='http://schemas.datacontract.org/
2004/07/XMLWebApi.Models' 
xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
<FirstName>" + firstName + "</FirstName><HomePhone>" + 
homePhone + "</HomePhone><LastName>" + lastName + 
"</LastName><Notes>" + notes + "</Notes></Employee>";

    settings.success = function (msg) {
        $("#msg").html($(msg).text());
    };

    settings.error = function () {
        $("#msg").append("Error while 
calling the Web API !!!");
    };

    $.ajax(settings);

});

Invoking Delete() Web API action

$("#delete").click(function () {
    var settings = {};
    settings.url = "/api/EmployeeManager/" 
+ $("#employeeid").val();
    settings.type = "DELETE";
    settings.contentType = "application/xml";
    settings.dataType = "xml";

    settings.success = function (msg) {
        $("#msg").html($(msg).text());
    };
    settings.error = function () {
        $("#msg").append("Error while 
calling the Web API !!!");
    };
    $.ajax(settings);
});

Using XmlSerializer instead of DataContractSerializer

By default ASP.NET Web API uses DataContractSerializer to serialize XML data. That's why those XML namespaces become necessary in your markup. You can skip that if you configure Web API serialization to use XmlSerializer. To do this, open WebApiConfig.cs and add the following line:

config.Formatters.XmlFormatter.UseXmlSerializer = true;

Now, your XML data can omit the namespaces as shown below:

...
settings.data = "<Employee>
<EmployeeID>" + empId + "</EmployeeID><FirstName>" + 
firstName + "</FirstName><HomePhone>" + homePhone + 
"</HomePhone><LastName>" + lastName + 
"</LastName><Notes>" + notes + "</Notes></Employee>";
...

Using XML data with HttpClient component

In the above example we used jQuery to deal with the XML. What if you are invoking the Web API through some server side code using HttpClient component? In this case also the process remains the same. You will be using methods of HttpClient such as GetAsync(), PostAsync(), PutAsync() and DeleteAsync(). Wherever you need to pass XML data to the Web API you will use StringContent to wrap the XML being transferred. An example follows:

...
string xmlEmp = $"<Employee xmlns='http://schemas.datacontract.org
/2004/07/EmployeeWebAPIService.Models' 
xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
<EmployeeID>{comboBox1.SelectedItem}</EmployeeID>
<FirstName>{textBox1.Text}</FirstName>
<HomePhone>{textBox3.Text}</HomePhone>
<LastName>{textBox2.Text}</LastName>
<Notes>{textBox4.Text}</Notes></Employee>";

HttpContent content = new StringContent(xmlEmp, 
Encoding.UTF8, "application/xml");
HttpResponseMessage response = client.PutAsync
("/api/EmployeeManager/" + comboBox1.SelectedItem, 
content).Result;
string xmlMsg = response.Content.ReadAsStringAsync().Result;
...

 

That's it for now ! Keep coding !!


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Meditation and Mindfulness to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 18 September 2017


Tags : ASP.NET ASP.NET Core MVC .NET Framework C# Visual Studio