Blogger

  • This email address is being protected from spambots. You need JavaScript enabled to view it.

    Recent items

Login

I've realized a custom web template based on Publishing Site Template (BaseTemplateName="CMSPUBLISHING" BaseTemplateID="39") used to create the site collection.

After the site collection creation, I had to add a Heading Link to Global Navigation. The test failed because the Navigation.TopNavigationBar object of root web was null.

As described into MSDN, the property is null when a site inherit the settings from parents, but I want to manipulate the root web that not have a parent web o.O.

After a first search, I found a solution (but this is not so clean).

{codecitation}

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPSite site = properties.Feature.Parent as SPSite;

    using (SPWeb web = site.OpenWeb("/your_web_url"))
    {
        if (web.Navigation.TopNavigationBar == null)
        {
            List<SPContentDatabase> contentdatabases = new List<SPContentDatabase>();

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SPNavigationNode node = new SPNavigationNode("", web.ServerRelativeUrl, false);

                web.AllowUnsafeUpdates = true;

                try
                {
                    SPNavigationNodeCollection navigationNodes = null;
                    navigationNodes = web.Navigation.GlobalNodes;

                    navigationNodes.AddAsFirst(node);
                }
                finally
                {
                    web.AllowUnsafeUpdates = false;
                }

                SPContentDatabase database = site.ContentDatabase;

                using (SqlConnection con = new SqlConnection(database.DatabaseConnectionString))
                {
                    con.Open();

                    using (SqlCommand command = con.CreateCommand())
                    {
                        command.CommandText = string.Format(@"UPDATE NavNodes
                        SET Url='', Eid={0}, ElementType=1, DocId=NULL
                        WHERE Eid={1}
                            and WebId='{2}'
                            and SiteId='{3}'",
                            1002,
                            node.Id,
                            web.ID.ToString(),
                            site.ID.ToString()
                        );

                        command.ExecuteNonQuery();
                    }
                }
            });
        }
    }
}

{/codecitation}

This solution, add a row into NavNodes table of Content DB with an element that have Eid=1002. This node enable to manipulate the TopNavigationBar. This solution is not supported from Microsoft, so I cannot use it into production environment.

Fortunally, exists a good solution for this problem: adding the code below into the Onet.xml file, magically the TopNavigationBar property is not null :D

<NavBars>
    <NavBar Name=”SharePoint Top Navbar” ID=”1002″ />
</NavBars>

With this settings, the system provide to initialize the navigation so I can manipulate it codebehind.

Published in SharePoint

While I was implementing an sorting code behind for the global navigation (or current), I found a defect in SharePoint 2010. The property web.Navigation.TopNavigationBar (or web.Navigation.QuickLaunch) always returns 0 items until you make a change through the UI (Site Action -> Site settings -> Navigation settings) and after that you can take action code behind and manipulate the sorting.


I needed to do it all without any interaction with the UI. To do this I had to add only the first time all nodes into the SPNavigationNodeCollection.

Show/Hidden csharp code

View source
 
 
 
//This block fixes the SharePoint defect ------------------------
var count = (from SPNavigationNode node in NavigationNodes
             where string.Compare(node.Properties["NodeType"] as string, "Area", true) == 0
             select node).Count();
 
 
if (count < pweb.GetPublishingWebs().Count)
{
    Dictionary<string, SPNavigationNode> nodeHash = new Dictionary<string, SPNavigationNode>();
    foreach (SPNavigationNode node in NavigationNodes)
        nodeHash.Add(node.Url, node);
 
    foreach (PublishingWeb subweb in pweb.GetPublishingWebs())
    {
        if (!nodeHash.ContainsKey(subweb.Url))
        {
            string relUrl = subweb.ParentPublishingWeb.Uri.MakeRelativeUri(subweb.Uri).ToString();
            SPNavigationNode nn = SPNavigationSiteMapNode.CreateSPNavigationNode(
                    subweb.Title, relUrl, NodeTypes.Area,
                    (string.Compare(navigationType,"global",true)==0 ? web.Navigation.TopNavigationBar : web.Navigation.QuickLaunch));
            nn.Update();
        }
    }
 
    web.Update();
}
 
 
 

Published in SharePoint