Creating Group Page Programmatically Sitefinity Backend - c#

I've searched and I can't find any documentation on how to create a Group Page in the sitefinity API. I know how to create a page programmatically.
var pageDataId = Guid.NewGuid();
PageManager manager = PageManager.GetManager();
PageData pageData = null;
PageNode pageNode = null;
// Get the parent node Id
if (parentPageNodeId == Guid.Empty)
{
parentPageNodeId = SiteInitializer.CurrentFrontendRootNodeId;
}
PageNode parent = manager.GetPageNode(parentPageNodeId);
// Check whether exists
var initialPageNode = manager.GetPageNodes().Where(n => n.Id == pageId).SingleOrDefault();
if (initialPageNode != null)
{
return;
}
// Create the page
pageData = manager.CreatePageData(pageDataId);
pageData.HtmlTitle = pageName;
pageData.Title = pageName;
pageData.Description = pageName;
pageData.Culture = Thread.CurrentThread.CurrentCulture.ToString();
pageData.UiCulture = Thread.CurrentThread.CurrentUICulture.ToString();
pageNode = manager.CreatePage(parent, pageId, NodeType.Standard);
pageNode.Page = pageData;
pageNode.Name = pageName;
pageNode.Description = pageName;
pageNode.Title = pageName;
pageNode.UrlName = Regex.Replace(pageName.ToLower(), #"[^\w\-\!\$\'\(\)\=\#\d_]+", "-");
pageNode.ShowInNavigation = true;
pageNode.DateCreated = DateTime.UtcNow;
pageNode.LastModified = DateTime.UtcNow;
// Check whether home page
if (isHomePage)
{
SystemManager.CurrentContext.CurrentSite.SetHomePage(pageId);
}
manager.SaveChanges();
// Publish
var bag = new Dictionary<string, string>();
bag.Add("ContentType", typeof(PageNode).FullName);
WorkflowManager.MessageWorkflow(pageId, typeof(PageNode), null, "Publish", false, bag);
}
This creates a regular page. I've tried changing the NodeType from standard to NodeType.Group and leaving the rest of the code as is. However this throws an exception "The current page is not standard page." I've looked for pageNode properties to make the page a group page rather than a regular page but I can't find any. If anyone knows how to do this I would really appreciate it.

the exception is probably being thrown because you are attempting to create PageData for the created Group node. I believe that Group nodes do not have page data, but rather serve only to group other page nodes.
try removing the creation and assignment of the pageData to the PageGroup.Page property, and that should allow you to save the created page node.
Also if you install the sitefinity SDK there's a SampleUtilities class in the resources folder that has a lot of helper methods for creating pages, templates, etc that serves as a great reference point for working with the API.
I hope this is helpful!

This is some code that might help you:
// Define our new view
var templateIconView = new TemplateIconView { ID = TemplateIconViewControlId };
var pageManager = PageManager.GetManager();
pageManager.Provider.SuppressSecurityChecks = true;
// Get the root
var parentNode = pageManager.GetPageNode(SiteInitializer.SitefinityNodeId);
// Check whether exists
var initialPageNode = pageManager.GetPageNodes().SingleOrDefault(n => n.Id == AdditionalToolsPageId);
if (initialPageNode != null) {
pageManager.Delete(initialPageNode);
pageManager.SaveChanges();
}
var homePageNode = pageManager.GetPageNodes().SingleOrDefault(n => n.Id == HomePageId);
if (homePageNode != null) {
pageManager.Delete(homePageNode);
pageManager.SaveChanges();
}
// Create the Group Page Node
var groupPageNode = pageManager.CreatePage(parentNode, AdditionalToolsPageId, NodeType.Group);
groupPageNode.Name = "KonstruiTools";
groupPageNode.Description.SetString("Konstrui Tools", true);
groupPageNode.Title.SetString("Konstrui Tools", true);
groupPageNode.UrlName = Regex.Replace("Konstrui Tools", #"[^\w\-\!\$\'\(\)\=\#\d_]+", "-").ToLower();
groupPageNode.ShowInNavigation = true;
groupPageNode.DateCreated = DateTime.UtcNow;
groupPageNode.LastModified = DateTime.UtcNow;
pageManager.SaveChanges();
// Create the actual page PageData
var pageData = pageManager.CreatePageData(HomePageId);
pageData.HtmlTitle = "Configure Template Icons";
pageData.Title = "Configure Template Icons";
pageData.Description = "Configure Template Icons";
pageData.Culture = Thread.CurrentThread.CurrentCulture.ToString();
pageData.UiCulture = Thread.CurrentThread.CurrentUICulture.ToString();
pageData.EnableViewState = true;
pageData.EnableViewStateMac = true;
// Add our control to the page with default permissions
var control = pageManager.CreateControl<PageControl>(templateIconView, Constants.VALUE_DEFAULT_BACKEND_PLACEHOLDER);
pageManager.SetControlDefaultPermissions(control);
pageData.Controls.Add(control);
// Assign the Default Backend Template
pageData.Template = pageManager.GetTemplate(SiteInitializer.DefaultBackendTemplateId);
// Create the actual page PageNode
var pageNode = pageManager.CreatePage(groupPageNode, HomePageId, NodeType.Standard);
pageNode.Page = pageData;
pageNode.Name = "ConfigureTemplateIcons";
pageNode.Description = "Configure Template Icons";
pageNode.Title = "Configure Template Icons";
pageNode.UrlName = Regex.Replace("Configure Template Icons", #"[^\w\-\!\$\'\(\)\=\#\d_]+", "-").ToLower();
pageNode.ShowInNavigation = true;
pageNode.DateCreated = DateTime.UtcNow;
pageNode.LastModified = DateTime.UtcNow;
pageNode.RenderAsLink = true;
pageManager.SaveChanges();
// Publish
var bag = new Dictionary<string, string>();
bag.Add("ContentType", typeof(PageNode).FullName);
WorkflowManager.MessageWorkflow(HomePageId, typeof(PageNode), null, "Publish", false, bag);
pageManager.Provider.SuppressSecurityChecks = false;
This creates a grouppage inside the backend on rootlevel, wich holds another page with a control.

Here is what I ended up doing. It will create a group page under another group page which is exactly what I needed for my requirements.
var pageId = Guid.NewGuid();
PageManager manager = PageManager.GetManager();
PageNode pageNode = null;
//Find the modules section which will serve as the
//parent page.
string pageTitle = ConfigurationManager.AppSettings["ModulesSection"].ToString();
//Gets the actual Modules page.
var modulesNode = SitefinityHelper.GetPageNode(pageTitle);
if (modulesNode.Id == Guid.Empty)
{
modulesNode.Id = SiteInitializer.CurrentFrontendRootNodeId;
}
PageNode modulesPage = manager.GetPageNode(modulesNode.Id);
// Check whether exists
var initialPageNode = manager.GetPageNodes().Where(n => n.Id ==
pageId).SingleOrDefault();
if (initialPageNode != null)
{
return false;
}
//Creates the page under the Modules section as a Group Page.
pageNode = manager.CreatePage(modulesPage, pageId, NodeType.Group);
pageNode.Name = newModule.Name;
pageNode.Description = newModule.Description;
pageNode.Title = newModule.Name;
pageNode.UrlName = Regex.Replace(newModule.Name.ToLower(), #"[^\w\-\!\$\'\(\)\=\#\d_]+", "-");
pageNode.ShowInNavigation = true;
pageNode.DateCreated = DateTime.UtcNow;
pageNode.LastModified = DateTime.UtcNow;
manager.SaveChanges();e here

You can create Group page using fluent API. It's easy way given in fluent API
App.WorkWith()
.Page()
.CreateNewPageGroup()
.Do(x => x.Title = "Testpage2")
.Do(x => x.Name = "Testpage2")
.Do(x => x.UrlName = "testpage2")
.SaveChanges();

Related

How to add/update milestones in a feature using rally rest API and C#?

I am not able to add or update milestones field for the Features in the Rally. If anyone having the code available using C# to update the same, please share with me. I am searching and doing from last one week with no luck.
When I am trying to add/Update milestones in the Features. I am getting the error as "Could not read: Could not read referenced object null". My code is as follows:-
public DynamicJsonObject UpdateFeaturesbyName(string fea, string bFun)
{
//getting list of Feature.
Request feat = new Request("PortfolioItem/Feature");
feat.Query = new Query("Name", Query.Operator.Equals, fea);
QueryResult TCSResults = restApi.Query(feat);
foreach (var res in TCSResults.Results)
{
var steps = res["Milestones"];
Request tsteps = new Request(steps);
QueryResult tstepsResults = restApi.Query(tsteps);
foreach (var item in tstepsResults.Results)
{
}
if (res.Name == fea)
{
var targetFeature = TCSResults.Results.FirstOrDefault();
DynamicJsonObject toUpdate = new DynamicJsonObject();
//toUpdate["Milestones"] = "";
// CreateResult createResult = restApi.Create(steps._ref, toUpdate);
// String contentRef = steps._ref;
//String contentRef = createResult._ref;
string[] value = null;
string AccCri = string.Empty;
if (!string.IsNullOrWhiteSpace(bFun))
{
value = bFun.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
foreach (string item in value)
{
//if (string.IsNullOrWhiteSpace(AccCri))
// AccCri = item;
//else
// AccCri = AccCri + "<br/>" + item;
if (!string.IsNullOrWhiteSpace(item))
{
//Query for Milestone.
Request ms = new Request("Milestone");
ms.Fetch = new List<string>() { "Name", "ObjectID" };
ms.Query = new Query("Name", Query.Operator.Equals, item);
QueryResult msResults = restApi.Query(ms);
var targetMLResult = msResults.Results.FirstOrDefault();
long MLOID = targetMLResult["ObjectID"];
DynamicJsonObject tarML = restApi.GetByReference("Milestone", MLOID, "Name", "_ref", "DisplayColor");
DynamicJsonObject targetML = new DynamicJsonObject();
targetML["Name"] = tarML["Name"];
//targetML["_ref"] = tarML["_ref"];
targetML["_ref"] = "/milestone/" + Convert.ToString(MLOID);
targetML["DisplayColor"] = tarML["DisplayColor"];
// Grab collection of existing Milestones.
var existingMilestones = targetFeature["Milestones"];
long targetOID = targetFeature["ObjectID"];
// Milestones collection on object is expected to be a System.Collections.ArrayList.
var targetMLArray = existingMilestones;
var tagList2 = targetMLArray["_tagsNameArray"];
tagList2.Add(targetML);//
//targetMLArray.Add(targetML);
targetMLArray["_tagsNameArray"] = tagList2;
toUpdate["Milestones"] = targetMLArray;
OperationResult updateResult = restApi.Update(res._ref, toUpdate);
bool resp = updateResult.Success;
}
}
}
//toUpdate["c_AcceptanceCriteria"] = AccCri;
//OperationResult updateResult = restApi.Update(res._ref, toUpdate);
}
}
var features = TCSResults.Results.Where(p => p.Name == fea).FirstOrDefault();
var featuresref = features._ref;
return features;
}
Now that v3.1.1 of the toolkit has been released you can use the AddToCollection method to do this.
Otherwise, you can still always just update the full collection. The value should be an arraylist of objects with _ref properties.
Check out this example (which adds tasks to defects, but should be very similar to what you're doing): https://github.com/RallyCommunity/rally-dot-net-rest-apps/blob/master/UpdateTaskCollectionOnDefect/addTaskOnDefect.cs

Using C# to access Query from TFS, but unable to access some fields from Query

I am bringing in a query from TFS into an application I wrote in C#. Everything is working fine except I cannot access certain fields from the query. They don't show up. I think perhaps they are most likely custom fields added to our project. For example: The build version number... In the TFS query, the field is called ObjectVersion. But I cannot use it, it doesn't exist in my code.
This is what I have. The TFSCheckIter() method just converts the iterationpath to something that my C# program recognizes, "TFSitemIteration". The lines Commented out are the Fields that I cant access.
Uri collectionUri = new Uri("http://Server/tfs/DefaultCollection/");
NetworkCredential credential = new NetworkCredential("UserName", "Password");
TfsTeamProjectCollection teamProjectCollection = new TfsTeamProjectCollection(collectionUri, credential);
teamProjectCollection.EnsureAuthenticated();
WorkItemStore workItemStore = teamProjectCollection.GetService<WorkItemStore>();
var togProject = workItemStore.Projects.OfType<Project>().FirstOrDefault(project => project.Name == "ProjectName");
if (togProject != null)
{
var CMRAQuery = togProject.StoredQueries.OfType<StoredQuery>().FirstOrDefault(query => query.Name == "TFSBuildTasks");
if (CMRAQuery != null)
{
WorkItemCollection WrkItmLst = workItemStore.Query(CMRAQuery.QueryText.Replace("#project", "\"ProjectName\"").Replace("#me", "\"Name\""));
foreach (WorkItem TFSitem in WrkItmLst)
{
TFSitemName = TFSitem.Title;
//TFSitemVersion = TFSitem.ObjectVersion;
//TFSitemType = TFSitem.ObjectType;
TFSitemState = TFSitem.State;
TFSitemIterPath = TFSitem.IterationPath;
//TFSitemconfig = TFSitem.IncludeConfig;
//TFSitemLB = TFSitem.LoadBalancer;
//TFSitemFW = TFSitem.Framework;
TFSCheckIter();
if (TFSitemState == "D-Promote" | TFSitemState == "I-Promote")
{
label5.Text = TFSitemName;
label6.Text = TFSitemState;
label7.Text = TFSitemIteration;
label8.Text = TFSitemVersion;
}
}
}
}
Use the Fields property TFSitemVersion = TFSitem.Fields['ObjectVersion'].Value. I suggest to use the Reference Name, e.g. YourCompany.ObjectVersion.

How to search Work Order records from Netsuite using api?

I have to fetch Work Order record from NetSuite based on work order number, I can do that using a saved search but would like to do it without it, so as i do not have a to create another saved search record in production. My code is not returning any result, however the search is successful.
here is the code i am using:
TransactionSearch ts = new TransactionSearch();
TransactionSearchBasic tsb = new TransactionSearchBasic();
// work order number
SearchStringField sfTranId = new SearchStringField();
sfTranId.#operator = SearchStringFieldOperator.#is;
sfTranId.searchValue = workorder;
sfTranId.operatorSpecified = true;
// type
SearchEnumMultiSelectField sfType = new SearchEnumMultiSelectField();
sfType.#operator = SearchEnumMultiSelectFieldOperator.anyOf;
sfType.operatorSpecified = true;
sfType.searchValue = new String[] {"_workOrder"};
tsb.tranId = sfTranId;
tsb.type = sfType;
ts.basic = tsb;
tsa3.criteria = ts;
// perform the search
SearchResult res = _service.search(ts);
res.pageSizeSpecified = true;
if (res.status.isSuccess)
{
SearchRow[] searchRows = res.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
TransactionSearchRow tranRow = (TransactionSearchRow)searchRows[0];
if (tranRow.basic.internalId != null && tranRow.basic.internalId.Length > 0)
{
woResult = tranRow.basic.internalId[0].searchValue.internalId;
}
}
}
I realized my mistake, basic search returns RecordList and not SearchRowList.

How do I find out the page type of a PageNode? (Composite C1)

I want to build an ASP.NET usercontrol that shows a homepage navigation including only pages of a certain page type (which I named ContentPage).
In the database table for published pages this information is present for each page (Column PageTypeID) but I am unable to find any way to access it via the Composite API from my code.
using(var conn = new DataConnection())
{
var siteMapNav = new SitemapNavigator(conn);
var pages = siteMapNav.CurrentHomePageNode.GetPageNodes(SitemapScope.DescendantsAndCurrent);
// what now?
}
How can I access the PageType information for a page from C#?
You can use the data connection to look up the page type on IPage.PageTypeId and then combine the the result from SitemapNavigator:
using (var conn = new DataConnection())
{
Guid pageTypeIdInQuestion = Guid.Empty; // put type id here
var siteMapNav = new SitemapNavigator(conn);
var pagesOfDesiredType = conn.Get<IPage>().Where(f => f.PageTypeId == pageTypeIdInQuestion).Select(f => f.Id);
var pages = siteMapNav.CurrentHomePageNode.GetPageNodes(SitemapScope.DescendantsAndCurrent).Where(f=> pagesOfDesiredType.Contains(f.Id));
}
Consider caching the result you get here and flush it with add/update/delete events on IPage and IPageStructure.
string pageType = null;
using (var conn = new DataConnection())
{
var currentPageId = HomePageNode.Id;
var pageTypeId = conn.Get<IPage>().Where( p => p.Id == currentPageId ).Select( p => p.PageTypeId ).Single();
pageType = conn.Get<IPageType>().Where(pt => pt.Id == pageTypeId ).Select(pt => pt.Name).Single();
}

Sharepoint Out of the box Approval Workflow Approve/Reject comments issue when programmatically altering it

I have a re-usable out of the box sharepoint approval workflow 2010, and I am programmatically approve/reject workflow using the below code snippet inside infopath formcode (2010).
Hashtable ht = new Hashtable();
ht[SPBuiltInFieldId.Completed] = "TRUE";
ht["Completed"] = "TRUE";
ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
ht["PercentComplete"] = 1.0f;
ht["Status"] = "Completed";
ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString
(new CultureInfo((int)task.Web.Language, false),
Strings.WorkflowStatusCompleted, new object[0]);
if (isApprove)
{
ht[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
ht["TaskStatus"] = "Approved";
ht[SPBuiltInFieldId.Comments] = "Approved by Manager";
ht["Comments"] = "Approved by Manager";
}
else
{
XPathNavigator navigatorRejectComments
= this.MainDataSource.CreateNavigator().SelectSingleNode
(XPATH_REJECT_COMMENTS, this.NamespaceManager);
ht[SPBuiltInFieldId.WorkflowOutcome] = "Rejected";
ht["TaskStatus"] = "Rejected";
ht[SPBuiltInFieldId.Comments] = navigatorRejectComments.Value.Trim();
ht["Comments"] = navigatorRejectComments.Value.Trim();
}
ht["FormData"] = SPWorkflowStatus.Completed;
web.AllowUnsafeUpdates = true;
isApproveReject = AlterTask(task, ht, true, 5, 100);
web.AllowUnsafeUpdates = false;
Task Alter method
private static bool AlterTask(SPListItem task, Hashtable htData, bool fSynchronous, int attempts, int millisecondsTimeout)
{
if ((int)task[SPBuiltInFieldId.WorkflowVersion] != 1)
{
SPList parentList = task.ParentList.ParentWeb.Lists[new Guid(task[SPBuiltInFieldId.WorkflowListId].ToString())];
SPListItem parentItem = parentList.Items.GetItemById((int)task[SPBuiltInFieldId.WorkflowItemId]);
for (int i = 0; i < attempts; i++)
{
SPWorkflow workflow = parentItem.Workflows[new Guid(task[SPBuiltInFieldId.WorkflowInstanceID].ToString())];
if (!workflow.IsLocked)
{
task[SPBuiltInFieldId.WorkflowVersion] = 1;
task.SystemUpdate();
break;
}
if (i != attempts - 1)
Thread.Sleep(millisecondsTimeout);
}
}
return SPWorkflowTask.AlterTask(task, htData, fSynchronous);
}
This code works fine, but the comments of the task is not getting altered and it is not included in the e-mail as well. Is there anything wrong with ht["Comments"] that I use? It is not getting altered in task comments. This is SharePoint 2010 workflows and infopath form i am using is also 2010.
Anyone faced similar problem ?
If you need code only for Lists (not for DocLibs) you can use item.ModerationInformation.Status property. Like the the following example:
var url = #"http://server/Lists/ContentApList";
var web = new SPSite(url).OpenWeb();
var list = web.GetList(url);
var item = list.GetItemById(1);
item["MyCheck"] = "test23";
item.ModerationInformation.Status = SPModerationStatusType.Pending;
item.ModerationInformation.Comment = "my coment";
item.SystemUpdate();
But if you want to do it for all list types, you can use internal method UpdateInternal, with the following parameters:
static void UpdateMigrate(SPListItem item)
{
UpdateInternal(item, true, false, Guid.Empty, true, false,false, false, false, false);
}
static void CheckList5()
{
var url = #"http://server/Lists/ContentApList";
var web = new SPSite(url).OpenWeb();
var file = web.GetFile("CheckDocLib/logo.gif");
var item = file.ListItemAllFields;
item["MyComments"] = "test23ddd";
item.ModerationInformation.Status = SPModerationStatusType.Approved;
item.ModerationInformation.Comment = "my coment";
UpdateMigrate(item);
}
You can use examples from this russian blog Item ModerationInformation and SPListItem.UpdateInternal()
To add a comment to a task when you Approve/Reject it, you just need to use the line before AlterTask:
ht["ows_FieldName_Comments"] = comments;
After the task is approved you can see the comments in the Workflow History List.
You can also get all the consolidated comments from a task with:
Hashtable extProperties = SPWorkflowTask.GetExtendedPropertiesAsHashtable(currentTask);
string consolidatedComments = extProperties["FieldName_ConsolidatedComments"].ToString();
Good luck!

Categories