Tuesday, July 26, 2016

Provider-Hosted Add-in CRUD example using CSOM

Below is a complete CRUD example of provider-hosted SharePoint Add-In using CSOM. In the controller, the CRUD is performed on a SharePoint list, "Products", which is made of [ID], [Title], [UnitPrice] and [UnitsOnStock] fields.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.SharePoint.Client;
using ProviderHostedCloud1Web.Models;

namespace ProviderHostedCloud1Web.Controllers
{
    [SharePointContextFilter]
    public class ProductController : Controller
    {

        // GET: Product
        public ActionResult Index()
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
            using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
            {
                if (cc != null)
                {
                    List productList = cc.Web.Lists.GetByTitle("Products");
                    cc.Load(productList);
                    cc.ExecuteQuery();

                    if (productList != null)
                    {
                        CamlQuery query = CamlQuery.CreateAllItemsQuery();
                        ListItemCollection products = productList.GetItems(query);
                        cc.Load(products);
                        cc.ExecuteQuery();

                        List retVal = new List();
                        foreach (var product in products)
                        {
                            retVal.Add(new Product
                            {
                                ID = product.Id,
                                Title = product["Title"].ToString(),
                                UnitPrice = Convert.ToDecimal(product["UnitPrice"]),
                                UnitsOnStock = Convert.ToInt32(product["UnitsOnStock"])
                            });
                        }
                        return View(retVal);
                    }

                    return View();
                }
                else
                {
                    ViewBag.ErrorMessage = "Error: ClientContext is null.";
                    return View();
                }
            }

        }

        // GET: Product/Details/5
        public ActionResult Details(int id)
        {
            try
            {
                var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
                using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
                {
                    if (cc != null)
                    {
                        ListItem item = cc.Web.Lists.GetByTitle("Products").GetItemById(id);
                        cc.Load(item);
                        cc.ExecuteQuery();

                        if (item != null)
                        {
                            Product retVal = new Product
                            {
                                ID = item.Id,
                                Title = item["Title"].ToString(),
                                UnitPrice = item["UnitPrice"] == null ? 0.00m : Convert.ToDecimal(item["UnitPrice"]),
                                UnitsOnStock = item["UnitsOnStock"] == null ? 0 : Convert.ToInt32(item["UnitsOnStock"])
                            };

                            return View(retVal);
                        }
                        else
                        {
                            return View();
                        }
                    }
                    else
                    {
                        ViewBag.ErrorMessage = "Error: ClientContext was null. ";
                        return View();
                    }
                }
            }
            catch (Exception ex)
            {
                Exception ie = ex;
                while (ie.InnerException != null)
                {
                    ie = ie.InnerException;
                }
                ViewBag.ErrorMessage = "Error: " + ie.Message;
                return View();
            }
        }

        // GET: Product/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Product/Create
        [HttpPost]
        public ActionResult Create(System.Web.Mvc.FormCollection collection)
        {
            string title = collection["Title"].ToString();
            decimal unitPrice = collection["UnitPrice"] == null ? 0.00m : Convert.ToDecimal(collection["UnitPrice"]);
            int unitsOnStock = collection["UnitsOnStock"] == null ? 0 : Convert.ToInt32(collection["UnitsOnStock"]);

            try
            {
                var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
                using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
                {
                    List productList = cc.Web.Lists.GetByTitle("Products");
                    ListItemCreationInformation creationInfo = new ListItemCreationInformation();
                    ListItem item = productList.AddItem(creationInfo);
                    item["Title"] = title;
                    item["UnitPrice"] = unitPrice;
                    item["UnitsOnStock"] = unitsOnStock;
                    item.Update();
                    cc.ExecuteQuery();

                    return RedirectToAction("Index", new { SPHostUrl = Request.QueryString["SPHostUrl"] });
                }
            }
            catch (Exception ex)
            {
                Exception ie = ex;
                while (ie.InnerException != null)
                {
                    ie = ie.InnerException;
                }
                ViewBag.ErrorMessage = "Error: " + ie.Message;
                Product product = new Product { Title = title, UnitPrice = unitPrice, UnitsOnStock = unitsOnStock };
                return View(product);
            }
        }

        // GET: Product/Edit/5
        public ActionResult Edit(int id)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
            using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
            {
                if (cc != null)
                {
                    ListItem item = cc.Web.Lists.GetByTitle("Products").GetItemById(id);
                    cc.Load(item);
                    cc.ExecuteQuery();
                    if (item != null)
                    {
                        Product product = new Product
                        {
                            ID = item.Id,
                            Title = item["Title"].ToString(),
                            UnitPrice = item["UnitPrice"] == null ? 0.00m : Convert.ToDecimal(item["UnitPrice"]),
                            UnitsOnStock = item["UnitsOnStock"] == null ? 0 : Convert.ToInt32(item["UnitsOnStock"])
                        };
                        return View(product);
                    }
                    else
                    {
                        return View();
                    }
                }
                else
                {
                    ViewBag.ErrorMessage = "Error: ClientContext was null";
                    return View();
                }

            }
        }

        // POST: Product/Edit/5
        [HttpPost]
        public ActionResult Edit(int id, System.Web.Mvc.FormCollection collection)
        {
            try
            {
                string title = collection["Title"].ToString();
                decimal unitPrice = Convert.ToDecimal(collection["UnitPrice"]);
                int unitsOnStock = Convert.ToInt32(collection["UnitsOnStock"]);

                var spContext = SharePointAcsContextProvider.Current.GetSharePointContext(HttpContext);
                using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
                {
                    if (cc != null)
                    {
                        ListItem item = cc.Web.Lists.GetByTitle("Products").GetItemById(id);
                        item["Title"] = title;
                        item["UnitPrice"] = unitPrice;
                        item["UnitsOnStock"] = unitsOnStock;
                        item.Update();
                        cc.ExecuteQuery();
                        return RedirectToAction("Index", new { SPHostUrl = Request.QueryString["SPHostUrl"] });
                    }
                    else
                    {
                        ViewBag.ErrorMessage = "ClientContext was null.";
                        Product product = new Product
                        {
                            ID = id,
                            Title = title,
                            UnitPrice = unitPrice,
                            UnitsOnStock = unitsOnStock
                        };
                        return View(product);
                    }
                }
            }
            catch (Exception ex)
            {
                Exception ie = ex;
                while (ie.InnerException != null)
                {
                    ie = ie.InnerException;
                }
                ViewBag.Error = "Error: " + ie.Message;
                return View();
            }
        }

        // GET: Product/Delete/5
        public ActionResult Delete(int id)
        {
            var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
            using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
            {
                if (cc != null)
                {
                    ListItem item = cc.Web.Lists.GetByTitle("Products").GetItemById(id);
                    cc.Load(item);
                    cc.ExecuteQuery();

                    if (item != null)
                    {
                        Product product = new Product
                        {
                            ID = item.Id,
                            Title = item["Title"].ToString(),
                            UnitPrice = item["UnitPrice"] == null ? 0.00m : Convert.ToDecimal(item["UnitPrice"]),
                            UnitsOnStock = item["UnitsOnStock"] == null ? 0 : Convert.ToInt32(item["UnitsOnStock"])
                        };
                        return View(product);
                    }
                    else
                    {
                        return View();
                    }
                }
                else
                {
                    ViewBag.Error = "Error: ClientContext was null";
                    return View();
                }
            }

        }

        // POST: Product/Delete/5
        [HttpPost]
        public ActionResult Delete(int id, System.Web.Mvc.FormCollection collection)
        {
            string title = collection["Title"].ToString();
            decimal unitPrice = Convert.ToDecimal(collection["UnitPrice"]);
            int unitsOnStock = Convert.ToInt32(collection["UnitsOnStock"]);
            try
            {
                var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
                using (ClientContext cc = spContext.CreateUserClientContextForSPHost())
                {
                    if (cc != null)
                    {
                        ListItem item = cc.Web.Lists.GetByTitle("Products").GetItemById(id);
                        item.DeleteObject();
                        cc.ExecuteQuery();
                        return RedirectToAction("Index", new { SPHostUrl = Request.QueryString["SPHostUrl"] });
                    }
                    else
                    {
                        Product product = new Product
                        {
                            ID = id,
                            Title = title,
                            UnitPrice = unitPrice,
                            UnitsOnStock = unitsOnStock
                        };
                        ViewBag.Error = "Error: ClientContext was null";
                        return View();
                    }
                }
            }
            catch (Exception ex)
            {
                Exception ie = ex;
                while (ie.InnerException != null)
                {
                    ie = ie.InnerException;
                }
                ViewBag.ErrorMessage = "Error: " + ie.Message;
                return View();
            }
        }
    }
}

Monday, July 25, 2016

Bootstrap Popover() - useful example

Bootstrap popover() example below has a few useful features:
  1. Popover initiates via mouse-hover over <span class="paymentNum">
  2. trigger: 'manual' is used with onmouseenter and onmouseleave event to mimic trigger by hover
  3. User can move the mouse into the popover. Popover dissapears when mouse is completely out of the popover-initiating span tag or the shown popover
  4. Once popover is shown, it stays visible even when mouse moves between the popover-initiating span tag and the popover itself (This would not work if trigger: 'hover' was used. It was possible by using trigger: 'manual' and onmouseenter and onmouseover events).
  5. Popover title is dynamically loaded.
  6. Popover content is dynamically loaded via ajax. Loading... is shown if there is a delay. When ajax get is done, its response dynamically replaces popover content.
<span class="paymentNum">@payment.PaymentNum</span>
<input type="hidden" class="payment-id" value="@payment.PaymentID" />
                       
.....

<script type="text/javascript">
        $(function () {

            $('span.paymentNum').popover({
                trigger: 'manual',
                placement: 'right',                
                title: function(){
                    return "Payment " + $(this).text();
                },
                html: true,
                animation: false,
                container: 'body',  
                template: '<div class="popover" role="tooltip" style="min-width: 400px; background-color: #fff; ">' +
                            '<div class="arrow"></div>' +
                            '<h3 class="popover-title" style="background-color: #dedede"></h3>' +
                            '<div class="popover-content" style="height: 400px; overflow-y: auto; font-size: 0.9em;"></div>' +
                            '</div>',
                content: function () {
                    var div_id = "temp_" + $.now();
                    var payment_id = $(this).parent().find('.payment-id').val();
                    
                    $.ajax({
                        type: 'GET',
                        url: GL.site_root_path + '/Payment/_QuickSummary/' + payment_id,
                        cache: false,
                        beforeSend: function () { },
                        complete: function () { }
                    }).done(function (d) {
                        $('#' + div_id).html(d); // Genius!!!
                    });
                    return '<div id="' + div_id + '"><div style="margin-top: 180px; text-align: center; font-size: 1.2em;">Loading ...<i class="fa fa-refresh fa-spin"></i></div></div>';                    
                }
            }).on('mouseenter', function () {
                var _this = this;
                $(this).popover("show");
                $('.popover').on('mouseleave', function () {
                    $(_this).popover("hide");
                });
            }).on('mouseleave', function () {
                var _this = this;
                setTimeout(function () {
                    if (!$('.popover:hover').length) {
                        $(_this).popover("hide");
                    }
                }, 50);
            });
        });

    </script>