Walkthrough: Extending a SharePoint Project Item Type

You can use the Business Data Connectivity Model project item to create a model for the Business Data Connectivity (BDC) service in SharePoint. By default, when you create a model by using this project item, the data in the model is not displayed to users. You must also create an external list in SharePoint to enable users to view the data.

In this walkthrough, you will create an extension for the Business Data Connectivity Model project item. Developers can use the extension to create an external list in their project that displays the data in the BDC model. This walkthrough demonstrates the following tasks:

  • Creating a Visual Studio extension that performs two main tasks:

    • It generates an external list that displays the data in a BDC model. The extension uses the object model for the SharePoint project system to generate an Elements.xml file that defines the list. It also adds the file to the project so that it is deployed together with the BDC model.

    • It adds a shortcut menu item to the Business Data Connectivity Model project items in Solution Explorer. Developers can click this menu item to generate an external list for the BDC model.

  • Building a Visual Studio Extension (VSIX) package to deploy the extension assembly.

  • Testing the extension.

Prerequisites

You need the following components on the development computer to complete this walkthrough:

Knowledge of the following concepts is helpful, but not required, to complete the walkthrough:

Creating the Projects

To complete this walkthrough, you need to create two projects:

  • A VSIX project to create the VSIX package to deploy the project item extension.

  • A class library project that implements the project item extension.

Start the walkthrough by creating the projects.

To create the VSIX project

  1. Start Visual Studio.

  2. On the File menu, point to New, and then click Project.

  3. In the New Project dialog box, expand the Visual C# or Visual Basic nodes, and then click the Extensibility node.

    Note

    The Extensibility node is available only if you install the Visual Studio 2010 SDK. For more information, see the prerequisites section above.

  4. In the combo box at the top of the dialog box, select .NET Framework 4. SharePoint tools extensions require features in this version of the .NET Framework.

  5. Click the VSIX Project template.

  6. In the Name box, type GenerateExternalDataLists.

  7. Click OK.

    Visual Studio adds the GenerateExternalDataLists project to Solution Explorer.

To create the extension project

  1. In Solution Explorer, right-click the solution node, click Add, and then click New Project.

    Note

    In Visual Basic projects, the solution node appears in Solution Explorer only when the Always show solution check box is selected in the General, Projects and Solutions, Options Dialog Box.

  2. In the New Project dialog box, expand the Visual C# or Visual Basic nodes, and then click Windows.

  3. In the combo box at the top of the dialog box, select .NET Framework 4.

  4. Select the Class Library project template.

  5. In the Name box, type BdcProjectItemExtension.

  6. Click OK.

    Visual Studio adds the BdcProjectItemExtension project to the solution and opens the default Class1 code file.

  7. Delete the Class1 code file from the project.

Configuring the Extension Project

Before you write code to create the project item extension, add code files and assembly references to the extension project.

To configure the project

  1. In the BdcProjectItemExtension project, add two code files that have the following names:

    • ProjectItemExtension

    • GenerateExternalDataLists

  2. On the Project menu, click Add Reference.

  3. On the .NET tab, press CTRL and click the following assemblies, and then click OK:

    • Microsoft.VisualStudio.SharePoint

    • System.ComponentModel.Composition

    • WindowsBase

Defining the Project Item Extension

Create a class that defines the extension for the Business Data Connectivity Model project item. To define the extension, the class implements the ISharePointProjectItemTypeExtension interface. Implement this interface whenever you want to extend an existing type of project item.

To define the project item extension

  1. Double-click the ProjectItemExtension code file.

  2. Paste the following code into the file.

    Note

    After adding this code, the project will have some compile errors. These errors will go away when you add code in later steps.

    Imports Microsoft.VisualStudio.SharePoint
    Imports System.ComponentModel.Composition
    
    Namespace Contoso.SharePointProjectItemExtensions.GenerateExternalDataLists
    
        ' Export attribute: Enables Visual Studio to discover and load this extension.
        ' SharePointProjectItemType attribute: Specifies the ID of the project item to extend.
        ' GenerateExternalDataListsExtension class: Defines the extension for the BDC project item.
        '     The other part of the partial class contains the logic for generating the external data lists. 
        <Export(GetType(ISharePointProjectItemTypeExtension))> _
        <SharePointProjectItemType("Microsoft.VisualStudio.SharePoint.BusinessDataConnectivity")> _
        Partial Friend Class GenerateExternalDataListsExtension
            Implements ISharePointProjectItemTypeExtension
    
            ' Creates the new shortcut menu item that the user clicks to generate the external data lists.
            Private Sub Initialize(ByVal SharePointProjectItemType As ISharePointProjectItemType) _
                Implements ISharePointProjectItemTypeExtension.Initialize
                AddHandler SharePointProjectItemType.ProjectItemMenuItemsRequested,
                    AddressOf SharePointProjectItemMenuItemsRequested
            End Sub
    
            Private Sub SharePointProjectItemMenuItemsRequested(ByVal Sender As Object, _
                ByVal e As SharePointProjectItemMenuItemsRequestedEventArgs)
                Dim generateListMenuItem As IMenuItem = e.ViewMenuItems.Add("Generate External Data List")
                AddHandler generateListMenuItem.Click, AddressOf GenerateExternalDataLists_Execute
            End Sub
        End Class
    End Namespace
    
    using Microsoft.VisualStudio.SharePoint;
    using System.ComponentModel.Composition;
    
    namespace Contoso.SharePointProjectItemExtensions.GenerateExternalDataLists
    {
        // Enables Visual Studio to discover and load this extension.
        [Export(typeof(ISharePointProjectItemTypeExtension))]
    
        // Specifies the ID of the project item to extend.
        [SharePointProjectItemType("Microsoft.VisualStudio.SharePoint.BusinessDataConnectivity")]
    
        // Defines the extension for the BDC project item. The other part of the partial class contains
        // the logic for generating the external data lists. 
        internal partial class GenerateExternalDataListsExtension : ISharePointProjectItemTypeExtension
        {
            // Implements IProjectItemTypeExtension.Initialize. Creates the new shortcut menu item that
            // the user clicks to generate the external data lists.
            public void Initialize(ISharePointProjectItemType projectItemType)
            {
                projectItemType.ProjectItemMenuItemsRequested += ProjectItemMenuItemsRequested;
            }
    
            private void ProjectItemMenuItemsRequested(object sender, SharePointProjectItemMenuItemsRequestedEventArgs e)
            {
                e.ViewMenuItems.Add("Generate External Data List").Click += GenerateExternalDataLists_Execute;
            }
        }
    }
    

Creating the External Data Lists

Add a partial definition of the GenerateExternalDataListsExtension class that creates an external data list for each entity in the BDC model. To create the external data list, this code first reads the entity data in the BDC model by parsing the XML data in the BDC model file. Then, it creates a list instance that is based on the BDC model and adds this list instance to the project.

To create the external data lists

  1. Double-click the GenerateExternalDataLists code file.

  2. Paste the following code into the file.

    Imports Microsoft.VisualStudio.SharePoint
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    Imports System.IO
    Imports System.Linq
    Imports System.Text
    Imports System.Xml.Linq
    
    Namespace Contoso.SharePointProjectItemExtensions.GenerateExternalDataLists
    
        ' Creates the external data lists for the BDC item. The other part of the partial class 
        ' defines the BDC project item extension.
        Partial Friend Class GenerateExternalDataListsExtension
    
            Private Const ModelFileNameString As String = "ModelFileName"
            Private Const EXTENSION_BDCM As String = ".bdcm"
            Private Const NamespaceString As String = "http://schemas.microsoft.com/windows/2007/BusinessDataCatalog"
            Private Shared ReadOnly BdcNamespace As XNamespace = XNamespace.Get(NamespaceString)
    
            ' Generates an external data list for each Entity in the BDC model. This event handler is called
            ' when the developer clicks the shortcut menu item that the extension adds to the BDC project item.
            Private Sub GenerateExternalDataLists_Execute(ByVal Sender As Object, ByVal e As MenuItemEventArgs)
    
                Dim projectItem As ISharePointProjectItem = CType(e.Owner, ISharePointProjectItem)
                Dim bdcmFile As ISharePointProjectItemFile = GetModelFile(projectItem)
    
                Dim doc As XDocument = XDocument.Load(bdcmFile.FullPath)
                Dim skippedEntities As List(Of XElement) = New List(Of XElement)()
    
                ' Try to generate an external data list for each entity defined in the BDC model file.
                For Each entity As XElement In doc.Root.Elements(BdcNamespace + "LobSystems").Elements( _
                    BdcNamespace + "LobSystem").Elements(BdcNamespace + "Entities").Elements(BdcNamespace + "Entity")
    
                    If False = GenerateExternalDataList(projectItem, entity) Then
                        skippedEntities.Add(entity)
                    End If
                Next
    
                ' Report skipped entities.
                If skippedEntities.Count <> 0 Then
                    Dim entityNameList As StringBuilder = Nothing
                    skippedEntities.ForEach(Function(entity As XElement)
                                                If (entityNameList Is Nothing) Then
                                                    entityNameList = New StringBuilder()
                                                Else
                                                    entityNameList.AppendLine(",")
                                                End If
                                                entityNameList.Append(entity.Attribute("Name").Value)
                                            End Function)
    
                    Dim message As String = String.Format("The following Entities were skipped because " &
                        "either a LobSystemInstance, SpecificFinder, or Finder was not found for them. \r\n{0}", _
                        entityNameList)
                    projectItem.Project.ProjectService.Logger.WriteLine(message, LogCategory.Warning)
                End If
            End Sub
    
            ' Gets the ISharePointProjectItemFile object for the BDC model file.
            Private Function GetModelFile(ByVal projectItem As ISharePointProjectItem) As ISharePointProjectItemFile
    
                Dim modelFileName As String = Nothing
                If projectItem.FeatureProperties.TryGetValue(ModelFileNameString, modelFileName) Then
                    modelFileName = Path.GetFileName(modelFileName)
                    Return (From file In projectItem.Files _
                            Where String.Compare(file.Name, modelFileName, StringComparison.OrdinalIgnoreCase) = 0 _
                            Select file).FirstOrDefault()
                Else
                    ' If we can't find the ModelFileName through the FeatureProperties, 
                    ' get the first file that has a '.bdcm' extension
                    Return (From file In projectItem.Files _
                            Where file.Name.EndsWith(EXTENSION_BDCM, StringComparison.OrdinalIgnoreCase) _
                            Select file).FirstOrDefault()
                End If
            End Function
    
            ' Boilerplate XML for the new list instance that is based on the BDC model.
            Private Const externalDataListContent As String = _
                "<?xml version=""1.0"" encoding=""utf-8""?>" & vbCrLf & _
                "        <Elements http://schemas.microsoft.com/sharepoint/"">" & vbCrLf & _
                "          <ListInstance Title=""$EntityName$DataList""" & vbCrLf & _
                "                        OnQuickLaunch=""TRUE""" & vbCrLf & _
                "                        TemplateType=""104""" & vbCrLf & _
                "                        FeatureId=""$SharePoint.Feature.Id$""" & vbCrLf & _
                "                        Url=""Lists/$EntityName$DataList""" & vbCrLf & _
                "                        Description=""Default List for $EntityName$."">" & vbCrLf & _
                "            <DataSource>" & vbCrLf & _
                "              <Property Name=""LobSystemInstance"" Value=""$LobSystemInstance$"" />" & vbCrLf & _
                "              <Property Name=""EntityNamespace"" Value=""$EntityNamespace$"" />" & vbCrLf & _
                "              <Property Name=""Entity"" Value=""$EntityName$"" />" & vbCrLf & _
                "              <Property Name=""SpecificFinder"" Value=""$SpecificFinder$"" />" & vbCrLf & _
                "              <Property Name=""Finder"" Value=""$Finder$"" />" & vbCrLf & _
                "            </DataSource>" & vbCrLf & _
                "          </ListInstance>" & vbCrLf & _
                "        </Elements>"
    
            ' Tries to generate an external data list for the specified BDC model project item and entity.
            Private Function GenerateExternalDataList(ByVal projectItem As ISharePointProjectItem, ByVal entity As XElement) As Boolean
    
                Dim lobSystemInstanceName As String = GetLobSystemInstanceName(entity)
                Dim specificFinderName As String = GetSpecificFinderName(entity)
                Dim finderName As String = GetFinderName(entity)
                Dim entityName As String = entity.Attribute("Name").Value
    
                If String.IsNullOrEmpty(lobSystemInstanceName) Or String.IsNullOrEmpty(specificFinderName) Or _
                    String.IsNullOrEmpty(finderName) Then
                    Return False
                End If
    
                Dim newExternalDataListName As String = entityName & "DataList"
                Dim existingProjectItem As ISharePointProjectItem = (From existingItem As ISharePointProjectItem In projectItem.Project.ProjectItems
                                                    Where existingItem.Name = newExternalDataListName
                                                    Select existingItem).FirstOrDefault()
    
                ' Add a new list instance and populate it with data from the BDC model.
                If existingProjectItem Is Nothing Then
                    Dim newExternalDataList As ISharePointProjectItem = projectItem.Project.ProjectItems.Add(newExternalDataListName, _
                        "Microsoft.VisualStudio.SharePoint.ListInstance")
    
                    Dim newExternalDataListString As String = externalDataListContent
                    newExternalDataListString = newExternalDataListString.Replace("$EntityName$", entityName)
                    newExternalDataListString = newExternalDataListString.Replace("$LobSystemInstance$", lobSystemInstanceName)
                    newExternalDataListString = newExternalDataListString.Replace("$EntityNamespace$", entity.Attribute("Namespace").Value)
                    newExternalDataListString = newExternalDataListString.Replace("$SpecificFinder$", specificFinderName)
                    newExternalDataListString = newExternalDataListString.Replace("$Finder$", finderName)
    
                    Dim elementsXmlPath As String = Path.Combine(newExternalDataList.FullPath, "Elements.xml")
                    File.WriteAllText(elementsXmlPath, newExternalDataListString)
                    Dim elementsFile As ISharePointProjectItemFile = newExternalDataList.Files.AddFromFile(elementsXmlPath)
                    elementsFile.DeploymentType = DeploymentType.ElementManifest
                End If
    
                Return True
            End Function
    
            Private Function GetLobSystemInstanceName(ByVal entity As XElement) As String
    
                Dim lobSystemInstances As XElement = entity.Parent.Parent.Element(BdcNamespace + "LobSystemInstances")
                If lobSystemInstances IsNot Nothing Then
                    Dim lobSystemInstance As XElement = lobSystemInstances.Elements(BdcNamespace + "LobSystemInstance").FirstOrDefault()
                    If lobSystemInstance IsNot Nothing Then
                        Return lobSystemInstance.Attribute("Name").Value
                    End If
                End If
                Return Nothing
            End Function
    
            Private Function GetSpecificFinderName(ByVal entity As XElement) As String
                Return GetMethodInstance(entity, "SpecificFinder")
            End Function
    
            Private Function GetFinderName(ByVal entity As XElement) As String
                Return GetMethodInstance(entity, "Finder")
            End Function
    
            Private Function GetMethodInstance(ByVal entity As XElement, ByVal methodInstanceType As String) As String
                Dim methods As XElement = entity.Element(BdcNamespace + "Methods")
                If methods IsNot Nothing Then
                    For Each method As XElement In methods.Elements(BdcNamespace + "Method")
                        Dim methodInstances As XElement = method.Element(BdcNamespace + "MethodInstances")
                        If methodInstances IsNot Nothing Then
                            For Each methodInstance As XElement In methodInstances.Elements(BdcNamespace + "MethodInstance")
                                If methodInstance.Attribute("Type").Value = methodInstanceType Then
                                    Return methodInstance.Attribute("Name").Value
                                End If
                            Next
                        End If
                    Next
                End If
                Return Nothing
            End Function
    
        End Class
    End Namespace
    
    using Microsoft.VisualStudio.SharePoint;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    
    namespace Contoso.SharePointProjectItemExtensions.GenerateExternalDataLists
    {
        // Creates the external data lists for the BDC item. The other part of the partial class 
        // defines the BDC project item extension.
        internal partial class GenerateExternalDataListsExtension
        {
            private const string ModelFileNameString = "ModelFileName";
            private const string EXTENSION_BDCM = ".bdcm";
            private const string NamespaceString = "http://schemas.microsoft.com/windows/2007/BusinessDataCatalog";
            private static readonly XNamespace BdcNamespace = XNamespace.Get(NamespaceString);
    
            // Generates an external data list for each Entity in the BDC model. This event handler is called
            // when the developer clicks the shortcut menu item that the extension adds to the BDC project item.
            private void GenerateExternalDataLists_Execute(object sender, MenuItemEventArgs e)
            {
                ISharePointProjectItem projectItem = (ISharePointProjectItem)e.Owner;
                ISharePointProjectItemFile bdcmFile = GetModelFile(projectItem);
    
                XDocument doc = XDocument.Load(bdcmFile.FullPath);
                List<XElement> skippedEntities = new List<XElement>();
    
                // Try to generate an external data list for each entity defined in the BDC model file.
                foreach (XElement entity in doc.Root.Elements(BdcNamespace + "LobSystems").Elements(
                    BdcNamespace + "LobSystem").Elements(BdcNamespace + "Entities").Elements(BdcNamespace + "Entity"))
                {
                    if (!GenerateExternalDataList(projectItem, entity))
                    {
                        skippedEntities.Add(entity);
                    }
                }
    
                // Report skipped entities.
                if (skippedEntities.Count != 0)
                {
                    StringBuilder entityNameList = null;
                    skippedEntities.ForEach(delegate(XElement entity)
                    {
                        if (entityNameList == null)
                        {
                            entityNameList = new StringBuilder();
                        }
                        else
                        {
                            entityNameList.AppendLine(",");
                        }
                        entityNameList.Append(entity.Attribute("Name").Value);
                    });
    
                    string message = string.Format("The following Entities were skipped because either a LobSystemInstance, " +
                        "SpecificFinder, or Finder was not found for them. \r\n{0}", entityNameList);
                    projectItem.Project.ProjectService.Logger.WriteLine(message, LogCategory.Warning);
                }
            }
    
            // Gets the ISharePointProjectItemFile object for the BDC model file.
            private ISharePointProjectItemFile GetModelFile(ISharePointProjectItem projectItem)
            {
                string modelFileName;
                if (projectItem.FeatureProperties.TryGetValue(ModelFileNameString, out modelFileName))
                {
                    modelFileName = Path.GetFileName(modelFileName);
                    return (from file in projectItem.Files
                            where string.Compare(file.Name, modelFileName, StringComparison.OrdinalIgnoreCase) == 0
                            select file).FirstOrDefault();
                }
                else
                {
                    // if we can't find the ModelFileName through the FeatureProperties, 
                    // get the first file that has a '.bdcm' extension
                    return (from file in projectItem.Files
                            where file.Name.EndsWith(EXTENSION_BDCM, StringComparison.OrdinalIgnoreCase)
                            select file).FirstOrDefault();
                }
            }
    
            // Boilerplate XML for the new list instance that is based on the BDC model.
            private const string externalDataListContent =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
                <Elements http://schemas.microsoft.com/sharepoint/"">
                  <ListInstance Title=""$EntityName$DataList""
                                OnQuickLaunch=""TRUE""
                                TemplateType=""104""
                                FeatureId=""$SharePoint.Feature.Id$""
                                Url=""Lists/$EntityName$DataList""
                                Description=""Default List for $EntityName$."">
                    <DataSource>
                      <Property Name=""LobSystemInstance"" Value=""$LobSystemInstance$"" />
                      <Property Name=""EntityNamespace"" Value=""$EntityNamespace$"" />
                      <Property Name=""Entity"" Value=""$EntityName$"" />
                      <Property Name=""SpecificFinder"" Value=""$SpecificFinder$"" />
                      <Property Name=""Finder"" Value=""$Finder$"" />
                    </DataSource>
                  </ListInstance>
                </Elements>";
    
            // Tries to generate an external data list for the specified BDC model project item and entity.
            private bool GenerateExternalDataList(ISharePointProjectItem projectItem, XElement entity)
            {
                string lobSystemInstanceName = GetLobSystemInstanceName(entity);
                string specificFinderName = GetSpecificFinderName(entity);
                string finderName = GetFinderName(entity);
                string entityName = entity.Attribute("Name").Value;
    
                if (string.IsNullOrEmpty(lobSystemInstanceName) || string.IsNullOrEmpty(specificFinderName) || 
                    string.IsNullOrEmpty(finderName))
                {
                    return false;
                }
    
                string newExternalDataListName = entityName + "DataList";
                ISharePointProjectItem existingProjectItem = (from ISharePointProjectItem existingItem in projectItem.Project.ProjectItems
                                                    where existingItem.Name == newExternalDataListName
                                                    select existingItem).FirstOrDefault();
    
                // Add a new list instance and populate it with data from the BDC model.
                if (existingProjectItem == null)
                {
                    ISharePointProjectItem newExternalDataList = projectItem.Project.ProjectItems.Add(newExternalDataListName, 
                        "Microsoft.VisualStudio.SharePoint.ListInstance");
    
                    string newExternalDataListString = externalDataListContent;
                    newExternalDataListString = newExternalDataListString.Replace("$EntityName$", entityName);
                    newExternalDataListString = newExternalDataListString.Replace("$LobSystemInstance$", lobSystemInstanceName);
                    newExternalDataListString = newExternalDataListString.Replace("$EntityNamespace$", entity.Attribute("Namespace").Value);
                    newExternalDataListString = newExternalDataListString.Replace("$SpecificFinder$", specificFinderName);
                    newExternalDataListString = newExternalDataListString.Replace("$Finder$", finderName);
    
                    string elementsXmlPath = Path.Combine(newExternalDataList.FullPath, "Elements.xml");
                    File.WriteAllText(elementsXmlPath, newExternalDataListString);
                    ISharePointProjectItemFile elementsFile = newExternalDataList.Files.AddFromFile(elementsXmlPath);
                    elementsFile.DeploymentType = DeploymentType.ElementManifest;
                }
    
                return true;
            }
    
            private string GetLobSystemInstanceName(XElement entity)
            {
                XElement lobSystemInstances = entity.Parent.Parent.Element(BdcNamespace + "LobSystemInstances");
                if (lobSystemInstances != null)
                {
                    XElement lobSystemInstance = lobSystemInstances.Elements(BdcNamespace + "LobSystemInstance").FirstOrDefault();
                    if (lobSystemInstance != null)
                    {
                        return lobSystemInstance.Attribute("Name").Value;
                    }
                }
                return null;
            }
    
            private string GetSpecificFinderName(XElement entity)
            {
                return GetMethodInstance(entity, "SpecificFinder");
            }
    
            private string GetFinderName(XElement entity)
            {
                return GetMethodInstance(entity, "Finder");
            }
    
            private string GetMethodInstance(XElement entity, string methodInstanceType)
            {
                XElement methods = entity.Element(BdcNamespace + "Methods");
                if (methods != null)
                {
                    foreach (XElement method in methods.Elements(BdcNamespace + "Method"))
                    {
                        XElement methodInstances = method.Element(BdcNamespace + "MethodInstances");
                        if (methodInstances != null)
                        {
                            foreach (XElement methodInstance in methodInstances.Elements(BdcNamespace + "MethodInstance"))
                            {
                                if (methodInstance.Attribute("Type").Value == methodInstanceType)
                                {
                                    return methodInstance.Attribute("Name").Value;
                                }
                            }
                        }
                    }
                }
    
                return null;
            }
        }
    }
    

Checkpoint

At this point in the walkthrough, all the code for the project item extension is now in the project. Build the solution to make sure that the project compiles without errors.

To build the solution

  • On the Build menu, select Build Solution.

Creating a VSIX Package to Deploy the Project Item Extension

To deploy the extension, use the VSIX project in your solution to create a VSIX package. First, configure the VSIX package by modifying the source.extension.vsixmanifest file that is included in the VSIX project. Then, create the VSIX package by building the solution.

To configure and create the VSIX package

  1. In Solution Explorer, double-click the source.extension.vsixmanifest file in the GenerateExternalDataLists project.

    Visual Studio opens the file in the manifest editor. The source.extension.vsixmanifest file is the basis for the extension.vsixmanifest file is required by all VSIX packages. For more information about this file, see VSIX Extension Schema Reference.

  2. In the Product Name box, type External Data List Generator.

  3. In the Author box, type Contoso.

  4. In the Description box, type An extension for Business Data Connectivity Model project items that can be used to generate external data lists.

  5. In the Content section of the editor, click the Add Content button.

  6. In the Add Content dialog box, in the Select a content type list box, select MEF Component.

    Note

    This value corresponds to the MefComponent element in the extension.vsixmanifest file. This element specifies the name of an extension assembly in the VSIX package. For more information, see MEFComponent Element (VSX Schema).

  7. Under Select a source, click the Project radio button, and select BdcProjectItemExtension in the list box next to it.

  8. Click OK.

  9. On the Build menu, click Build Solution. Make sure that the project compiles without errors.

  10. Open the build output folder for the GenerateExternalDataLists project. Make sure that this folder now contains the GenerateExternalDataLists.vsix file.

    By default, the build output folder is the ..\bin\Debug folder under the folder that contains your project file.

Testing the Project Item Extension

You are now ready to test the project item extension. First, start debugging the extension project in the experimental instance of Visual Studio. Then, use the extension in the experimental instance of Visual Studio to generate an external list for a BDC model. Finally, open the external list on the SharePoint site to verify that it works as expected.

To start debugging the extension

  1. Restart Visual Studio with administrator privileges and open the GenerateExternalDataLists solution.

  2. In the BdcProjectItemExtension project, open the ProjectItemExtension code file and add a breakpoint to the line of code in the Initialize method.

  3. Open the GenerateExternalDataLists code file, and add a breakpoint to the first line of code in the GenerateExternalDataLists_Execute method.

  4. Press F5 to start debugging.

    Visual Studio installs the extension to %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\External Data List Generator\1.0 and starts an experimental instance of Visual Studio. You will test the project item in this instance of Visual Studio.

To test the extension

  1. In the experimental instance of Visual Studio, on the File menu, point to New, and then click Project.

  2. Expand Visual C#, expand SharePoint, and then click 2010.

  3. In the combo box at the top of the dialog box, make sure that .NET Framework 3.5 is selected. Projects for Microsoft SharePoint Server 2010 require this version of the .NET Framework.

  4. In the list of project templates, click Business Data Connectivity Model.

  5. In the Name box, type TestBDCModel.

  6. Click OK.

  7. In the SharePoint Customization Wizard, type the URL of the site that you want to use for debugging, and click Finish.

  8. Verify that the code in the other instance of Visual Studio stops on the breakpoint that you set earlier in the Initialize method. Press F5 in this instance of Visual Studio to continue to debug the project.

  9. In the experimental instance of Visual Studio, press F5 to build, deploy, and run the TestBDCModel project. The Web browser opens to the default page of the SharePoint site that is used for debugging.

  10. Verify that the Lists section in the Quick Launch area does not yet contain a list that is based on the default BDC model in the project. You must first create an external data list, either by using the SharePoint user interface or by using the project item extension.

  11. Close the Web browser.

  12. In the instance of Visual Studio that has the TestBDCModel project open, right-click the BdcModel1 node in Solution Explorer and click Generate External Data List.

  13. Verify that the code in the other instance of Visual Studio stops on the breakpoint that you set earlier in the GenerateExternalDataLists_Execute method. Press F5 to continue to debug the project.

  14. The experimental instance of Visual Studio adds a list instance named Entity1DataList to the TestBDCModel project, and it also generates a feature named Feature2 for the list instance.

  15. Press F5 to build, deploy, and run the TestBDCModel project. The Web browser opens to the default page of the SharePoint site that is used for debugging.

  16. Verify that the Lists section in the Quick Launch now contains a list that is named Entity1DataList.

  17. Click the Entity1DataList list.

  18. Verify that the list contains columns named Identifier1 and Message, and one item with the Identifier1 value of 0 and Message value of Hello World. All of this data is provided by the default BDC model that is generated by the Business Data Connectivity Model project template.

  19. Close the Web browser.

Cleaning up the Development Computer

After you finish testing the project item extension, remove the external list and BDC model from the SharePoint site and remove the project item extension from Visual Studio.

To remove the external data list from the SharePoint site

  1. In the Quick Launch area of the SharePoint site, click the Entity1DataList list.

  2. In the Ribbon on the SharePoint site, click the List tab.

  3. On the List tab, in the Settings group, click List Settings.

  4. Under Permissions and Management, click Delete this list. Click OK to confirm that you want to send the list to the recycle bin.

  5. Close the Web browser.

To remove the BDC model from the SharePoint site

  • In the experimental instance of Visual Studio, on the Build menu, click Retract.

    Visual Studio removes the BDC model from the SharePoint site.

To remove the project item extension from Visual Studio

  1. In the experimental instance of Visual Studio, on the Tools menu, click Extension Manager.

    The Extension Manager dialog box opens.

  2. In the list of extensions, click External Data List Generator, and then click Uninstall.

  3. In the dialog box that appears, click Yes to confirm that you want to uninstall the extension.

  4. Click Restart Now to complete the uninstallation.

  5. Close both instances of Visual Studio (the experimental instance and the instance of Visual Studio that has the GenerateExternalDataLists solution open).

See Also

Concepts

Extending the SharePoint Project System

Other Resources

Creating a Business Data Connectivity Model

Designing a Business Data Connectivity Model