Sample: Building apps for SharePoint with MVC (Edit and Delete)

In this post I will extend provider-hosted MVC app sample built by Chakkaradeep Chandran aka Chaks (Visual Studio PM at Microsoft, responsible for Office API tooling) s in a way to implement Edit and Delete operations. For reference, here are links to first two parts on Chaks blog:

I will start from sample code which is provided in the end of Part 2, and can be downloaded from here.

Disclaimer: This blog post contains sample code, and as such is not production-ready. It does not include validation, robust exception handling or logging.

First step is to extend the existing Product class in Models folder. In order to be able to successfullt reference Product that will be edited, property Id will be added to Product class.

public class Product    

public int Id { get; set; }  

public string Title { get; set; }  

public string Description { get; set; }  

public string Price { get; set; }

}

Edit Product

To implement Edit Product operation, I will create two methods in HomeController that correspond to Edit operation. One action method will be used for display, and another to process updates made by users. To accomplish Edit Operation, it is also necessary to create two additional methods in SharePoint Service.

[SharePointContextFilter] public ActionResult Edit(int id) {     var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

    Product product = SharePointService.GetProductDetails(spContext, id);

    return View(product);

}

[HttpPost] [SharePointContextFilter] public ActionResult Edit(Product product) {

    var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);

    SharePointService.UpdateProduct(spContext,product);

    return RedirectToAction("Index", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri });

}

Methods in SharePoint Service are GetProductDetails and UpdateProduct, shown below:

public static Product GetProductDetails(SharePointContext spContext, int id) {

    using (var clientContext = spContext.CreateUserClientContextForSPAppWeb()) {

        if (clientContext != null) {

            List lstProducts = clientContext.Web.Lists.GetByTitle("Products");             ListItem selectedItem = lstProducts.GetItemById(id);             clientContext.Load(selectedItem);

            clientContext.ExecuteQuery();

            if (selectedItem != null){

                return new Product {

                    Id = selectedItem.Id,                     Title = selectedItem["Title"] as string,                     Description = selectedItem["ProductDescription"] as string,                     Price = selectedItem["Price"] as string

};

}         }     }

    return null;

}

public static bool UpdateProduct(SharePointContext spContext, Product product) {

    using (var clientContext = spContext.CreateUserClientContextForSPAppWeb()) {

        if (clientContext != null){

            try {

                List lstProducts = clientContext.Web.Lists.GetByTitle("Products");                                   ListItem selectedItem = lstProducts.GetItemById(product.Id);                  selectedItem["Title"] = product.Title;                 selectedItem["ProductDescription"] = product.Description;                 selectedItem["Price"] = product.Price;                 selectedItem.Update();                                                                  clientContext.ExecuteQuery();                   return true            }             catch (ServerException ex) {

                return false            }          }     }

    return false;

}

With Edit Product controller methods in place, I can scaffold Edit View from the controller, using Add View command which is available from contextual menu that I can reach if I right-click anywhere inside Edit Action method:

In Add View form I need to appropriately select Template and Model Class. View name will be pre-populated with text "Edit" because the form is invoked from Edit action method

Using this approach, Edit view will be created using default scaffolding template in Visual Studio.

Remarks:

  1. Method that responds to POST is decorated with attribute HttpPost

  2. When performing redirect, it is necessary to pass SPHostUrl parameter, so that SharePoint Context can be created. More info here and here

Delete Product

For Delete Product operation, I can use similar procedure:

Action Methods in HomeController:

[SharePointContextFilter] public ActionResult Delete(int id) {

    var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);  

    Product product = SharePointService.GetProductDetails(spContext, id);

    return View(product);

}

[HttpPost] [SharePointContextFilter] public ActionResult Delete(Product product) {

    var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);  

    SharePointService.DeleteProduct(spContext, product);  

    return RedirectToAction("Index", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri });

}

DeleteProduct method in SharePointService

public static void DeleteProduct(SharePointContext spContext, Product product) {

    using (var clientContext = spContext.CreateUserClientContextForSPAppWeb()) {

try {             List productsList = clientContext.Web.Lists.GetByTitle("Products");             ListItem itemToDelete = productsList.GetItemById(product.Id);             itemToDelete.DeleteObject();

            clientContext.ExecuteQuery();         }          catch (ServerException ex) {

// TODO: Exception Handling         }     } } ****

Add View form

Changes in Index View and GetProducts method

To enable Edit and Delete operations, I will slightly modify Products table in Index.cshtml. Modifications include adding Edit and Delete links for each item in this table, as shown in the code snippet below. ****

<table class="table table-striped">     <thead>         <tr> **            <th> </th>             <th>Title</th           ** <th>Description</th**           ** <th>Price</th</tr</thead>

<tbody@foreach (SharePointAppSampleWeb.Models.Product objProduct in Model) {

<tr<td@Html.ActionLink("Edit", "Edit", new ) | @Html.ActionLink("Delete", "Delete", new )

</td>  <td>@objProduct.Title</td> <td>@objProduct.Description</td<td>@objProduct.Price</td</tr>

</tbody> </table>

GetProducts method in SharePointService also has to be changed, because in original version Product.Id has not been passed to the model, as shown in code snippet below:

foreach (var lstProductItem in lstProductItems) {

    products.Add(         new Product { **            Id = lstProductItem.Id,**             Title = lstProductItem["Title"].ToString(),             Description = lstProductItem["ProductDescription"].ToString(),             Price = lstProductItem["Price"].ToString()      });

}

Debug the app

When Products table is open, clicking "Edit" in the row will open Edit form.

Textboxes will be pre-filled with values of current item properties. Values can be edited, and after clicking Save, changes will be saved back to SharePoint List.

Testing Delete operation can be performed by clicking Delete link in any row. Confirmation window will open, and after clicking Delete, product will be deleted from SharePoint list.

Download

Entire code sample can be downloaded from my SkyDrive: http://1drv.ms/TAbT0T . Feel free to comment J