연습: SharePoint 프로젝트 항목 형식 확장
비즈니스 데이터 연결 모델 프로젝트 항목을 사용하여 SharePoint에서 BDC(비즈니스 데이터 연결) 서비스의 모델을 만들 수 있습니다. 기본적으로 이 프로젝트 항목을 사용하여 모델을 만들면 모델의 데이터가 사용자에게 표시되지 않습니다. 사용자가 데이터를 볼 수 있도록 하려면 SharePoint에서 외부 목록도 만들어야 합니다.
이 연습에서는 비즈니스 데이터 연결 모델 프로젝트 항목의 확장을 만듭니다. 개발자는 확장을 사용하여 BDC 모델의 데이터를 표시하는 외부 목록을 프로젝트에 만들 수 있습니다. 이 연습에서는 다음 작업을 수행합니다.
다음 두 가지 주요 작업을 수행하는 Visual Studio 확장 만들기
BDC 모델의 데이터를 표시하는 외부 목록을 생성합니다. 이 확장은 SharePoint 프로젝트 시스템의 개체 모델을 사용하여 목록을 정의하는 Elements.xml 파일을 생성합니다. 또한 BDC 모델과 함께 배포되도록 프로젝트에 파일을 추가합니다.
솔루션 탐색기에서 비즈니스 데이터 연결 모델 프로젝트 항목에 대한 바로 가기 메뉴 항목을 추가합니다. 개발자는 이 메뉴 항목을 클릭하여 BDC 모델에 대한 외부 목록을 생성할 수 있습니다.
확장 어셈블리를 배포하기 위한 VSIX(Visual Studio Extension) 패키지 빌드
확장 테스트
사전 요구 사항
이 연습을 완료하려면 개발 컴퓨터에 다음 구성 요소가 필요합니다.
지원되는 Microsoft Windows, SharePoint 및 Visual Studio 버전. 자세한 내용은 SharePoint 솔루션 개발 요구 사항을 참조하십시오.
Visual Studio 2010 SDK 이 연습에서는 SDK의 VSIX 프로젝트 템플릿을 사용하여 프로젝트 항목을 배포하기 위한 VSIX 패키지를 만듭니다. 자세한 내용은 Visual Studio에서 SharePoint 도구 확장을 참조하십시오.
다음 개념을 알고 있으면 연습을 완료하는 데 도움이 되지만 반드시 필요하지는 않습니다.
Microsoft SharePoint Server 2010의 BDC 서비스. 자세한 내용은 BDC Architecture를 참조하십시오.
BDC 모델의 XML 스키마. 자세한 내용은 BDC Model Infrastructure를 참조하십시오.
프로젝트 만들기
이 연습을 완료하려면 두 프로젝트를 만들어야 합니다.
VSIX 패키지를 만들어 프로젝트 항목 확장을 배포하기 위한 VSIX 프로젝트
프로젝트 항목 확장을 구현하는 클래스 라이브러리 프로젝트
먼저 프로젝트를 만들어 연습을 시작합니다.
VSIX 프로젝트를 만들려면
Visual Studio를 시작합니다.
파일 메뉴에서 새로 만들기를 가리킨 다음 프로젝트를 클릭합니다.
새 프로젝트 대화 상자에서 Visual C# 또는 Visual Basic 노드를 확장한 다음 확장성 노드를 클릭합니다.
참고
확장성 노드는 Visual Studio 2010 SDK를 설치한 경우에만 사용할 수 있습니다. 자세한 내용은 위의 필수 구성 요소 단원을 참조하십시오.
대화 상자 맨 위의 콤보 상자에서 .NET Framework 4를 선택합니다. SharePoint 도구 확장을 사용하려면 이 .NET Framework 버전의 기능이 필요합니다.
VSIX 프로젝트 템플릿을 클릭합니다.
이름 상자에 GenerateExternalDataLists를 입력합니다.
확인을 클릭합니다.
Visual Studio에서 솔루션 탐색기에 GenerateExternalDataLists 프로젝트를 추가합니다.
확장 프로젝트를 만들려면
솔루션 탐색기에서 솔루션 노드를 마우스 오른쪽 단추로 클릭한 다음 추가, 새 프로젝트를 차례로 클릭합니다.
참고
Visual Basic 프로젝트에서는 옵션 대화 상자, 프로젝트 및 솔루션, 일반에서 솔루션 항상 표시 확인란을 선택한 경우에만 솔루션 탐색기에 솔루션 노드가 표시됩니다.
새 프로젝트 대화 상자에서 Visual C# 또는 Visual Basic 노드를 확장하고 Windows를 클릭합니다.
대화 상자 맨 위의 콤보 상자에서 .NET Framework 4를 선택합니다.
클래스 라이브러리 프로젝트 템플릿을 선택합니다.
이름 상자에 BdcProjectItemExtension을 입력합니다.
확인을 클릭합니다.
Visual Studio에서 솔루션에 BdcProjectItemExtension 프로젝트를 추가하고 기본 Class1 코드 파일을 엽니다.
프로젝트에서 Class1 코드 파일을 삭제합니다.
확장 프로젝트 구성
프로젝트 항목 확장을 만드는 코드를 작성하기 전에 코드 파일과 어셈블리 참조를 확장 프로젝트에 추가합니다.
프로젝트를 구성하려면
BdcProjectItemExtension 프로젝트에서 다음과 같이 이름이 지정된 코드 파일 두 개를 추가합니다.
ProjectItemExtension
GenerateExternalDataLists
프로젝트 메뉴에서 참조 추가를 클릭합니다.
.NET 탭에서 Ctrl 키를 누르고 다음 어셈블리를 클릭한 다음 확인을 클릭합니다.
Microsoft.VisualStudio.SharePoint
System.ComponentModel.Composition
WindowsBase
프로젝트 항목 확장 정의
비즈니스 데이터 연결 모델 프로젝트 항목의 확장을 정의하는 클래스를 만듭니다. 확장을 정의하기 위해 클래스에서 ISharePointProjectItemTypeExtension 인터페이스를 구현합니다. 기존 프로젝트 항목 형식을 확장하려는 경우 이 인터페이스를 구현합니다.
프로젝트 항목 확장을 정의하려면
ProjectItemExtension 코드 파일을 두 번 클릭합니다.
파일에 다음 코드를 붙여 넣습니다.
참고
이 코드를 추가하면 프로젝트에서 컴파일 오류가 발생합니다. 이러한 오류는 이후 단계에서 코드를 추가하면 사라집니다.
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; } } }
외부 데이터 목록 만들기
BDC 모델의 각 엔터티에 대해 외부 데이터 목록을 만드는 GenerateExternalDataListsExtension 클래스의 부분 정의를 추가합니다. 외부 데이터 목록을 만들기 위해 이 코드에서는 먼저 BDC 모델 파일의 XML 데이터를 구문 분석하여 BDC 모델의 엔터티 데이터를 읽습니다. 그런 다음 BDC 모델을 기반으로 하여 목록 인스턴스를 만들고 프로젝트에 이 목록 인스턴스를 추가합니다.
외부 데이터 목록을 만들려면
GenerateExternalDataLists 코드 파일을 두 번 클릭합니다.
파일에 다음 코드를 붙여 넣습니다.
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 = "https://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 https://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 = "https://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 https://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; } } }
검사점
이 연습의 이전 단계를 통해 프로젝트 항목 확장을 위한 모든 코드가 프로젝트에 포함되었습니다. 솔루션을 빌드하여 프로젝트가 오류 없이 컴파일되는지 확인합니다.
솔루션을 빌드하려면
- 빌드 메뉴에서 솔루션 빌드를 선택합니다.
프로젝트 항목 확장을 배포하기 위한 VSIX 패키지 만들기
확장을 배포하려면 솔루션에서 VSIX 프로젝트를 사용하여 VSIX 패키지를 만듭니다. 먼저 VSIX 프로젝트에 포함된 source.extension.vsixmanifest 파일을 수정하여 VSIX 패키지를 구성합니다. 그런 다음 솔루션을 빌드하여 VSIX 패키지를 만듭니다.
VSIX 패키지를 구성하고 만들려면
솔루션 탐색기에서 GenerateExternalDataLists 프로젝트의 source.extension.vsixmanifest 파일을 두 번 클릭합니다.
매니페스트 편집기에서 파일이 열립니다. source.extension.vsixmanifest 파일은 모든 VSIX 패키지에 필요한 extension.vsixmanifest 파일의 기초를 제공합니다. 이 파일에 대한 자세한 내용은 VSIX Extension Schema Reference를 참조하십시오.
제품 이름 상자에 External Data List Generator를 입력합니다.
만든 이 상자에 Contoso를 입력합니다.
설명 상자에 외부 데이터 목록을 생성하는 데 사용할 수 있는 비즈니스 데이터 연결 모델 프로젝트 항목의 확장을 입력합니다.
편집기의 콘텐츠 섹션에서 콘텐츠 추가 단추를 클릭합니다.
콘텐츠 추가 대화 상자의 콘텐츠 형식 선택 목록 상자에서 MEF Component를 선택합니다.
참고
이 값은 extension.vsixmanifest 파일의 MefComponent 요소에 해당합니다. 이 요소는 VSIX 패키지의 확장 어셈블리 이름을 지정합니다. 자세한 내용은 MEFComponent Element (VSX Schema)를 참조하십시오.
소스 선택에서 프로젝트 라디오 단추를 클릭하고 그 옆에 있는 목록 상자에서 BdcProjectItemExtension을 선택합니다.
확인을 클릭합니다.
빌드 메뉴에서 솔루션 빌드를 클릭합니다. 프로젝트가 오류 없이 컴파일되는지 확인합니다.
GenerateExternalDataLists 프로젝트의 빌드 출력 폴더를 엽니다. 이제 이 폴더에 GenerateExternalDataLists.vsix 파일이 들어 있습니다.
기본적으로 빌드 출력 경로는 프로젝트 파일이 포함된 폴더 아래에 있는 .. \bin\Debug 폴더입니다.
프로젝트 항목 확장 테스트
이제 프로젝트 항목 확장을 테스트할 준비가 되었습니다. 우선 실험 모드의 Visual Studio 인스턴스에서 확장 프로젝트 디버깅을 시작합니다. 그런 다음 실험 모드의 Visual Studio 인스턴스에서 확장을 사용하여 BDC 모델에 대한 외부 목록을 생성합니다. 마지막으로, SharePoint 사이트에서 외부 목록을 열어 예상대로 작동하는지 확인합니다.
확장 디버깅을 시작하려면
관리자 권한으로 Visual Studio를 다시 시작하고 GenerateExternalDataLists 솔루션을 엽니다.
BdcProjectItemExtension 프로젝트에서 ProjectItemExtension 코드 파일을 열고 Initialize 메서드의 코드 줄에 중단점을 추가합니다.
GenerateExternalDataLists 코드 파일을 열고 GenerateExternalDataLists_Execute 메서드의 코드 첫째 줄에 중단점을 추가합니다.
F5 키를 눌러 디버깅을 시작합니다.
Visual Studio에서는 확장을 %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\External Data List Generator\1.0에 설치하고 실험 모드의 Visual Studio 인스턴스를 시작합니다. 이 Visual Studio 인스턴스에서 프로젝트 항목을 테스트합니다.
확장을 테스트하려면
실험 모드의 Visual Studio 인스턴스에서 파일 메뉴의 새로 만들기를 가리킨 다음 프로젝트를 클릭합니다.
Visual C#, SharePoint를 차례로 확장하고 2010을 클릭합니다.
대화 상자 맨 위의 콤보 상자에서 .NET Framework 3.5가 선택되어 있는지 확인합니다. Microsoft SharePoint Server 2010용 프로젝트에는 이 .NET Framework 버전이 필요합니다.
프로젝트 템플릿 목록에서 비즈니스 데이터 연결 모델을 클릭합니다.
이름 상자에 TestBDCModel을 입력합니다.
확인을 클릭합니다.
SharePoint 사용자 지정 마법사에서 디버깅에 사용할 사이트의 URL을 입력하고 마침을 클릭합니다.
다른 Visual Studio 인스턴스의 코드가 이전에 Initialize 메서드에 설정한 중단점에서 중지하는지 확인합니다. 이 Visual Studio 인스턴스에서 F5 키를 눌러 프로젝트 디버깅을 계속 진행합니다.
실험 모드의 Visual Studio 인스턴스에서 F5 키를 눌러 TestBDCModel 프로젝트를 빌드, 배포 및 실행합니다. 디버깅에 사용되는 SharePoint 사이트의 기본 페이지가 웹 브라우저에서 열립니다.
빠른 실행 영역의 목록 섹션에 프로젝트의 기본 BDC 모델을 기반으로 하는 목록이 아직 포함되지 않은 것을 확인합니다. 먼저 SharePoint 사용자 인터페이스를 사용하거나 프로젝트 항목 확장을 사용하여 외부 데이터 목록을 만들어야 합니다.
웹 브라우저를 닫습니다.
TestBDCModel 프로젝트가 열려 있는 Visual Studio 인스턴스에서 솔루션 탐색기의 BdcModel1 노드를 마우스 오른쪽 단추로 클릭하고 외부 데이터 목록 생성을 클릭합니다.
다른 Visual Studio 인스턴스의 코드가 이전에 GenerateExternalDataLists_Execute 메서드에 설정한 중단점에서 중지하는지 확인합니다. F5 키를 눌러 프로젝트를 계속 디버깅합니다.
실험 모드의 Visual Studio 인스턴스에서 Entity1DataList라는 목록 인스턴스가 TestBDCModel 프로젝트에 추가되고 목록 인스턴스에 대한 Feature2라는 기능도 생성됩니다.
F5 키를 눌러 TestBDCModel 프로젝트를 빌드, 배포 및 실행합니다. 디버깅에 사용되는 SharePoint 사이트의 기본 페이지가 웹 브라우저에서 열립니다.
이제 빠른 실행 영역의 목록 섹션에 Entity1DataList라는 목록이 포함된 것을 확인합니다.
Entity1DataList 목록을 클릭합니다.
목록에 Identifier1 및 Message 열이 있고, Identifier1 값이 0이고 Message 값이 Hello World인 하나의 항목이 포함된 것을 확인합니다. 이 데이터는 모두 비즈니스 데이터 연결 모델 프로젝트 템플릿에 의해 생성된 기본 BDC 모델에서 제공됩니다.
웹 브라우저를 닫습니다.
개발 컴퓨터 정리
프로젝트 항목 확장의 테스트를 마쳤으면 SharePoint 사이트에서 외부 목록과 BDC 모델을 제거하고 Visual Studio에서 프로젝트 항목 확장을 제거합니다.
SharePoint 사이트에서 외부 데이터 목록을 제거하려면
SharePoint 사이트의 빠른 실행 영역에서 Entity1DataList 목록을 클릭합니다.
SharePoint 사이트의 리본 메뉴에서 목록 탭을 클릭합니다.
목록 탭의 설정 그룹에서 목록 설정을 클릭합니다.
사용 권한 및 관리에서 이 목록 삭제를 클릭합니다. 확인을 클릭하여 목록을 휴지통으로 보냅니다.
웹 브라우저를 닫습니다.
SharePoint 사이트에서 BDC 모델을 제거하려면
실험 모드의 Visual Studio 인스턴스에서 빌드 메뉴의 제거를 클릭합니다.
Visual Studio를 통해 SharePoint 사이트에서 BDC 모델이 제거됩니다.
Visual Studio에서 프로젝트 항목 확장을 제거하려면
실험 모드의 Visual Studio 인스턴스에서 도구 메뉴의 확장 관리자를 클릭합니다.
확장 관리자 대화 상자가 열립니다.
확장 목록에서 External Data List Generator을 클릭한 다음 제거를 클릭합니다.
나타나는 대화 상자에서 예를 클릭하여 확장을 제거합니다.
지금 다시 시작을 클릭하여 제거를 완료합니다.
Visual Studio의 두 인스턴스, 즉 실험 모드의 인스턴스와 GenerateExternalDataLists 솔루션이 열려 있는 Visual Studio 인스턴스를 모두 닫습니다.