새로운 API를 생성하기 전, 페이지 아이템 및 데이터소스 구조를 정하여야 한다. 각 컴퍼니 또는 비지니스의 컨셉, 그리고 웹사이트의 수에 따라 아이템 스트럭쳐는 다양하게 변경되어있을 수 있으므로 이번 예제에서는 어떻게 사이크코어의 사용자가 렌더링 아이템을 적용 시키고 그에 맞는 데이타소스를 손쉽게(?) 적용할수 있도록 포커스를 두었다. 이는 경우에 따라 언제든지 확장 및 수정이 가능할수 있다.
아래는 기본적으로 유저가 렌더링 아이템을 적용하고 데이타소스를 생성하여 페이지 레이아웃에 적용하는 순서이다.
- 업데이트를 하고자 하는 페이지 아이템으로 이동
- Content Editor에 원하는 경로에 컴포넌트의 데이터소스 생성한다.
- xEditor로 이동 후, 적용되어진 Placeholder에 컴포넌트를 Insert한다.
- 적용 되어진 컴포넌트의 속성을 열어, 데이터소스 아이템을 Datasource 필드에 적용을 시킨다.
아래의 API를 통하여 컴포넌트와 관련된 아이템을 페이지에 적용하는 방법이다.
- 업데이트 하고자 하는 아이템의 xEditor 오픈
- Placeholder에 원하는 컴포넌트 Insert
- 생성되어진 Input 버튼 (One-Click)을 통하여 컴포넌트의 데이터소소를 정해진 경로에 생성
필자의 방법처럼 API를 사용하여 아이템을 생성과 동시에 Layout에 데이터소스를 적용하면 Content Editor 와 xEditor의 변경 없이 손쉽게 누구나 페이지에 컴포넌트 및 그에 맞는 데이터소스를 적용시킬수가 있다. 좀 더 자세히 알아보기 위하여 필자는 아래의 샘플 소스를 작성하였다.
먼저 새로운 Route을 적용 시키고 "CreateItem" 이라는 API 액션을 생성하도록 하자.
필자는 API라는 새로운 프로젝트를 만든 후, RouteMap을 "{controller}/{action}/{id}" 으로 설정하고 CustomApiController와 Api 모델을 생성하였다. Controller에는 새로운 아이템을 생성하는 ActionResult와 페이지 아이템 하위의 데이터소스폴더 및 생성되어진 데이타소스의 키를 업데이트할수 있는 레이아웃 업데이트 Method도 같이 생성하였다.
CustomApiController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | using System.Web.Mvc; using Sitecore.Data.Items; using Sitecore.Data; using Sitecore.Globalization; using Sitecore.SecurityModel; using Sitecore.Layouts; namespace Sitecore.Custom.Component.API.Controllers { public class CustomApiController : Controller { Database masterDb = Configuration.Factory.GetDatabase("master"); Database webDb = Configuration.Factory.GetDatabase("web"); /// <summary> /// 새로운 ResourceFolder 페이지 아이템 하위에 생성한다. /// 해당 페이지 아이템과 관련된 모든 컴포넌트의 데이타소스는 /// 페이지 하위 ResourceFolder에 모두 생성된다. /// </summary> /// <param name="api">api</param> /// <param name="parentItem">ResouceFolder가 만들어진 상위의 페이지 아이템</param> /// <returns></returns> public Item CreateResourceFolder(Models.Api api, Item parentItem) { var localResourceFolder = parentItem.Database.GetItem(parentItem.Paths.FullPath + "/" + api.localResourceFolderName); using (new SecurityDisabler()) { TemplateItem template = parentItem.Database.GetTemplate("User Defined/Local Resource Folder"); if (localResourceFolder == null) { localResourceFolder = parentItem.Add(api.localResourceFolderName, template); } } return localResourceFolder; } /// <summary> /// 생성되어진 Datasource Item의 ID아이디를 페이지 레이아웃에 업데이트한다. /// </summary> /// <param name="pageItem">현재 페이지 아이템</param> /// <param name="datasourceItem">새로운 데이타소스 아이템</param> /// <param name="renderingUid">렌더링 아이템의 유니크 아이디</param> public void UpdateDatasourceKey(Item pageItem, Item datasourceItem, string renderingUid) { using (new SecurityDisabler()) { // Get the layout definitions and the device string deviceId = Context.Device.ID.ToString(); DeviceItem device = pageItem.Database.Resources.Devices[deviceId]; Data.Fields.LayoutField layoutField = new Sitecore.Data.Fields.LayoutField(pageItem.Fields[Sitecore.FieldIDs.FinalLayoutField]); LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value); DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(device.ID.ToString()); foreach (RenderingDefinition rd in deviceDefinition.Renderings) { // Update the renderings datasource value accordingly if (rd.UniqueId == "{" + renderingUid.ToUpper() + "}") { rd.Datasource = datasourceItem.ID.ToString(); // Save the layout changes pageItem.Editing.BeginEdit(); layoutField.Value = layoutDefinition.ToXml(); pageItem.Editing.EndEdit(); } } } } /// <summary> /// 새로운 아이템을 정해진 템플릿에 맞게 생성한다 /// </summary> /// <param name="itemName">새로운 아이템을 이름</param> /// <param name="id">{id}에 생성될 다이나믹 아이디</param> /// <param name="templateGuid">새로운 아이템의 템플릿 Guid</param> /// <param name="isDatasourceItem">현재 생성될 아이템이 데이타소스인지 확인 (Default: false)</param> /// <param name="renderingUid">레이아웃에 업데이트 되어진 렌더링 아이템의 유니크 아이디</param> /// <returns></returns> public ActionResult CreateItem(string itemName, string id, string templateGuid, string isDatasourceItem = "0", string renderingUid = null) { Models.Api api = new Models.Api(); using (new LanguageSwitcher("en")) { Item pageItem = masterDb.GetItem(ID.Parse(id)); // 새로운 데이타소스가 생성되었다면, 레이아웃을 업데이트한다 if (isDatasourceItem == "1") { api.item = CreateResourceFolder(api, pageItem); } api.templateItem = masterDb.GetTemplate(ID.Parse(templateGuid)); Item newDatasource = api.item.Add(itemName, api.templateItem); // 새로운 데이타소스가 생성되었다면, 레이아웃을 업데이트한다 if (isDatasourceItem == "1" && newDatasource != null) { UpdateDatasourceKey(pageItem, newDatasource, renderingUid); } } return new EmptyResult(); } } } |
Api.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using Sitecore.Data.Items; using Sitecore.Data; namespace Sitecore.Custom.Component.API.Models { public class Api { public string actionType { get; set; } public Item item { get; set; } public Database sourceDb { get; set; } public Database targetDb { get; set; } public TemplateItem templateItem { get; set; } public string localResourceFolderName { get { return "Local Resource"; } } } } |
API는 준비되었으므로 다음 포스트에서 심플한 컴포넌트를 만들어 API를 xEditor에서호출하여 보자.