Friday, April 12, 2013

Design Manager deployed Page Layout not displaying custom css file

I recently ran into an issue in which I was attempting to reference a custom css page within a Design Manager deployed page layout; however, I couldn't get the custom css page to load on web pages despite the fact that I was prominently referencing the css file in the proper location of the page layout's HTML file.  After doing a bit of research, I finally discovered that you also need to add a special attribute to the <link> element called "ms-design-css-conversion" and set the value to "no".  Here is an example of what your <link> element will look like in order for the custom css file to load properly:
<link href="MyCustomPageLayoutStyle.css" type="text/css" rel="stylesheet" ms-design-css-conversion="no" />
Also, here is a complete example that also shows you the proper location for referencing you custom css file within your custom page layout's HTML file:

<!--MS:<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server">-->
<!--CS: Start Edit Mode Panel Snippet-->
    <!--SPM:<%@Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>-->
    <!--SPM:<%@Register Tagprefix="Publishing" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>-->
        <!--MS:<Publishing:EditModePanel runat="server" id="editmodestyles">-->
        <!--MS:<SharePoint:CssRegistration name="&#60;% $SPUrl:~sitecollection/Style Library/~language/Themable/Core Styles/editmode15.css %&#62;" After="&#60;% $SPUrl:~sitecollection/Style Library/~language/Themable/Core Styles/pagelayouts15.css %&#62;" runat="server">-->
        <!--ME:</SharePoint:CssRegistration>-->
    <!--ME:</Publishing:EditModePanel>-->
    <!--CE: End Edit Mode Panel Snippet-->

    <link href="MyCustomPageLayoutStyle.css" type="text/css" rel="stylesheet" ms-design-css-conversion="no" /> 

<!--ME:</asp:ContentPlaceHolder>-->

Wednesday, March 27, 2013

Programmatically determine if a web-scoped feature has been activated

This may be of limited use, but if you're ever looking for a way to programmatically determine if a web-scoped feature has been activated on a given SharePoint site, here is a quick method you can use to obtain that information:

private bool IsFeatureActivated(Guid siteId, Guid webId, Guid featureId)
{
    bool isFeatureActivated = false;
    using (SPSite site = new SPSite(siteId))
    {
        using (SPWeb web = site.OpenWeb(webId))
        {
            if (web.Features[featureId] != null)
            {
                isFeatureActivated = true;
            }
        }
    }
    return isFeatureActivated;
}

Monday, March 11, 2013

View the XML data behind a Search Core Results Web Part


If you wish to view the raw XML data that is associated with a Search Core Results or People Search Core Results web part, you can do so via the following steps:

  1. Open IE and navigate to the page that contains the given Core Results web part
  2. Select Site Actions -> Edit Page
  3. Click on your web part's menu and select Edit Web Part
  4. Expand Display Properties and click on the XSL Editor... button
  5. In the Text Editor window, copy the existing XSL to a temporary location since you'll probably need it again.  Here is a possible option for you:
    1. Hit Ctrl+a to highlight all of the content
    2. Hit Ctrl+c to save the content
    3. Open Notepad
    4. Hit Ctrl+v to past the content to Notepad
  6. Return to the Text Editor window, hit Ctrl+a, and hit Delete
  7. Copy and paste the following XSL code into the Text Editor window:
  8. <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <xmp><xsl:copy-of select="*"/></xmp> </xsl:template> </xsl:stylesheet>
  9. Click Save
  10. Click OK
  11. Return to the parent Search page and enter a valid search parameter
At this point, the page that contains the Search Core Results web part will be displayed with the XML contents available for your review.  Once your review of the data is complete, I recommend that you revisit the XLS Editor... and replace the XSL code with the code that you copied into Notepad earlier.  Unless, of course, your users like to view XML data in his/her search results which is not very likely...

Thursday, March 7, 2013

Assign a Preview image to your custom Page Layouts

There are quite a few good sites out there that provide steps for creating custom page layouts using the new SharePoint 2013 Design Manager, but none of them bring up how you would go about assigning a Preview image to your new custom Page Layouts. This is most likely due to the fact it's pretty simple to do once you know where to look for it. Anyway, these procedures assume that you've already created and deployed your new custom Page Layouts using Design Manager. Here goes...

Add the Preview Images to the Master Page Gallery
  1. Using your web browser, open up a link to your Master Page Gallery (i.e.  http://SharePointWebApp/_catalogs/masterpage/Forms/AllItems.aspx)
  2. Double-click on the en-us directory
  3. Double-click on the Preview Images directory
  4. Click on the Files tab
  5. Under the New section, click Upload Document
  6. Click Browse..., navigate to your first Preview file, and click on it
  7. Click Open
  8. Click OK
  9. For Content Type, select Master Page Preview
  10. For UI Version, place a check in the 15 checkbox



  11. Click Save
  12. Once the image is uploaded, click on the image list item and select Publish a Major Version
  13. Click OK
  14. Repeat Steps 5-13 for each Preview Image
NOTE:  If you don't publish your files as shown in Steps 12-13, your Preview images will appear as a red X when the user is looking at the locations where the Preview image is viewed


Assign the Preview Images
  1. Navigate back to the home page of the Master Page Gallery
  2. If you used the Design Manager to add your custom Page Layouts, you will click on the .html file associated with your first custom Page Layout and select Edit Properties (that is, if they are still associated with each other which is most likely the case...)
  3. Locate the Preview Image section
  4. Enter the URL of the file in the Type the Web address: textbox  (i.e. http://SharePointWebApp/_catalogs/masterpage/en-US/Preview%20Images/PreviewImageName.png)
  5. Enter a user-friendly description in the Type the description: textbox
  6. Click Save
  7. Repeat Steps 2-6 to assign the Preview images to their resepctive Page Layouts

Verify the Preview Image of a custom Page Layout
  1. Navigate to a page on your site and click Edit
  2. Click on the Page tab
  3. Under Page Actions, click Page Layout
  4. Verify that your custom Preview image has been assigned (i.e. in my example, my custom Page Layout is TestLayout1 and it's based on the Article Page content type)

Tuesday, February 26, 2013

Programmatically assign a SharePoint user to a "Person or Group" column in a SharePoint list

Here is some sample code that demonstrates how you can assign a given SharePoint user to a "Person or Group" column or field (in this case, I have a custom "Person or Group" field called "Owner") contained within a SharePoint list:

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

...

Guid siteId = new Guid("GuidOfSiteCollection");
Guid webId = new Guid("GuidOfSite");
Guid listId = new Guid("GuidOfList");
string itemTitle = "My Item's Title";
string userName = "Domain//UserName";

using (SPSite site = new SPSite(siteId))
{
    using (SPWeb web = site.OpenWeb(webId))
    {
        // Find all list items that match your search criteria
        SPQuery query = new SPQuery();
        query.Query = string.Format("{0}", itemTitle);
        SPListItemCollection items = web.Lists[listId].GetItems(query);
        // Obtain a reference to SPUser object associated with the specified user
        SPUser user = web.AllUsers[userName];
        // Assign the user to the custom "Owner" field of my SharePoint list items
        web.AllowUnsafeUpdates = true;
        foreach (SPListItem item in items)
        {
            if (user != null)
            {
                item["Owner"] = user;
                item.Update();
            } 
        }
        web.AllowUnsafeUpdates = false;
    }
}
As you can tell, this is a super-simplified version of some actual code that I've got working. Naturally, you will want to organize this code to better suit your needs (as well as add some exception handling), but the purpose of this example is to show you the basics of how it's done. Enjoy!

Monday, February 25, 2013

How to obtain a copy of the InfoPath template file associated with a SharePoint Form Library

Here are the steps you can use for obtaining a copy of the InfoPath template file (i.e. template.xsn) after it has been published to a SharePoint form library:

  1. Open IE and navigate to the SharePoint site where your forms library exists
  2. Click on Site Actions -> View All Site Content
  3. Under the Document Libraries section, locate and click on the link for your form library
  4. On the Library Tools tab, click on Library


  5. Locate the Connect & Export section and click on Open with Explorer


  6. When Windows Explorer pops up, click on the Forms directory


  7. Locate the "template.xsn" file


  8. Copy and paste the "template.xsn" file to a location on your local hard drive
You may now edit that local copy of the template.xsn file using InfoPath and publish the form back to the SharePoint form library (i.e. the path information was saved to the form when it was published).

Tuesday, February 19, 2013

Programmatically obtain a list of files contained in a directory

If you ever need to programmatically obtain information about files contained within a given directory/folder, I've provided some sample code from a Windows Form Application I created that will provide you with that capability.  In this particular instance, my Windows App allows the user to select the directory he/she wishes to review and then populates a Grid View control with information about the files contained in the directory (i.e. in this simple example, the name of the file and the date the file was last modified):

using System.Windows.Forms;
using System.Data;
using System.IO;

public partial class Form1 : Form
{
        private FolderBrowserDialog m_fbd;

        ...

        /// <summary>
        /// When the button is clicked, the user will be prompted to select the input file to open via the OpenFileDialog
        /// control.  Once the user has selected the input file, the information in the file will be read, parsed, and then
        /// displayed in the grid view control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReviewFiles_Click(object sender, EventArgs e)
        {
            if (m_fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("FileName");
                dt.Columns.Add("LastModifiedDate");

                DirectoryInfo dir = new DirectoryInfo(m_fbd.SelectedPath);
                foreach (FileInfo file in dir.GetFiles("*.*"))
                {
                    DataRow row = dt.NewRow();
                    row["FileName"] = file.Name;
                    row["LastModifiedDate"] = file.LastWriteTime.ToString();
                    dt.Rows.Add(row);
                }
                dataGridView1.DataSource = dt;
            }
        }

If you would only like to display information about certain types of files, you can modify the parameter of the GetFiles method call appropriately.  In the following example, the code will only display information about  .pdf files contained in the selected directory:

foreach (FileInfo file in dir.GetFiles("*.pdf"))

Yes, I know...this example provides too much code to demonstrate how easy it is to programmatically obtain info about files in a given directory, but I thought it would be fun to add the additional code that could turn this into a nice utility if needed...