Image depicting Provider-Hosted MVC AppSharePoint Apps (also referred to as add-ins) extend SharePoint’s capability to solve specific business problems. There are three types of apps:

a) SharePoint-hosted
b) Provider-hosted
c) Autohosted

This blog post will walk through the process of creating and deploying a provider-hosted MVC app, which displays a welcome message to the logged-in user. Further, it will provide code snippets that allow this app to address the specific business use case of employee(s) submitting “Leave requests” to manager(s). Provider-hosted MVC apps contain two components:

a) App-part that resides on SharePoint/Office 365
b) Web site/web application that can be deployed on a server in a corporate domain or on a cloud service

As we proceed further, we will be deploying App-part to SharePoint Online/Office 365 and ‘Web application’ to Azure.

Creating Provider-Hosted MVC App in Visual Studio

1) In Visual Studio 2013 – Navigate to File > New > Project, select ‘App for SharePoint2013.’ Give it a ‘Name’ and click on ‘Ok’ as shown in the screenshot below:

Visual Studio 2013

2) Specify the ‘URL’ where you want to deploy the app and select ‘Provider-hosted’ as shown in the screenshot below:

Hosting

3) Select ‘ASP.NET MVC Web Application’ option and click on the ‘Next’ button.

MVC Web Application

4) Select ‘Azure Access Control Service’ authentication.

Azure Access

5) Click on the ‘Finish’ button.

Creating a Website in Azure

1) Log in to Portal.Azure.com and click on ‘App Services.’

App Services

2) Click on ‘Add’ and then click on ‘Web App’ option.

App Services

Web Apps

3) Click on ‘Create’ button.

4) On the following screen, enter ‘App name,’ select ‘Subscription,’ select ‘Create new,’ and re-enter the ‘App name’ and click on the ‘Create’ button at the bottom, as shown in the screenshot below:

fields

5) A few moments later your website is ready. Clicking on the website name (ApplyLeave) will show the details of the web application created.

apply leave

6) Click on ‘…More’ and then click on ‘Get Publish Profile’ as shown below. Save the profile on your machine.

Publish Profile

How to Deploy Provider-Hosted MVC App to Office 365 and Web Application Component to Azure

1) In Visual Studio 2013, right click on ‘LeaveRequest’ app project and then click on ‘Publish.’

leave request

2) In the Publish your app screen, select ‘New’ from the current profile drop-down menu.

publish app

3) Browse and select the Azure website publishing profile, which was downloaded earlier and click on ‘Next’ button.

Import Profile

4) Register the SharePoint provider-hosted MVC app by navigating to [Offic365 Site]/ /_layouts/15/appregnew.aspx. Fill all details as shown below and click on ‘Create’ button.

register

Note: You can obtain the ‘App domain’ and ‘Redirect URI’ from the Azure website created earlier. Be sure to change ‘http’ to ‘https.’

5) Back in Visual Studio 2013, copy and paste the ‘Client ID’ and ‘Client Secret’ as shown below and click on the ‘Finish’ button.

Identity

6) Subsequently, click on ‘Deploy your web project’ button.

deploy

7) Click on ‘Start Preview.’

Start Preview

8) Once the preview process is completed, click on ‘Connection’ tab. Change the ‘Destination URL’ from ‘http’ to ‘https’ and click on ‘Validate Connection’ button.

Connection

9) If ‘Validation’ succeeds, click on ‘Publish’ button; otherwise, correct the errors and click on ‘Publish.’ After the site is published, you should see the ‘Site was published successfully’ message.

10) Next, click on ‘Package the app’ button. Ensure ‘Client ID’ matches with the one generated earlier and click on ‘Finish’ button. The App package gets created.

package app

11) Navigate to your ‘AppCatalog’ site and upload the ‘app package’ created in step (10) by clicking the ‘Upload’ option.

app catalog

12) Navigate to Office 365 SharePoint site, where you would prefer to deploy/add this app. Click on ‘Settings Icon’ (Highlighted below) and then click on ‘Site Contents.’

office365

13) Click on ‘add an app.’

add app

14) Click on ‘From Your Organization’ (present on the left menu) and then click on ‘LeaveRequest’ app. Click the ‘Trust it’ option.

from organization

15) Once the app is added, click on it. You can see it is now redirected to the Azure web site created earlier.

azure web

Extending the App – Creating List and Adding Code (Use Case)

Let us now look at the various steps required to extend a simple welcome message app that allows employees to submit leave requests to their managers.

Creating SharePoint List in Office 365/SharePoint Online

The sample leave request app will read from and write to this list.

1) Log in to Office 365 SharePoint Online site previously used for deploying your app.

2) Navigate to Settings Icon > Site Contents > Add an app. Click on ‘Custom List,’ give a name ‘Leave Requests,’ and click on ‘Create.’

3) On the top ribbon menu, click on ‘List’ tab and then ‘List Settings,’ as depicted below.

list settings

4) Scroll to the bottom and click on ‘Create column’ link. Create all the columns listed in the table below:

table

Steps in Visual Studio 2013

In Visual Studio 2013, open the previously created MVC app project and add new class files (highlighted in red) to the ‘WebApplication’ project (2nd project in the solution; do not add to App Project component) in respective folders by navigating to Add > New Item, as shown in the screenshot below:

web application

  • Add the code snippet below to leaves.cs file:
namespace GDAzurePHMvcSPWeb.Models
{
public class Leave
{
public string Description { get; set; }
public string Reason { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string Manager { get; set; }
public string Status { get; set; }
}
}
  • Add below code snippet to SharePointService.cs file
namespace GDAzurePHMvcSPWeb
{
public class SharePointService
{
public static string GetUserName(SharePointContext spContext)
{
string strUserName = null;
User spUser = null;
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
spUser = clientContext.Web.CurrentUser;
clientContext.Load(spUser, user => user.Title);
clientContext.ExecuteQuery();
strUserName = spUser.Title;
}
}
return strUserName;
}
//Reads submitted leaves and displays in the UI
public static List<Leave>GetLeaves(SharePointContext spContext, CamlQuery camlQuery)
{
List<Leave> leaves = new List<Leave>(); 
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
List lstLeaves = clientContext.Web.Lists.GetByTitle("Leave Requests");
ListItemCollection lstLeaveItems = lstLeaves.GetItems(camlQuery);
clientContext.Load(lstLeaveItems);
clientContext.ExecuteQuery();
if (lstLeaveItems != null)
{
foreach (var lstLeaveItem in lstLeaveItems)
{
leaves.Add(
new Leave
{
Description = lstLeaveItem["Title"].ToString(),
StartDate = (DateTime)lstLeaveItem["StartDate"],
EndDate = (DateTime)lstLeaveItem["EndDate"],
Reason = lstLeaveItem["Reason"].ToString(),
Manager = lstLeaveItem["Manager"].ToString(),
Status = lstLeaveItem["Status"].ToString()
});
}
}
}
}
return leaves;
}
//Gets Leave Reason type choice field values from list
public static List<SelectListItem>GetLeaveTypes(SharePointContext spContext)
{
List<SelectListItem> reasonTypes = new List<SelectListItem>();
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
List lstLeaves = clientContext.Web.Lists.GetByTitle("Leave Requests");
Field choiceReason = lstLeaves.Fields.GetByInternalNameOrTitle("Reason");
FieldChoice fldReason = clientContext.CastTo<FieldChoice>(choiceReason);
clientContext.Load(fldReason, f => f.Choices);
clientContext.ExecuteQuery();
foreach (string vacationType in fldReason.Choices)
{
reasonTypes.Add(new SelectListItem() { Text = vacationType.ToString(), Value = vacationType.ToString() });
}
}
}//End Using
return reasonTypes;
}
}
}
  • Add below code to VacationDataAccessLayer.cs
namespace GDAzurePHMvcSPWeb
{
public class VacationDataAccessLayer
{
//Adds the user filled vacation request form values to Leave Request list
public void AddLeaveRequest(Leave leave, SharePointContext spContext)
{
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
List lstLeaves = clientContext.Web.Lists.GetByTitle("Leave Requests");
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem leaveListItem = lstLeaves.AddItem(itemCreateInfo);
leaveListItem["Title"] = leave.Description;
leaveListItem["Reason"] = leave.Reason;
leaveListItem["StartDate"] = leave.StartDate;
leaveListItem["EndDate"] = leave.EndDate;
leaveListItem["Manager"] = leave.Manager;
leaveListItem["Status"] = "Pending With Manager"; 
leaveListItem.Update();
clientContext.ExecuteQuery();
}
}//End Using 
}
}
}
  • Add below code snippet to Create.cshtml file
@model GDAzurePHMvcSPWeb.Models.Leave
@{
ViewBag.Title = "Create";
}
<div id="divSPChrome"></div>
<div style="font-family:Arial">
<h2>Submit New Vacation Request</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Leave</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Reason, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@*Binding the choice field to dropdown list*@
@Html.DropDownList("Reason", (IEnumerable<SelectListItem>)@ViewBag.VacationTypes, "Select Reason")
@Html.ValidationMessageFor(model => model.Reason)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.StartDate, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.StartDate)
@Html.ValidationMessageFor(model => model.StartDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EndDate, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EndDate)
@Html.ValidationMessageFor(model => model.EndDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Manager, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Manager)
@Html.ValidationMessageFor(model => model.Manager)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit" class="btn btn-success"/>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div> 
</div>
  • Now modify the code files highlighted in green.
  • Modify the HomeController.cs file with the code snippet below:
[SharePointContextFilter]
public ActionResult Index()
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
ViewBag.Username = SharePointService.GetUserName(spContext);
//Read submitted leave requests and display in the view
CamlQuery queryLeaves = new CamlQuery();
queryLeaves.ViewXml = @"<View><ViewFields><FieldRef Name='Title'/><FieldRef Name='StartDate'/><FieldRef Name='EndDate'/><FieldRef Name='Reason'/>
<FieldRef Name='Manager'/><FieldRef Name='Status'/></ViewFields></View>";
List<Leave> leaves = SharePointService.GetLeaves(spContext, queryLeaves);
return View(leaves);
}
//Below Action gets called When we navigate to the HomeController/Create url
[HttpGet]
public ActionResult Create()
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
//Get Leave Reason type choice field values
List<SelectListItem> leaveTypes = SharePointService.GetLeaveTypes(spContext);
ViewBag.VacationTypes = leaveTypes;
return View();
}
//Below Action gets called when "Create" button is clicked on the create.cshtml view. Here we write code to store data in to a datasource (like SQL server) in this case SharePoint List.
[HttpPost]
public ActionResult Create(Leave leave)
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext); 
VacationDataAccessLayer vdal = new VacationDataAccessLayer();
vdal.AddLeaveRequest(leave, spContext);
return RedirectToAction("Index", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri });
}
  • Modify the Index.cshtml file with the code snippet below:
@model IEnumerable<GDAzurePHMvcSPWeb.Models.Leave>
@using GDAzurePHMvcSPWeb.Models;
@{
ViewBag.Title = "Home Page";
}
<div class="jumbotron">
<h2>Welcome to Vacation Request Application - @ViewBag.UserName!</h2>
<p class="lead">To Submit Vacation Request for Approval, Please click on "New Vacation Request" link below.</p>
</div>
<div class="row">
<div class="col-lg-12">
<div class="span8">
<p class="lead"><u>Employee Leaves</u></p>
@Html.ActionLink("New Vacation Request", "Create")
<table class="table table-striped">
<thead>
<tr>
<th>Description</th>
<th>Start Date</th>
<th>End Date</th>
<th>Reason</th>
<th>Manager</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@foreach (Leave objLeave in @Model)
{
<tr>
<td>@objLeave.Description</td>
<td>@objLeave.StartDate.ToString("MM/dd/yyy")</td>
<td>@objLeave.EndDate.ToString("MM/dd/yyy")</td>
<td>@objLeave.Reason</td>
<td>@objLeave.Manager</td>
<td>@objLeave.Status</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
  • In the App Project (1st project in the solution) go to ‘AppManifest.Xml’ file and click on ‘Permissions’ tab. Assign permissions as shown below.

App Manifest Screen

  • Now re-publish the app to Office 365 and web application to Azure as explained previously.
  • Once ‘LeaveRequest’ app is added to SharePoint Online site or Office 365, give the app permissions to ‘Leave Requests’ list and click on ‘Trust it.’

trust

  • If you have followed all the steps above correctly, you will see this screen:

employe eleaves

  • Clicking on ‘New Vacation Request’ link will render the screen below:

New Vacation

Advantages of extending SharePoint with Provider-hosted apps with MVC and Azure

  • Code runs outside of SharePoint/Office 365, so SharePoint upgrades are easy
  • Code is highly secure and cannot be modified in the browser
  • SharePoint server is protected from app-crash
  • No server maintenance troubles, as code runs in a cloud environment

Evoke’s SharePoint Services

Evoke Technologies provides innovative SharePoint services and solutions, helping global enterprises meet their collaboration needs. Evoke’s comprehensive SharePoint Online and SharePoint on-premises services enable organizations to meet their business goals and adds immense business value. At Evoke, we believe SharePoint is the right cloud ecosystem for growing enterprises. Evoke’s SharePoint services streamline workflow, maximize efficiency and enhance overall productivity for enterprises across the globe.

Evoke’s SharePoint Service Offerings Include:

  • SharePoint Implementation and Administration
  • Office 365 and SharePoint Development
  • Planning and Integration
  • Configuration and Customization
  • Application Modernization Services
  • Support and Administration

Evoke has partnered with Nintex and TekDog Inc., the world leaders in productivity, training and workflow solutions. Our partnerships with Nintex and TekDog Inc. help businesses easily embrace SharePoint services.

Call Evoke Technologies at (937) 202-4161 (Select Option 2 for Sales) or visit our website to find out more about how simplified solutions for everyday business challenges can be at your fingertips now!

Srinivas Challagolla

View posts by Srinivas Challagolla
Srinivas Challagolla is working as Technical lead at Evoke Technologies. He has 9+ years of experience in designing and developing web-based solutions using Microsoft technologies. In his free time Srinivas likes to read and explore emerging technologies.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>