icon Web API
Created by Orckestra

Example 1: CRUD using JavaScript

How to use Web API to perform CRUD operations with JavaScript on a static data type

In the following example, we'll create a static data type ("Product") and build a Web API that will serve as a web point for CRUD operations on this type. Then we'll create a C1 Razor function that will perform these CRUD operations via AJAX+JSON requests.

Creating a Visual Studio project

  1. Make sure you've installed the Composite.AspNet.WebAPI package.
  2. Create a Class Library project in Visual Studio naming it, for example, "WebApiDemo".
  3. Add references to Composite.dll, Microsoft.Practices.EnterpriseLibrary.Validation.dll and System.Web.Http.dll on your website (/Bin)

Creating a static data type

  1. Add an interface called "Product".
  2. Replace the default content of the generated code with this code:
    using Composite.Core.WebClient.Renderings.Data;
    using Composite.Data;
    using Composite.Data.Hierarchy;
    using Composite.Data.Hierarchy.DataAncestorProviders;
    using Composite.Data.Validation.Validators;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
    using System;
    
    namespace WebApiDemo
    {
        [AutoUpdateble]
        [DataScope("public")]
        [RelevantToUserType("Developer")]
        [DataAncestorProvider(typeof(NoAncestorDataAncestorProvider))]
        [ImmutableTypeId("e46dcbcf-2da7-4267-8fae-2624328e3d63")]
        [KeyTemplatedXhtmlRenderer(XhtmlRenderingType.Embedable, "<span>{label}</span>")]
        [KeyPropertyName("Id")]
        [Title("Product")]
        [LabelPropertyName("Title")]
        public interface Product : IData
        {
            [ImmutableFieldId("ed5f44c3-cb4a-4c5e-b76c-f952c991d79b")]
            [DefaultFieldNewGuidValue]
            [StoreFieldType(PhysicalStoreFieldType.Guid)]
            [NotNullValidator]
            [FieldPosition(-1)]
            Guid Id { get; set; }
    
            [ImmutableFieldId("fb0daafa-80f6-48d5-801c-7f712fc4d079")]
            [StoreFieldType(PhysicalStoreFieldType.String, 64)]
            [NotNullValidator]
            [FieldPosition(0)]
            [StringSizeValidator(0, 64)]
            [DefaultFieldStringValue("")]
            [TreeOrdering(1)]
            string Title { get; set; }
    
            [ImmutableFieldId("2d412b4d-f2bd-483e-bb74-8ca0631c7d3a")]
            [StoreFieldType(PhysicalStoreFieldType.Integer)]
            [FieldPosition(1)]
            [IntegerRangeValidator(-2147483648, 2147483647)]
            [DefaultFieldIntValue(0)]
            int Price { get; set; }
        }
    }

    Download the sample code

  3. Use EnsureCreateStore on the application startup to ensure that the data type has been created:
    using Composite.Core.Application;
    using Composite.Data.DynamicTypes;
    
    namespace WebApiDemo
    {
        [ApplicationStartup]
        internal static class StartupHandler
        {
            public static void OnBeforeInitialize()
            {
            }
    
            public static void OnInitialized()
            {
                DynamicTypeManager.EnsureCreateStore(typeof (Product));
            }
        }
    }
    
    Download the sample code

Creating a Web API

  1. Add a "controller" class that inherits from ApiController and implement the Web API.
  2. Replace the default content of the generated code with this code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Web.Http;
    using Composite.Data;
    
    namespace WebApiDemo
    {
        public class ProductController : ApiController
        {
            // Getting the list of products
            public IEnumerable<Product> Get()
            {
                using (var c = new DataConnection())
                {
                    return c.Get<Product>().OrderBy(p => p.Title).ToList();
                }
            }
    
            // Getting a product by id
            public Product Get(Guid id)
            {
                using (var c = new DataConnection())
                {
                    return c.Get<Product>().FirstOrDefault(p => p.Id == id);
                }
            }
    
            // Adding a new product
            public Product PostProduct(Product product)
            {
                using (var c = new DataConnection())
                {
                    product.Id = Guid.NewGuid();
    
                    return c.Add(product);
                }
            }
    
            // Updating an existing Product
            public void PutProduct(Guid id, Product productJson)
            {
                using (var c = new DataConnection())
                {
                    var product = c.Get<Product>().FirstOrDefault(p => p.Id == id);
                    if (product == null)
                    {
                        throw new HttpResponseException(HttpStatusCode.NotFound);
                    }
    
                    product.Title = productJson.Title;
                    product.Price = productJson.Price;
    
                    c.Update(product);
                }
            }
    
            // Deleting a new product
            public void DeleteProduct(Guid id)
            {
                using (var c = new DataConnection())
                {
                    var product = c.Get<Product>().FirstOrDefault(p => p.Id == id);
    
                    if (product != null)
                    {
                        c.Delete(product);
                    }
                }
            }
        }
    }
    
    Download the sample code

Adding the WebApiDemo to the website

  1. Build the project.
  2. Copy WebApiDemo.dll from \WebApiDemo\bin\Release (or \WebApiDemo\bin\Debug) to ~/Bin on your website.

Creating a C1 Razor function for CRUD operations

  1. Log in to the C1 Console.
  2. In the Functions perspective, add a new Razor function called "WebApiCrudExample".
  3. Replace the generated code with this code:
    @using WebApiDemo
    @inherits RazorFunction
    
    @functions {
        public override string FunctionDescription
        {
            get  { return "A demo function that outputs a hello message."; }
        }
    }
    
    @{
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://www.composite.net/ns/function/1.0">
        <head>
            <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.12.0/jquery.validate.min.js"></script>
            <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
    
            <script type="text/javascript">
    // <!--
                function LoadJson(url)
                {
                    $.getJSON(url, function (data) {
                        $("#jsonResult")[0].textContent = JSON.stringify(data, null, 2);
                    });
                }
    
                function AddProduct() {
                    if (!$("#title").valid() || !$("#price").valid()) {
                        return;
                    }
    
                    var product = {
                        Title: $("#title")[0].value,
                        Price: parseInt($("#price")[0].value)
                    };
    
                    $.ajax({
                        url: '/api/product/',
                        type: 'POST',
                        data: JSON.stringify(product),
                        contentType: "application/json;charset=utf-8",
                        success: function (data) {
                            alert('Product added Successfully');
    
                            UpdateProductList();
                        },
                        error: function (message) {
                            alert('Product not Added: ' + JSON.stringify(message));
                        }
                    });
    
                    return false;
                }
    
                function OpenForEditing(productId) {
    
                    $.getJSON('/api/product/' + productId, function (data) {
    
                        $("#edit_id")[0].value = data.Id;
                        $("#edit_title")[0].value = data.Title;
                        $("#edit_price")[0].value = data.Price;
    
                        $("#editProductForm").show();
    
                        $("#editProductForm")[0].scrollIntoView();
                    });
                }
    
                function EditProduct() {
                    if (!$("#edit_title").valid() || !$("#edit_price").valid()) {
                        return;
                    }
    
                    var product = {
                        Id: $("#edit_id")[0].value,
                        Title: $("#edit_title")[0].value,
                        Price: $("#edit_price")[0].value
                    };
    
                    $.ajax({
                        type: "PUT",
                        url: '/api/product/' + product.Id,
                        data: JSON.stringify(product),
                        contentType: "application/json; charset=utf-8",
                        dataType: "json",
                        processData: true,
                        success: function (data, status, jqXHR) {
                            
                            UpdateProductList();
                            $("#editProductForm").hide();
    
                        },
                        error: function (xhr) {
                            alert(xhr.responseText);
                        }
                    });
                }
    
                function RemoveProduct(productId) {
                    $.ajax({
                        type: "DELETE",
                        url: "/api/product/" + productId,
                        contentType: "json",
                        dataType: "json",
                        success: function (data) {
                            document.getElementById(productId).remove();
                        },
                        error: function (xhr) {
                            alert(xhr.responseText);
                        }
                    });
                }
    
                $.template("productRowTemplate", "<tr id='${Id}'><td> ${Title} </td> <td> ${Price} </td>"
                    + " <td> <a href='javascript:return false;' onclick=\"OpenForEditing('${Id}')\"> Edit </a></td>"
                    + " <td> <a href='javascript:return false;' onclick=\"RemoveProduct('${Id}')\"> Remove </a></td></tr>");
    
                function UpdateProductList() {
                    $.getJSON("/api/product", function (data) {
                        $("#productRows")[0].innerHTML = "";
                        $.tmpl("productRowTemplate", data).appendTo("#productRows");
                    });
                }
    
                $(function()
                {
                    $('#addProductForm').validate();
    
                    UpdateProductList();
                });
                //-->
            </script>
            <style type="text/css">
                .queryLink {
                    display: inline-block; 
                    background-color: lightblue; 
                    padding: 10px 20px;
                }
    
                #productRows tr {
                    border-bottom: 2px solid black;
                }
    
                #productRows td,
                .productList thead td {
                    padding: 10px;
                }
            </style>
        </head>
        <body>
            
            <h1>Add a product</h1>
            <form id="addProductForm" method="POST" action="#" role="form">
                <div class="form-group">
                    <label for="title">Title</label>
                    <input type="text" class="required" name="title" id="title" />
                </div>
    
                <div class="form-group">
                    <label for="title">Price</label>
                    <input type="text" class="number required" name="price" id="price" />
                </div>
                
                <a class="btn btn-default" href="javascript: return false;" onclick="AddProduct()"> Add </a>
            </form>
            
            <h2>List of products</h2>
            
            <table class="productList">
                <thead>
                    <tr>
                        <td>Title</td>
                        <td>Price</td>
                        <td></td>
                    </tr>
                </thead>
                <tbody id="productRows">
                    
                </tbody>
            </table>
    
            <div id="editProductForm" style="display: none">
    
                <h1>Edit product form</h1>
                <form id="editProductForm" method="POST" action="#" role="form">
                    <input type="hidden" id="edit_id" />
    
                    <div class="form-group">
                        <label for="title">Title</label>
                        <input type="text" class="required" name="title" id="edit_title" />
                    </div>
    
                    <div class="form-group">
                        <label for="title">Price</label>
                        <input type="text" class="number required" name="price" id="edit_price" />
                    </div>
    
                    <a class="btn btn-default" href="javascript: return false;" onclick="EditProduct()"> Edit </a>
                </form>
    
            </div>
            
            <h1>JSON result example</h1>
            <a href="javascript:return false;" onclick="LoadJson('/api/product')" class="queryLink">
                Get Products JSON
            </a>
    
            <pre id="jsonResult" style="padding: 10px; max-width: 700px; border: 2px solid black">
            </pre>
        </body>
    </html>
    Download the sample code
  4. Edit or create a page.
  5. Insert this function on the page.
  6. Save and publish the page.

Testing the demo

Now you can perform CRUD operations with the "Products" data type on the page.

  1. Open the page where you inserted the "WebApiCrudExample" function.
  2. Do one of the following:
    • Add a product.
    • Edit or remove a product.
    • View the list of products.
    • Get the product data in JSON format.
Back to top