Create a provider-hosted add-in that includes a custom SharePoint list and content type
Important
The SharePoint Add-In model in SharePoint Online has been deprecated as of November 27th 2023, checkout the full retirement announcement to learn more.
Deprecation means that the feature will not get any new investments, but it's still supported. SharePoint add-in model is retired fully on April 2nd, 2026 and is no longer available after that time. Primary replacement technology for the SharePoint add-in model is SharePoint Framework (SPFx) which continues to be supported also in future.
Create a SharePoint Add-in that combines a cloud-hosted web application with custom SharePoint-hosted list templates, list instances, and custom content types by using the Office Developer Tools for Visual Studio. Learn how to interact with SharePoint add-in webs by using the REST/OData web service, and how to implement OAuth in a SharePoint Add-in.
Most classic SharePoint components, such as custom content types, custom list definitions, and workflows, can be included in a cloud-hosted SharePoint Add-in. The simple example in this article contains the following:
An add-in web with:
Some custom site columns
A custom content type that uses the custom columns
A custom list template that uses the custom content type
A list instance based on the custom list definition
An ASP.NET web application that reads data from the list instance
Prerequisites for creating this SharePoint Add-in
Visual Studio includes the Microsoft Office Developer Tools for Visual Studio, but sometimes a version of the tools is released between updates of Visual Studio. To be sure that you have the latest version of the tools, run the installer for Office Developer Tools for Visual Studio 2013 or the installer for Office Developer Tools for Visual Studio 2015.
A SharePoint installation for testing and debugging
This can be on the same computer as your development computer, or you can develop with a remote SharePoint installation. If you work with a remote installation, you need to install the client object model redistributable on the target installation. It is available as a redistributable package on the Microsoft Download Center. Search for "SharePoint Server 2013 Client Components SDK" or "SharePoint Online Client Components SDK".
The test SharePoint website must be created from the Developer Site site definition (which you can create in Central Administration).
Your remote web application communicates with the add-in web by using either JavaScript and the cross-domain library or OAuth. If OAuth is used, as it is in the continuing example of this article, the SharePoint installation must be configured to use OAuth.
Note
For guidance about how to set up a development environment that fits your needs, see Two types of SharePoint Add-ins: SharePoint-hosted and provider-hosted.
Core concepts to know for creating an add-in
Before you create your first add-in, you should have a basic understanding of what SharePoint Add-ins are and the differences between SharePoint-hosted and provider-hosted SharePoint Add-ins. The articles in the following table should give you that understanding.
Article title | Description |
---|---|
SharePoint Add-ins | Learn about the new add-in model in SharePoint that enables you to create add-ins, which are small, easy-to-use solutions for end users. |
Important aspects of the SharePoint Add-in architecture and development landscape | Learn about aspects of the architecture of SharePoint Add-ins and the model for SharePoint Add-ins, including the add-in hosting options, user interface (UI) options, deployment system, security system, and life cycle. |
Choose patterns for developing and hosting your SharePoint Add-in | Learn about the various ways that you can host SharePoint Add-ins. |
Develop the SharePoint Add-in
In the procedures of this section, you create a SharePoint Add-in that includes an add-in web with SharePoint components and a remote web application on your development machine.
To set up the Visual Studio solution and its elements
In Visual Studio, create an Add-in for SharePoint project from the Office SharePoint | Add-ins node (under either C# or Visual Basic) in the templates tree of the New Project Wizard. Select the Provider-hosted hosting option. In the continuing example of this article, C# is used as the language, and LocalTheater is the project name.
In the wizard, select Finish.
Open the AppManifest.xml file in the manifest designer. The Title element has the project name as its default value. Replace it with something more friendly because this is the name of the add-in that users see in the UI.
Specify a Name for the add-in. This is an internal name that must contain only ASCII characters and must contain no spaces; for example, LocalTheater.
Open the Web.config file in the web application project, and add the element
<customErrors mode="Off"/>
to the system.web element.Check to see that references to the following assemblies are in the web application project. If your edition of Visual Studio did not add the references automatically, add them now.
Microsoft.IdentityModel.dll. This assembly is installed into the global assembly cache with Windows Identity Foundation (WIF). Because this is a .NET Framework 3.5 assembly, it is filtered out of the Framework node of the Add Reference dialog box by default. You can add a reference to it by browsing directly to the
C:\Program Files\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5
directory of your development computer.Microsoft.IdentityModel.Extensions.dll. You can add a reference to it by browsing directly to the
C:\Program Files\Reference Assemblies\Microsoft\Microsoft Identity Extensions\1.0
folder of your development computer.System.IdentityModel.dll. This assembly is part of the .NET Framework 4, and it appears on the Assemblies | Framework node of the Add Reference dialog box.
If your remote web application accesses information in the host web as well as in the add-in web, you must add an AppPermissionRequests element, with one or more child AppPermissionRequest elements, to the AppManifest.xml file. (The web application in the continuing example of this article accesses only the add-in web. Add-in principals automatically have all permissions needed to the add-in web, so the AppManifest.xml in the example does not have an AppPermissionRequests element.) For more information about add-in permission requests and how to add them, see Add-in permissions in SharePoint.
To add the SharePoint components
You add SharePoint components to an add-in exactly as you would add them to a classic farm solution. However, not every kind of SharePoint component can be included in a SharePoint Add-in. The purposes these components serve are accomplished in other ways in SharePoint Add-ins.
For detailed information about what kinds of SharePoint components can be included in a SharePoint Add-in and how to include them in a project, see Types of SharePoint components that can be in a SharePoint Add-in.
For purposes of the continuing example, use the following procedures, which provide examples of using Visual Studio to add custom columns, content types, list templates, and list instances to a SharePoint Add-in.
To create the custom column types
In Solution Explorer, add a SharePoint Site Column item to the SharePoint Add-in project with the name Actor.
In the elements.xml file for the new site column, edit the Field element so that it has the attributes and values shown in the following example, except that you should not change the GUID for the ID attribute from the value that Visual Studio generated for it. Don't forget the framing braces "{}".
<Field ID="{generated GUID}"
Name="Actor"
Title="Actor"
DisplayName="Actor/Actress"
Group="Theater and Movies"
Description="The person cast, perhaps tentatively, in the role"
Type="Text"
/>
Add another Site Column to the project named CastingStatus.
In the elements.xml file for the new site column, edit the Field element so that it has the attributes and values shown in the following example, except that you should not change the GUID for the ID attribute from the value Visual Studio generated for it.
<Field ID="{generated GUID}"
Name="CastingStatus"
Title="CastingStatus"
DisplayName="Casting Status"
Group="Theater and Movies"
Description="The current casting status of the role"
Type="Choice">
</Field>
- Because this is a Choice field, you must specify the possible choices, the order in which they should appear in the drop-down list when a user is making a choice, and the default choice. Add the following child markup to the Field element.
<CHOICES>
<CHOICE>Not Started</CHOICE>
<CHOICE>Audition Scheduled</CHOICE>
<CHOICE>Auditioned</CHOICE>
<CHOICE>Role Offered</CHOICE>
<CHOICE>Committed to Role</CHOICE>
</CHOICES>
<MAPPINGS>
<MAPPING Value="1">Not Started</MAPPING>
<MAPPING Value="2">Audition Scheduled</MAPPING>
<MAPPING Value="3">Auditioned</MAPPING>
<MAPPING Value="4">Role Offered</MAPPING>
<MAPPING Value="5">Committed to Role</MAPPING>
</MAPPINGS>
<Default>Not Started</Default>
To create the custom content type
In Solution Explorer, add a SharePoint Content Type item to the SharePoint Add-in project with the name ActingRole. When prompted by the wizard to select the base content type, select Item, and then select Finish.
If the content type designer does not automatically open, select the ActingRole content type in Solution Explorer to open it.
Open the Content Type tab in the designer, and fill the text boxes as follows:
Content Type Name: ActingRole
Description: Represents a role in a play or movie.
Group Name: Theater and Movies
Verify that none of the check boxes on the tab are selected. The check box for Inherits the columns from the parent Content Type may be selected by default. Be sure to clear it.
Open the Columns tab in the designer.
Use the grid to add the two site columns to the content type. They are listed in the drop-down list by their display names: Actor/Actress and Casting Status. (If they are not listed, you may not have saved the project since adding the custom site columns. Select Save all).
Save the file and close the designer.
The next step requires that you work directly in the raw XML for the content type, so in Solution Explorer, select the elements.xml file child of the ActingRole content type.
There are already FieldRef elements in the file for the two columns that you added. Add FieldRef elements for two built-in SharePoint columns as peers of the two that are already there. The following is the markup for the elements. You must use these same GUIDs for the ID attribute because these are built-in field types with fixed IDs. Add these above the two FieldRef elements for the custom site columns.
<FieldRef Name="LinkTitle" ID="{82642ec8-ef9b-478f-acf9-31f7d45fbc31}" DisplayName="Character" />
<FieldRef Name="Title" ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="Character" />
Note that we have given these fields the custom display name Character in the sense of a character in a play or movie.
To create the custom list template and a list instance
Add a SharePoint List item to the SharePoint Add-in project with the name CharactersInShow. On the Choose List Settings page of the SharePoint Customization Wizard, leave the list display name at the default CharactersInShow, select the Create a customizable list based on option, and select Default (Blank) on the drop-down list. Select Finish.
When you complete the wizard, a CharactersInShow list template is created with a child list instance named CharactersInShowInstance. A list designer may have opened by default. It is used in a later step.
Open the elements.xml child of the CharactersInShow list template (not the elements.xml child of the CharactersInShowInstance).
Add spaces to the DisplayName attribute to make it friendlier: Characters in Show.
Set the Description attribute to The characters in a play or movie.
Leave all other attributes at their default, save the file, and close it.
If the list designer is not open, select the CharactersInShow node in Solution Explorer.
Open the Columns tab in the designer, and then select the Content Types button.
In the Content Type Settings dialog, add the ActingRole content type.
Select the ActingRole content type in the list of types, and then select the Set as Default button.
Select the Item content type, right-click the small arrowhead that appears to the left of the content type name, and then select Delete.
Repeat the preceding step for the Folder content type, so that ActingRole is the only content type listed. Select OK to close the dialog.
Three columns are now in the list of columns. Select Title, right-click the small arrowhead that appears to the left of the content type name, and then select Delete. Only two columns should now be listed, Actor/Actress and Casting Status.
Open the List tab of the designer. This tab is used to set certain values for the list instance, not the list template.
Change the values on this tab to the following:
Title: Characters in Hamlet
List URL: Lists/CharactersInHamlet
Description: The characters in Hamlet and casting information.
Leave the check boxes at their default status, save the file, and close the designer.
The list instance may have its old name in Solution Explorer. If so, open the shortcut menu for CharactersInShowInstance, select Rename, and change the name to CharactersInHamlet.
Open the schema.xml file.
There may be two ContentType elements in the file, one with the Name attribute value of ActingRole and another called ListFieldsContentType. Only the one called ActingRole belongs, so delete any other ContentType elements.
Note
There may not be line breaks between the ContentType elements, in which case it may appear at first that there is only one. Scroll to the right and check carefully for others.
The Fields element should have two Field elements (which are on a single line if there is no line break between them). One should exactly duplicate the Field element in the Actor site column elements.xml, and the other should exactly duplicate the Field element from the CastingStatus site column elements.xml. If there is not an exact match, including all child elements (such as the CHOICES and MAPPINGS elements), copy the Field element from the site column elements.xml file and paste it in place of the mismatched Field element in the schema.xml file.
Still in the schema.xml file, in the View element whose BaseViewID value is "0", replace the existing ViewFields element with the following markup. (Use exactly this GUID for the FieldRef named
LinkTitle
.)
<ViewFields>
<FieldRef Name="Title" ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="Character" />
<FieldRef Name="Actor" ID="{GUID from the site column elements.xml}" />
<FieldRef Name="CastingStatus" ID="{GUID from the site column elements.xml}" />
</ViewFields>
Replace the two missing ID attribute values with the GUIDs in the respective site column elements.xml files. Don't forget the framing braces "{}".
Still in the schema.xml file, in the View element whose BaseViewID value is "1", replace the existing ViewFields element with the following markup. (Use exactly this GUID for the FieldRef named
LinkTitle
.)
<ViewFields>
<FieldRef Name="LinkTitle" ID="{82642ec8-ef9b-478f-acf9-31f7d45fbc31}" DisplayName="Character" />
</ViewFields>
Copy the two FieldRef elements for
Actor
andCastingStatus
that you added to the previous view to this ViewFields element as siblings of theLinkTitle
FieldRef.Save and close the schema.xml file.
Open the elements.xml file that is a child of the list instance CharactersInHamlet.
Populate the list with some initial data by adding the following markup as a child of the ListInstance element.
<Data>
<Rows>
<Row>
<Field Name="Title">Hamlet</Field>
<Field Name="Actor">Tom Higginbotham</Field>
<Field Name="CastingStatus">Committed to Role</Field>
</Row>
<Row>
<Field Name="Title">Claudius</Field>
<Field Name="Actor"></Field>
<Field Name="CastingStatus">Not Started</Field>
</Row>
<Row>
<Field Name="Title">Gertrude</Field>
<Field Name="Actor">Satomi Hayakawa</Field>
<Field Name="CastingStatus">Auditioned</Field>
</Row>
<Row>
<Field Name="Title">Ophelia</Field>
<Field Name="Actor">Cassi Hicks</Field>
<Field Name="CastingStatus">Committed to Role</Field>
</Row>
<Row>
<Field Name="Title">The ghost</Field>
<Field Name="Actor">Lertchai Treetawatchaiwong</Field>
<Field Name="CastingStatus">Role Offered</Field>
</Row>
</Rows>
</Data>
In Solution Explorer, select Feature1 to open the Feature designer. In the designer, set the Title to Theater and Movie Data Components, and set the Description to Site columns, content types, and list instances for data about theater and movies.. Save the file, and close the designer.
If the Feature1 in Solution Explorer has not been renamed, open its shortcut menu, select Rename, and rename it TheaterAndMovieDataComponents.
To code the remote web application project
Develop the web application as you would any other web application for your preferred platform stack. For a Microsoft stack, you can use either the REST/OData web service or one of the client object models in SharePoint. For a non-Microsoft stack, you can use the REST/OData endpoints in SharePoint to perform create/read/update/delete (CRUD) operations on data in the add-in web.
Note
When you add a reference to an assembly to your web application project in Visual Studio, set the Copy Local property of the assembly to True, unless you know that the assembly is already installed on the web server, or you can ensure that it is installed before you deploy your add-in. The .NET Framework is installed on Microsoft Azure Web Roles and Azure websites. But the SharePoint client assemblies and the various Microsoft managed code extensions and foundations are not installed. Office Developer Tools for Visual Studio automatically adds references to some assemblies commonly used in SharePoint Add-ins and sets the Copy Local property.
For the continuing example, you develop an ASP.NET web application. Take the following steps.
- Open the Default.aspx file and replace the body element of the file with the following markup. The markup adds a Get the Cast button that, when chosen, reads the Characters in Hamlet list that is in the add-in web and presents its data in a GridView control that appears only after the button is pressed.
<body >
<form id="form1" runat="server">
<div>
<h2>Local Theater</h2>
</div>
<asp:Literal ID="Literal1" runat="server"><br /><br /></asp:Literal>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Get the Cast"/>
<asp:Literal ID="Literal2" runat="server"><br /><br /></asp:Literal>
<asp:GridView ID="GridView1" runat="server" Caption="The Cast" ></asp:GridView>
</form>
</body>
- Open the Default.aspx.cs file and add the following using statements to it.
using Microsoft.SharePoint.Client;
using Microsoft.IdentityModel.S2S.Tokens;
using System.Net;
using System.IO;
using System.Xml;
using System.Data;
using System.Xml.Linq;
using System.Xml.XPath;
using Microsoft.SharePoint.Samples;
The last of these statements refers to the namespace that is declared in the TokenHelper.cs file.
3. Add the following fields to the **Default** class. ```csharp SharePointContextToken contextToken; string accessToken; Uri sharepointUrl; ```
- Replace the Page_Load method with the following code that uses the TokenHelper class to obtain tokens from the OAuth-compliant secure token server. The access token is then stored in the CommandArgument property of the button for later retrieval by the button's click event handler.
protected void Page_Load(object sender, EventArgs e)
{
TokenHelper.TrustAllCertificates();
string contextTokenString = TokenHelper.GetContextTokenFromRequest(Request);
if (contextTokenString != null)
{
// Get context token
contextToken = TokenHelper.ReadAndValidateContextToken(contextTokenString, Request.Url.Authority);
// Get access token
sharepointUrl = new Uri(Request.QueryString["SPAppWebUrl"]);
accessToken = TokenHelper.GetAccessToken(contextToken, sharepointUrl.Authority).AccessToken;
// Pass the access token to the button event handler.
Button1.CommandArgument = accessToken;
}
}
- Add the following event handler to the Default class. The handler begins by retrieving the access token that was stored in the button's CommandArgument property.
protected void Button1_Click(object sender, EventArgs e)
{
// Retrieve the access token that the Page_Load method stored
// in the button's command argument.
string accessToken = ((Button)sender).CommandArgument;
}
- The handler needs to reacquire the modified add-in web URL on postbacks, so add the following code.
if (IsPostBack)
{
sharepointUrl = new Uri(Request.QueryString["SPAppWebUrl"]);
}
- Add the following line that uses one of the SharePoint REST/OData endpoints to obtain list data. In this example, the code reads the Characters in Hamlet list that is deployed to the add-in web. The APIs for this service make it easy, in a single line of code, to select a list and specify three fields from the list to return.
Note that in the OData URL, you must use the internal names of the fields (columns) rather than the display names, so the code uses Title
, Actor
, and CastingStatus
rather than Character
, Actor/Actress
, and Casting Status
. For more information about the REST/OData web service, see Use OData query operations in SharePoint REST requests.
// REST/OData URL section
string oDataUrl = "/_api/Web/lists/getbytitle('Characters In Hamlet')/items?$select=Title,Actor,CastingStatus";
- Add the following code that uses the HttpWebRequest and HttpWebResponse classes of the System.Net namespace to construct the HTTP request and response objects.
// HTTP Request and Response construction section
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + oDataUrl);
request.Method = "GET";
request.Accept = "application/atom+xml";
request.ContentType = "application/atom+xml;type=entry";
request.Headers.Add("Authorization", "Bearer " + accessToken);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- Add the following code to parse the ATOM-formatted response XML. It uses the classes of the System.Xml.Linq namespace to parse the data that is returned and construct a List<T> of the items from the SharePoint list. (You could also use the classes of the System.Xml namespace.)
Note that, in the XML that SharePoint returns, the child elements of the entry element hold metadata about the list item. The actual row data of a SharePoint list item is nested two layers down in the properties element. For that reason the Elements<T> extension method is used twice to filter out the higher levels.
// Response markup parsing section
XDocument oDataXML = XDocument.Load(response.GetResponseStream(), LoadOptions.None);
XNamespace atom = "http://www.w3.org/2005/Atom";
XNamespace d = "http://schemas.microsoft.com/ado/2007/08/dataservices";
XNamespace m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
List<XElement> entries = oDataXML.Descendants(atom + "entry")
.Elements(atom + "content")
.Elements(m + "properties")
.ToList();
- Add the following LINQ query to construct an IEnumerable<T> collection of an anonymous type that has just the properties you need and no others. Note that although the code must refer to the item title field by its internal name
Title
, the property name in the anonymous type, to which the value is assigned, can be namedCharacter
. One effect of this is that when the collection is bound to a grid control, the more appropriate name Character appears on the page.
var entryFieldValues = from entry in entries
select new { Character=entry.Element(d + "Title").Value,
Actor=entry.Element(d + "Actor").Value,
CastingStatus=entry.Element(d + "CastingStatus").Value };
- Finish the handler with the following code to bind the data to a GridView control on the page. The column headers in the grid default to the property names of the anonymous type:
Character
,Actor
, andCastingStatus
. The GridView control has properties that enable you to control the name and formatting column headers, so you could have Actor/Actress and Casting Status to match the column headers in SharePoint. For simplicity, these techniques are not described here. (You could also use a DataGrid control.)
GridView1.DataSource = entryFieldValues;
GridView1.DataBind();
- Save all files.
To test and debug the SharePoint Add-in
To test the SharePoint Add-in and its remote web application, select the F5 key in Visual Studio. The web application is deployed to IIS Express at localhost. The SharePoint Add-in is installed to the target SharePoint website. (In the continuing example, the remote add-in does not try to interact with the host web, and the add-in principal automatically has permissions to the add-in web, so you are not prompted to grant permissions.) The Site Contents page of your target SharePoint website opens, and you see the new add-in listed there.
Select the SharePoint Add-in, and the remote web application opens to the page you specified in the StartPage element in the AppManifest.xml file. Use the web application as needed to verify that it is working. In the continuing example of this topic, just select the button. Doing so creates a grid and populates it with the Characters in Hamlet list of the add-in web.
Publish the SharePoint Add-in
To publish your SharePoint Add-in, upload the add-in package to a corporate add-in catalog or to the Office add-in store. For more information, see Publishing to the Office Store or an organization's add-in catalog and Publish SharePoint Add-ins.
Troubleshooting
If the add-in is not working, you should consider whether a mistake in the CAML markup is blocking deployment of the SharePoint components. Use a procedure similar to the following, which is based on the continuing example, to verify the deployment.
To test the provisioning of the add-in web
Open the Site Settings page of the host web. In the Site Collection Administration section, select the Site hierarchy link.
On the Site Hierarchy page, you see your add-in listed by its URL. Do not launch it. Instead, copy the URL and use the URL in the remaining steps.
Navigate to URL_of_app_web/_layouts/15/ManageFeatures.aspx, and on the Site Features page that opens, verify that Theater and Movie Data Components is on the alphabetical list of features in your SharePoint Add-in, and that its status is Active.
Navigate to URL_of_app_web/_layouts/15/mngfield.aspx, and on the Site Columns page that opens, verify that a Theater and Movies group is in the list of site columns, and that it contains your new custom site columns, Actor/Actress and Casting Status.
Navigate to URL_of_app_web/_layouts/15/mngctype.aspx, and on the Site Content Types page that opens, verify that a Theater and Movies group is in the list of content types, and that it contains your new ActingRole content type.
Select the link to the ActingRole content type. On the Site Content Type page that opens, verify that the content type has the two new site column types, Actor/Actress and Casting Status, and that the item title field has been given your custom display name: Character.
Navigate to URL_of_app_web/_layouts/15/mcontent.aspx, and on the Site Libraries and Lists page that opens, verify that there is a Customize "Characters in Hamlet" link.
Select the Customize "Characters in Hamlet" link, and verify on the list settings page that the only content type for the list is your custom ActingRole content type, and that your two new site columns, Actor/Actress and Casting Status are listed in the Columns section. (The Title column may appear with its internal name Title instead of the display name Character that you gave it.)
Note
If there is no Content Types section on the page, you must enable management of content types. Click the Advanced Settings link, and on the Advanced Settings page, enable management of content types, and then select OK. You are returned to the previous page, where there is now a list of Content Types section.
- Near the top of the page is the Web Address of the list. Copy this and paste it into the address bar of your browser, and then navigate to the list. Verify that the list has the sample items that you created. (The Title column may appear with its internal name Title instead of the display name Character that you gave it.)