public string GetLatestItems(LatestItemsRequest request) { // Create a new, null Core Service Client SessionAwareCoreServiceClient client = null; try { // Creates a new core service client client = new SessionAwareCoreServiceClient("netTcp_2013"); // Gets the current user so we can impersonate them for our client string username = GetUserName(); client.Impersonate(username); // Start building up a string of html to return, including headings for the table that the html will represent. string html = "<div class=\"usingItems results\" id=\"latestItemsList\">"; html += CreateItemsHeading(); var filter = new SearchQueryData(); // TODO: Add check for valid start and end times: if (String.IsNullOrEmpty(request.startTime)) { filter.ModifiedAfter = DateTime.Now.AddDays(-1); } else { filter.ModifiedAfter = Convert.ToDateTime(request.startTime); } if (String.IsNullOrEmpty(request.endTime)) { filter.ModifiedBefore = DateTime.Now; } else { filter.ModifiedBefore = Convert.ToDateTime(request.endTime); } filter.IncludeLocationInfoColumns = true; if (!string.IsNullOrEmpty(request.pathOfContainer) && !request.pathOfContainer.Equals("(All)")) { // Assume publication field is valid publication name // TODO: Validate here string containerId = client.GetTcmUri(ConvertPathToWebdav(request.pathOfContainer), null, null); //string pubTcm = client.GetTcmUri("/webdav/" + request.publication, null, null); filter.SearchIn = new LinkToIdentifiableObjectData { IdRef = containerId }; } if (!string.IsNullOrEmpty(request.user) && !request.user.Equals("(All)")) { // TODO: Find a more efficient way of doing this than simply looking at all users. var users = client.GetSystemWideList(new UsersFilterData { BaseColumns = ListBaseColumns.IdAndTitle, IsPredefined = false }); string userId = string.Empty; foreach (var ud in users) { if (ud.Title == request.user) { userId = ud.Id; } } // If userId is not found, allow an empty string to be passed, which will trigger and error message. filter.Author = new LinkToUserData() { IdRef = userId }; } filter.ItemTypes = new[] { ItemType.Schema, ItemType.Component, ItemType.TemplateBuildingBlock, ItemType.ComponentTemplate, ItemType.PageTemplate, ItemType.Category, ItemType.Folder, ItemType.Keyword, ItemType.Page, ItemType.StructureGroup, ItemType.VirtualFolder, ItemType.Publication }; filter.BlueprintStatus = SearchBlueprintStatus.Local; var searchResults = client.GetSearchResults(filter); filter.BlueprintStatus = SearchBlueprintStatus.Localized; var searchResults2 = client.GetSearchResults(filter); // Merge the two searchResults arrays (local and localized; union goes into searchResults): int array1OriginalLength = searchResults.Length; Array.Resize <IdentifiableObjectData>(ref searchResults, array1OriginalLength + searchResults2.Length); Array.Copy(searchResults2, 0, searchResults, array1OriginalLength, searchResults2.Length); int row = 0; foreach (IdentifiableObjectData item in searchResults) { row++; string path = ""; if (item is RepositoryLocalObjectData) { path = ((RepositoryLocalObjectData)item).LocationInfo.Path; } bool outputItem = true; // If user is not empty or set to (All), then run some logic to see if items match selected user within specified time range. // This is necessary to account for scenarios where one user creates an item, but another edits it at a later time, for instance. // If no specific user is specified, DO NOT run these checks as they are expensive and not necessary in that case! // Only perform this check for Versioned Items (i.e. not folders, etc.). ////if (!string.IsNullOrEmpty(request.user) && !request.user.Equals("(All)") && (item is VersionedItemData)) ////{ //// // Set flag to false by default and set back to true if we find a match. //// outputItem = false; //// VersionsFilterData versionsFilter = new VersionsFilterData(); //// versionsFilter.IncludeRevisorDescriptionColumn = true; //// IdentifiableObjectData[] versionList = client.GetList(item.Id, versionsFilter); //// foreach (IdentifiableObjectData objectData in versionList) //// { //// var versionInfo = (FullVersionInfo)objectData.VersionInfo; //// // Check 2 things: //// // 1) that versionInfo.Revisor.Title == request.user //// // 2) that versionInfo.RevisionDate.Value is between filter.ModifiedAfter and filter2.ModifiedBefore //// // If we find a match, set outputItem to true and break the foreach loop. //// if (versionInfo.Revisor.Title == request.user) //// { //// if ((objectData.VersionInfo.RevisionDate >= filter.ModifiedAfter) && (objectData.VersionInfo.RevisionDate <= filter.ModifiedBefore)) //// { //// outputItem = true; //// break; //// } //// } //// } ////} if (outputItem) { string currItemHtml = "<div class=\"item\">"; // Some JS magic is needed here to retrieve the icon and add it to the url by string replacement. // We need to do this in JS because the core service provides no access to an item's icon. currItemHtml += "<script>var icon = $models.getItem(\"" + item.Id + "\").getInfo().Icon;</script>"; currItemHtml += "<div id=\"tempIconId" + row + "\" class=\"icon\" style=\"background-image: url(/WebUI/Editors/CME/Themes/Carbon2/icon_v7.1.0.66.627_.png?name=" + "****" + "&size=16)\">" + "" + "</div>"; currItemHtml += "<script>document.getElementById('tempIconId" + row + "').outerHTML = document.getElementById('tempIconId" + row + "').outerHTML.replace(\"****\", icon);</script>"; currItemHtml += "<div class=\"name\">" + item.Title + "</div>"; currItemHtml += "<div class=\"path\">" + path + "</div>"; currItemHtml += "<div class=\"id\">" + item.Id + "</div>"; currItemHtml += "</div>"; html += currItemHtml; } } // Close the div we opened above html += "</div>"; // Explicitly abort to ensure there are no memory leaks. client.Abort(); // Return the html we've built. return(html); } catch (Exception ex) { // Proper way of ensuring that the client gets closed... we close it in our try block above, // then in a catch block if an exception is thrown we abort it. if (client != null) { client.Abort(); } // We are rethrowing the original exception and just letting webapi handle it. throw ex; } }