Sean Carter

Ramblings about SharePoint, C# and ASP.NET

C# – determine SharePoint authentication mode

leave a comment »

if (SPContext.Current.Site.WebApplication.IisSettings[SPContext.Current.Site.Zone].AuthenticationMode == System.Web.Configuration.AuthenticationMode.Forms) 
{ 
//run if forms authenticated
}

Written by Sean Carter

June 9, 2015 at 12:25 pm

Posted in Uncategorized

Build SharePoint XML Site Map using PortalSiteMapProvider

leave a comment »

Using Linq to XML…code is for a Console app so could be run as scheduled console job (could also implement within a SharePoint Timer Job). Uses list of rules to exclude specific content types and locations. Need references to:

  • Microsoft.SharePoint.dll
  • Microsoft.SharePoint.Publishing.dll
  • System.Xml.Linq.dll
  • System.Web.dll
using System;
using System.IO;
using System.Web;
using System.Data;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.Navigation;
using System.Xml.Linq;
using Microsoft.SharePoint.Utilities;
using System.Text.RegularExpressions;
 
namespace GenerateSiteMap
{
    class Program
    {
        static string[] excludeContentTypes = { "Redirect Page", "Web Part Page" };

        static void Main(string[] args)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(args[0])) //rootWeb or sub site
                    {
                        DoVisualSiteMap(site);
                    }
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
 
        public static void DoVisualSiteMap(SPSite site)
        {
            using (SPWeb rootWeb = site.OpenWeb())
            {
                PortalSiteMapProvider ps = PortalSiteMapProvider.WebSiteMapProvider;
                if (HttpContext.Current == null)
                {
                    HttpRequest request = new HttpRequest("", rootWeb.Url, "");
                    HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
                    HttpContext.Current.Items["HttpHandlerSPWeb"] = rootWeb;
                }
 
                //Build hierarchical sitemap using recursion
                bool exclusionsListExists = false;
                foreach (SPList list in rootWeb.Lists)
                {
                    if (list.Title == "Site Map Exclusions") //List exists so see if there are any exclusions....if so process them...
                    {
                        exclusionsListExists = true;
                        SiteMapNode startNode = ps.CurrentNode;
                        XDocument doc = new XDocument();

                        XElement siteMapRoot = new XElement("div",
                             new XAttribute("class", "site-map-container")
                         );

                        //Add root list and list item outside of recursion
                        XElement rootList = new XElement("ul");
                        siteMapRoot.Add(rootList);
                        XElement rootListItem = new XElement("li");
                        rootList.Add(rootListItem);
                        rootListItem.Add(new XElement("a", startNode.Title,
                                                    new XAttribute("href", startNode.Url)));
                        doc.Add(siteMapRoot);

                        GetNavigationRecursive(site, list, startNode, ref rootListItem);
                        Console.WriteLine("Finished processing site map, now uploading...");
                        //Upload to Site Collection Documents
                        UploadSiteMapToSiteCollectionDocuments(rootWeb, doc.ToString());
                        Console.WriteLine("Completed Upload of site map to Site Collection Documents");
                    }
                }
                if (!exclusionsListExists)
                {
                    Console.WriteLine("Exclusion list 'Site Map Exclusions' not found");
                }

            }
 
        }

        private static void GetNavigationRecursive(SPSite site, SPList exclusionList, SiteMapNode pageNode, ref XElement currentNode)
        {
            if (pageNode.ChildNodes.Count > 0)
            {
                XElement list = new XElement("ul");
                currentNode.Add(list);
                foreach (SiteMapNode node in pageNode.ChildNodes)
                {
                    string [] pathParts = Regex.Split(node.Url, @"/Pages");
                    
                    if (pathParts.Length == 2)
                    {
                        bool includeItemInSiteMap = true; //optimistic
                        try
                        {
                            using (SPWeb web = site.OpenWeb(pathParts[0]))
                            {
                                SPListItem currentItem = web.GetListItem(node.Url);
                                foreach (string contentTypeToExlude in excludeContentTypes)
                                {
                                    if (currentItem != null && currentItem.ContentType.Name == contentTypeToExlude)
                                    {
                                        includeItemInSiteMap = false;
                                        Console.WriteLine(string.Format("Excluded page: {0} with Content Type: {1} from for sitemap for site : {2}", node.Url, currentItem.ContentType.Name, pathParts[0]));
                                        break;
                                    }
                                }

                            }

                            if (includeItemInSiteMap) //don't neeed to check again of already excluded
                            {
                                foreach (SPListItem exclusionListItem in exclusionList.Items)
                                {
                                    string itemUrl = string.Format("{0}/{1}", site.Url, node.Url).ToLower();

                                    if (itemUrl.Contains(exclusionListItem["Title"].ToString().ToLower()))
                                    {
                                        includeItemInSiteMap = false;
                                        Console.WriteLine(string.Format("Excluded page: {0} with exclusion rule: {1} from for sitemap for site : {2}", node.Url, exclusionListItem["Title"].ToString().ToLower(), pathParts[0]));
                                        break;
                                    }
                                }
                            }

                            if (includeItemInSiteMap) //only include if not excluded by content type / url patterm match rule
                            {
                                XElement listItem = new XElement("li");
                                listItem.Add(new XElement("a", node.Title,
                                                new XAttribute("href", node.Url)));

                                list.Add(listItem);
                                if (node.ChildNodes.Count > 0)
                                {
                                    GetNavigationRecursive(site, exclusionList, node, ref listItem);
                                }
                            }
                        }
                        catch (FileNotFoundException) {
                            Console.WriteLine(string.Format("Unable to open page: {0} for site: {1}", node.Url, pathParts[0]));
                        } //can happen, keep calm and continue with next node
                    }
                }
            }
        }

        private static void UploadSiteMapToSiteCollectionDocuments(SPWeb web, string siteMap)
        {
            web.AllowUnsafeUpdates = true;
            SPDocumentLibrary documentLibrary = (SPDocumentLibrary)web.Lists["Site Collection Documents"];
            SPFileCollection files = documentLibrary.RootFolder.Files;

            SPFile file = web.GetFile(documentLibrary.RootFolder.Url + "/" + "visualsitemap.xml");

            if (file.Exists && file.CheckOutStatus != SPFile.SPCheckOutStatus.None)
            {
                file.UndoCheckOut();
            }

            if (file.Exists)
            {
                file.CheckOut();
            }

            using (MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(siteMap)))
            {
                file = files.Add(documentLibrary.RootFolder.Url + "/" + "visualsitemap.xml", ms, true);
                //logger.LogMessage(string.Format("Uploaded Sitemap {0} for site: {1}", file.Url, site.Url), true);
            }

            file.Update();

            file.CheckIn("Checked in automatically");

            if (documentLibrary.EnableMinorVersions)
            {
                file.Publish("Checked in automatically");
            }


            if (documentLibrary.EnableModeration)
            {
                file.Approve("Checked in automatically");
            }
            web.AllowUnsafeUpdates = false;
        }
 
 
     
 
    }
}


Written by Sean Carter

April 26, 2015 at 7:06 am

Posted in C#, SharePoint 2010

Add Test PublishingPages

leave a comment »

Console app, includes test content and rollup image, call like this:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.Fields;


namespace AddIntranetTestPages
{

    public class TestPageData
    {
        public TestPageData(string title, string articleContent, string rollupImage)
        {
            Title = title;
            ArticleContent = articleContent;
            RollupImage = rollupImage;
        }
        public string Title { get; set; }
        public string ArticleContent { get; set; }
        public string RollupImage {get; set;}
    }

    class Program
    {
        static void Main(string[] args)
        {


            List<TestPageData> testData = new List<TestPageData>();

            testData.Add(new TestPageData("Collaboratively administrate empowered markets via plug-and-play network",
            @"Collaboratively administrate empowered markets via plug-and-play networks. Dynamically procrastinate B2C users after installed base benefits. Dramatically visualize customer directed convergence without revolutionary ROI.",
                                        "/SiteCollectionImages/flag.jpg"));

            testData.Add(new TestPageData("Efficiently unleash cross-media information without cross-media value",
            @"Efficiently unleash cross-media information without cross-media value. Quickly maximize timely deliverables for real-time schemas. Dramatically maintain clicks-and-mortar solutions without functional solutions.",
                                        "/SiteCollectionImages/PPS/hospitality.jpg"));

            testData.Add(new TestPageData("Completely synergize resource sucking relationships via premier niche markets",
            @"Completely synergize resource sucking relationships via premier niche markets. Professionally cultivate one-to-one customer service with robust ideas. Dynamically innovate resource-leveling customer service for state of the art customer service.",
                                         "/SiteCollectionImages/ball.jpg"));

            testData.Add(new TestPageData("Objectively innovate empowered manufactured products whereas parallel platforms",
            @"Objectively innovate empowered manufactured products whereas parallel platforms. Holisticly predominate extensible testing procedures for reliable supply chains. Dramatically engage top-line web services vis-a-vis cutting-edge deliverables.",
                                        "/SiteCollectionImages/wand.jpg"));

            testData.Add(new TestPageData("Proactively envisioned multimedia based expertise and cross media growth strategies",
            @"Proactively envisioned multimedia based expertise and cross-media growth strategies. Seamlessly visualize quality intellectual capital without superior collaboration and idea-sharing. Holistically pontificate installed base portals after maintainable products.",
                                         "/SiteCollectionImages/PPS/education.jpg"));

            testData.Add(new TestPageData("Phosfluorescently engage worldwide methodologies with web-enabled technology",
            @"Phosfluorescently engage worldwide methodologies with web-enabled technology. Interactively coordinate proactive e-commerce via process-centric outside the box thinking. Completely pursue scalable customer service through sustainable potentialities.",
                                        "/SiteCollectionImages/community.jpg"));

            testData.Add(new TestPageData("Collaboratively administrate turnkey channels whereas virtual etailers",
            @"Collaboratively administrate turnkey channels whereas virtual e-tailers. Objectively seize scalable metrics whereas proactive e-services. Seamlessly empower fully researched growth strategies and interoperable internal or organic sources.",
                                      "/SiteCollectionImages/leisure.jpg"));

            testData.Add(new TestPageData("Credibly innovate granular internal or organic sources whereas high standards in web-readiness",
            @"Credibly innovate granular internal or organic sources whereas high standards in web-readiness. Energistically scale future-proof core competencies vis-a-vis impactful experiences. Dramatically synthesize integrated schemas with optimal networks.",
                                        "/SiteCollectionImages/transport.jpg"));

            testData.Add(new TestPageData("Interactively procrastinate high payoff content without backward-compatible data",
            @"Interactively procrastinate high-payoff content without backward-compatible data. Quickly cultivate optimal processes and tactical architectures. Completely iterate covalent strategic theme areas via accurate e-markets.",
                                        "/SiteCollectionImages/Icons/workplace.jpg"));

            testData.Add(new TestPageData("Globally incubate standards compliant channels before scalable benefits",
            @"Globally incubate standards compliant channels before scalable benefits. Quickly disseminate superior deliverables whereas web-enabled applications. Quickly drive clicks-and-mortar catalysts for change before vertical architectures.",
                                        "/SiteCollectionImages/mobile.jpg"));

     

            using (SPSite site=new SPSite(args[0]))
            {
                using (SPWeb web=site.OpenWeb())
                {

                    PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
                    PageLayout[] pageLayouts = publishingWeb.GetAvailablePageLayouts();
                    PageLayout currPageLayout = pageLayouts[0];
                    PublishingPageCollection pages = publishingWeb.GetPublishingPages();


                    for (int i = 1001; i < int.Parse(args[1]); i++)
                    {
                        //get item at random (well sorted by a random guid)
                        var randomTestPage = testData.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
                        PublishingPage newPage = pages.Add(randomTestPage.Title + "-" +i.ToString() + ".aspx", currPageLayout);
                        newPage.ListItem["Title"] = randomTestPage.Title;
                        newPage.ListItem["HtmlOne"] = randomTestPage.ArticleContent;

                        ImageFieldValue _field = new ImageFieldValue();
                        _field.ImageUrl = randomTestPage.RollupImage;
                        _field.AlternateText = randomTestPage.Title;
                        _field.Hyperlink = "http://www.google.co.uk";
                        newPage.ListItem["PublishingRollupImage"] = _field;

                        newPage.ListItem.Update();
                        newPage.Update();
                        newPage.CheckIn("This is just a comment");
                        newPage.ListItem.File.Publish("Published by me");
                        try
                        {
                            newPage.ListItem.File.Approve("Approved by me");
                        }
                        catch { }; //if moderation not turned on this will throw an exception but we want to swallow it 

                    }
                
                }
            }
        }
    }
}

Written by Sean Carter

April 17, 2015 at 1:14 pm

Posted in C#, SharePoint 2010

WPF – Determine whether a GridView cell failed a ValidationRule

leave a comment »

For example where the GridView already has already had invalid data set on it according to a ValidationRule e.g.


public class TagNameCellValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (value != null)
            {
                var rx = new System.Text.RegularExpressions.Regex("^\\w+([\\s-_]\\w+)*$");
                if (!rx.IsMatch(value.ToString()) || value.ToString().Length > 50)
                {
                    return new ValidationResult(false, "'" + value.ToString() + "' is not a valid Tag Name. Valid names may only contain alphanueric characters, spaces and underscores and be 50 characters or less in length");
                    //check for unique
                }
            }
            return new ValidationResult(true, null);
        }
    }


…XAML for completeness:


<DataGrid.Columns>
    <DataGridTextColumn Header="Id" Binding="{Binding Id, TargetNullValue='[new]'}" Width="40"  IsReadOnly="True" />
    <DataGridTextColumn Header="Tag Name">
    <DataGridTextColumn.Binding>
            <Binding Path="Name" TargetNullValue='[Tag Name]'>
                <Binding.ValidationRules>
                    <local:TagNameCellValidationRule />
                </Binding.ValidationRules>
        </Binding>
        </DataGridTextColumn.Binding>
    </DataGridTextColumn>
    <DataGridTextColumn Header="Position" Binding="{Binding Position}" Width="60" IsReadOnly="True" />
</DataGrid.Columns>


…you wish to prevent the code behind a commit button from running and put up a message(for example)…however the offending value does not exist on any of the rows (it failed the validation so the bad data is not committed to the GridView row) so you can’t check these. Can do in code behind like this:


        /// <summary>
        /// Determine whether the an error was raised in the DataGrid i.e. ValidationRule returned false
        /// </summary>
        /// <param name="dg"></param>
        /// <returns></returns>
        private bool HasErrorText(DataGrid dg)
        {
            bool hasError = false;

            var itemsSource = TagsGrid.ItemsSource as IEnumerable;
            foreach (var item in itemsSource)
            {
                var row = TagsGrid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
                if (Validation.GetHasError(row) == true)
                {
                    hasError = true;
                }

            }
            return hasError;
        }

Written by Sean Carter

March 13, 2014 at 1:09 pm

Posted in C#

Troubleshooting Kerberos Authentication with WCF Service (and SQL Server)

leave a comment »

Ensure Service Principal is set in the web.config:
Service Principal name in web.config

Ensure it’s a Kerberos authentication from the Web Servers point of view (i.e. log on the the web server console and run Event Viewer there):
Kerberos - Event Viewer

Validate the SQL Server Server service account SPN registration:
System.Data.SqlClient.SqlException: Login failed for user ‘NT AUTHORITY\ANONYMOUS LOGIN’

As you’re probably using Kerberos delegation to connect to the database as the same user connecting to the client application you’d better make sure that the user has access to the SQL Server/database…you can do runas /user:domain\username [path to sql management studio]\ssms.exe as described here

Of course there are numerous other possibilities not listed that could cause Kerberos woes..

Written by Sean Carter

March 12, 2014 at 11:59 am

Posted in Security

Reset Visual Studio

leave a comment »

Start > Run > devenv /resetuserdata

..use when intellisense breaks or some other weird stuff happens that cannot be resolved manually

Written by Sean Carter

March 10, 2014 at 2:06 pm

Posted in Uncategorized

Putting code snippets in SharePoint Wiki

leave a comment »

…or any other HTML page for that matter:

http://hilite.me/

Paste in C#/JavaScript etc, click the highlight button, copy and paste the resulting HTML into the HTML view in SharePoint Wiki and you’re done

Works for lots of different languages and lots of formatting options. Nice.

Written by Sean Carter

March 5, 2014 at 3:54 pm