Removing styling in a SharePoint 2013 AppPart the easy way

By bhoeijmakers at January 23, 2013 08:53
Filed Under: SharePoint 2013

Introduction

The other day I was wrestling with the new SharePoint 2013 App framework. I created a SharePoint 2013 SharePoint Hosted App. Besides full screen mode (which pops up when you press F5 in Visual Studio 2012), I also wanted to add an AppPart in order to make the app available on my host website. The problem I was facing is that my App Part is just an IFrame loading the main page of my App. This includes the Chrome and Navigation of the App default.aspx page. This makes my App Part look like this:

 

 

What I don't want!

 

I was searching the internet for a quick and easy way to remove the chrome and navigation from the page when using an AppPart, while keeping it when my App is in Full screen mode. I could only find some pretty complex ways to do this, so I thought I’ll share my solution to this. The final result looks like this:

 

 

DemoAppPart_NoStyling

 

The Solution

I did this in a SharePoint Hosted App. The problem as described above occurs if your App page is hosted inside SharePoint (as is the case with a SharePoint hosted app). What I did was first create a new Project in Visual Studio 2012 and choose the “App for SharePoint 2013” template. I then chose the “SharePoint-hosted” app option. This creates a default SharePoint Hosted app with a Default.aspx page in the App-web.

 

In order to make an AppPart available in the Host Web you’ll have to add a Client Web Part item to your Visual Studio Solution. Right-click on your project in Visual Studio and select New Item. Then choose the Client Web Part item template.

AddProjectItem

 

In the next dialog window I chose “Select or enter a URL for an existing web page”.

ClientWebPartPage

 

This makes sure that the AppPart loads the same page in the IFrame as is shown in the full screen version of the app. Doing the steps above gives you an Elements.xml file containing the following XML:

 

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ClientWebPart Name="MyDemoAppPart" 
                 Title="My Demo AppPart" 
                 Description="This is a demo AppPart" 
                 DefaultWidth="300" DefaultHeight="200">
 
    <!-- Content element identifies the location of the page that will render inside the client web part
         Properties are referenced on the query string using the pattern _propertyName_
         Example: Src="~appWebUrl/Pages/ClientWebPart1.aspx?Property1=_property1_" -->
    <Content Type="html" Src="~appWebUrl/Pages/Default.aspx" />
 
    <!-- Define properties in the Properties element.
         Remember to put Property Name on the Src attribute of the Content element above. -->
    <Properties>
    </Properties>
 
  </ClientWebPart>
</Elements>

 

Putting the new AppPart on a page in your Host Web gives the result as shown in the introduction of this article. To remove most of the navigation and chrome a very simple trick can be applied. Just add “IsDlg=1” to the querystring of the call to the Default.aspx file in the App Web. This querystring is also used by SharePoint internally to remove navigation when opening a Model Dialog. Hence the name of the parameter IsDlg. So now the Elements.xml file looks like this:

 

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ClientWebPart Name="MyDemoAppPart" 
                 Title="My Demo AppPart" 
                 Description="This is a demo AppPart" 
                 DefaultWidth="300" DefaultHeight="200">
 
    <!-- Content element identifies the location of the page that will render inside the client web part
         Properties are referenced on the query string using the pattern _propertyName_
         Example: Src="~appWebUrl/Pages/ClientWebPart1.aspx?Property1=_property1_" -->
    <Content Type="html" Src="~appWebUrl/Pages/Default.aspx?IsDlg=1" />
 
    <!-- Define properties in the Properties element.
         Remember to put Property Name on the Src attribute of the Content element above. -->
    <Properties>
    </Properties>
 
  </ClientWebPart>
</Elements>

 

The clue is in the following line of XML:

 

    <Content Type="html" Src="~appWebUrl/Pages/Default.aspx?IsDlg=1" />

 


As you can see I’ve added the IsDlg=1 as a querystring. The resulting AppPart looks like this:

 

DemoAppPart_isDlg

 

Almost got it! The only thing is that there is a lot of whitespace in the top of my AppPart content. Using the IE developer tools I figured out that this is caused by a div with id=”globalNavBox” that is still taking up space.

 

<div class="noindex" id="globalNavBox">

 

In order to hide it I’ll have to add a little bit of JavaScript using jQuery to my App.js file. This piece of JavaScript fires only when the IsDlg=1 parameter is in the querystring.

 

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
$(document).ready(function () {
    // Hide the globalNavBox element if IsDlg querystring parameter is set
    var isDialog = getQueryStringParameterByName('IsDlg');
    if (isDialog == '1') {
        $("#globalNavBox").hide();
    }
 
    context = SP.ClientContext.get_current();
    web = context.get_web();
 
    getUserName();
});
 
function getQueryStringParameterByName(name) {
    var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

 

The trick is in the following:

 

    var isDialog = getQueryStringParameterByName('IsDlg');
    if (isDialog == '1') {
        $("#globalNavBox").hide();
    }

 

When isDialog is 1, I use jQuery to hide the element with Id=”globalNavBox”.

 

This results in an AppPart with all Chrome and Navigation removed. The same page in Full Screen Mode does show the Chrome and Navigation.

 

Summary

To remove all the default styling from a SharePoint Hosted App page showing in an AppPart, you can take the following approach:

 

Add IsDlg=1 to the querystring of the call to the App page from the AppPart.

Add the following code to the App.js file:

 

    var isDialog = getQueryStringParameterByName('IsDlg');
    if (isDialog == '1') {
        $("#globalNavBox").hide();
    }

Wiring Taxonomy Fields in the Sandbox in SharePoint 2010 using PowerShell

By bhoeijmakers at July 30, 2012 14:21
Filed Under: .NET, SharePoint 2010

A while ago I did a series of blog posts about Taxonomy Fields. You can find those posts here: Part I, Part II, Part III. Most of the code in those posts is not usable when working in the Sandbox, since the Microsoft.SharePoint.Taxonomy namespace is not available when writing solutions for the sandbox.

 

The other day I had to write a solution for a customer which had (among others of course) the following requirements:

- Centrally managed content types

- Sandboxed Solution

- Automated Install

 

I decided to create a Sandboxed Content Type Hub that would contain my Site Columns and Content Types.

 

All this will be deployed to the SharePoint Farm using PowerShell Scripts. This gives me some flexibility to configure my Taxonomy Fields using PowerShell. The solution to declaring Taxonomy Fields described in my earlier post http://www.insidesharepoint.net/post/2010/11/05/Using-taxonomyfields-in-Sharepoint-2010-Part-I.aspx uses a Feature Receiver to connect the declared Taxonomy Field to its hidden notefield and to the Term Set from the TermStore. In order to do this, we need classes from the Microsoft.SharePoint.Taxonomy namespace that are not available in the Sandbox. So I couldn’t use that solution directly.

 

What I eventually did was declare the fields as usual in the solution, and then rewrite the feature receiver to a PowerShell function. Also I wrote scripts to create the Content Type Hub site collection and to upload the Sandboxed Solution containing my Content Types and Site Columns to the Content Type Hub site collection. I thought I share the code to do this with you, maybe it helps someone out there.

 

Wiring up a Taxonomy Field using PowerShell:

 

function ConfigureMetaDataField( [string]$taxFieldGuid, [string]$noteFieldGuid, [string]$siteUrl, [string]$mmaName, [string]$groupName, [string]$termSetName ) 
{
    # Get the site
    $site = Get-SPSite $siteUrl
    # Get the taxonomy field that was deployed by the Sandboxed WSP
    [Microsoft.SharePoint.Taxonomy.TaxonomyField]$field = $site.RootWeb.Fields | Where-Object { $_.Id -eq $taxFieldGuid }
    
    # Set the hidden note field
    $field.TextField = $noteFieldGuid
    # Get the correct Term Set from the Managed Metadata service app
    $session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)
    $termstore = $session.TermStores[$mmaName]
    $group = $termstore.Groups | Where-Object { $_.Name -eq $groupName }
    $termSet = $group.TermSets[$termSetName]
    # Set the fields termstore id and termset id
    $field.SspId = $termstore.Id
    $field.TermSetId = $termSet.Id
    # Update the field

$field.Update()

 

# Dispose

$site.Dispose()

}
 

The PowerShell function assumes that you have already deployed the Taxonomy Field and its hidden note field using a (Sandboxed) WSP. How to do this is described in my earlier post here, but reprinted here for completeness:

 

Fields declaration:

 

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
	<Field Type="TaxonomyFieldTypeMulti"          
		DisplayName="MyTaxonomyField"          
		ShowField="Term1033" Required="TRUE"          
		ID="{8D0458C1-0FB7-4981-BEE1-52D0DF01895C}"          
		StaticName="MyTaxonomyField"          
		Name="MyTaxonomyField"          
		Group="Custom"         
		Mult="TRUE"         
		>
	</Field>    
	<Field Type="Note"          
		DisplayName="MyTaxonomyField_0"          
		StaticName="MyTaxonomyFieldTaxHTField0"          
		Name="MyTaxonomyFieldTaxHTField0"          
		ID="{3a913424-fc7f-49ef-8fb6-a2ca1712cdc3}"          
		Hidden="TRUE"         
		DisplaceOnUpgrade="TRUE"         
	/>
</Elements>
 

ContentType declaration:

 
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x0100b58d33764b384da58bbadee9721e1843"
               Name="MyCustomContentType"
               Group="Custom"
               Description="Custom provisioned contenttype containing a Taxonomyfield"
               Inherits="TRUE"
               Version="0">
    <FieldRefs>
      <FieldRef ID="8D0458C1-0FB7-4981-BEE1-52D0DF01895C" Name="MyTaxonomyField"/>
      <FieldRef ID="3a913424-fc7f-49ef-8fb6-a2ca1712cdc3" Name="MyTaxonomyFieldTaxHTField0"/>
      <FieldRef ID="f3b0adf9-c1a2-4b02-920d-943fba4b3611" Name="TaxCatchAll"/>
      <FieldRef ID="8f6b6dd8-9357-4019-8172-966fcd502ed2" Name="TaxCatchAllLabel"/>
    </FieldRefs>
  </ContentType>
  <Receivers>
    <Receiver>
      <Name>TaxonomyItemSynchronousAddedEventReceiver</Name>
      <Type>ItemAdding</Type>
      <Assembly>Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
      <Class>Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver</Class>
      <SequenceNumber>10000</SequenceNumber>
    </Receiver>
    <Receiver>
      <Name>TaxonomyItemUpdatingEventReceiver</Name>
      <Type>ItemUpdating</Type>
      <Assembly>Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
      <Class>Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver</Class>
      <SequenceNumber>10000</SequenceNumber>
    </Receiver>
  </Receivers>
</Elements>
  

Uploading the Sandboxed Solution (WSP) to the Content Type Hub Site Collection:

 

Add-SPUserSolution -LiteralPath $wspPath -Site $siteUrl

 

Activating the Sandboxed Solution:

 

Install-SPUserSolution -Identity SolutionName.wsp -Site $siteUrl

 

Activate the Content Type Feature using the commandlet Enable-SPFeature.

 

This feature automatically activates the Site columns feature. If you make the Site Columns feature hidden and you create an activation dependency between the Content Type feature and the Site Columns feature, the Site columns feature will automatically be activated when activating the Content Type Feature. Pretty neat.

 

Calling the PowerShell function:

 

ConfigureMetaDataField -taxFieldGuid "8D0458C1-0FB7-4981-BEE1-52D0DF01895C" -noteFieldGuid "3a913424-fc7f-49ef-8fb6-a2ca1712cdc3" ‘

-siteUrl "http://mycontenttypehub" -mmaName "My Managed Meta Data Service Application" -group "MyGroup" -termSet "MyTermSet"

 

Thats it! Hope this helps someone…

Tools & tricks for troubleshooting SharePoint 2010: Unexpected Errors

By bhoeijmakers at March 28, 2012 09:46
Filed Under: SharePoint 2010

A good part of my time I’m working on troubleshooting issues with SharePoint 2010 farms. Usually this includes (but is not limited to) unexpected errors and performance problems. In this blogpost I will describe some of the tools and tricks I use on a daily basis to pinpoint the source of problems.

 

Unexpected errors

We all know them, right? “An unexpected error has occurred”.

 

image

 

Now what? To get a more descriptive message about what might be wrong, there are two approaches: More...

I’m speaking on the TechDays 2012 in The Hague

By bhoeijmakers at February 14, 2012 21:24
Filed Under: .NET, SharePoint 2010

On thursday the 16th of february I’m speaking on the TechDays 2012 NL in The Hague. I’m doing a level 200 session called SharePoint 2010 for ASP.NET developers together with my collegue Donald Hessing. Hope to meet you there!

Implementing logging in SharePoint 2010 using the SharePoint Guidance library

By bhoeijmakers at December 04, 2011 08:18
Filed Under: .NET, SharePoint 2010

In this post I will talk about a way to implement a logging component in SharePoint 2010 that uses the Microsoft SharePoint Guidance Patterns and Practices library. The SharePoint Guidance library contains a lot of cool and very useful components. I will only focus on the logging component in this post and how to use it in practice to create your own logging component. In this post I am creating a Farm Solution. In a later post I will talk about how to do this in a sandboxed solution.

 

If you don’t want to read the theory and go straight to downloading the example solution, click here

 

More...

Speaking on SharePoint Connections in Amsterdam

By bhoeijmakers at November 18, 2011 09:18
Filed Under: Sharepoint 2010

I’m happy to announce that I will be doing a session on SharePoint Connections 2011 in Amsterdam next Wednesday the 23th of November together with my collegae Donald Hessing. We will be doing the same session that we did on the European SharePoint Conference in Berlin last October.

 

i'm-a-speaker

Taxonomy fields revisited: Getting the Term Store programmatically

By bhoeijmakers at November 04, 2011 16:12
Filed Under: .NET, SharePoint 2010

In my series of posts about using Taxonomy Fields in SharePoint 2010 I am using code to do all kinds of stuff with Taxonomy Fields and Terms from code. Because I can´t leave those fascinating Taxonomy Fields for what they are, here is yet another post about this subject Smile 

 

This is a follow up on my previous posts on this subject:

Using Taxonomy Fields in SharePoint 2010 - Part I

Using Taxonomy Fields in SharePoint 2010 - Part II

Using Taxonomy Fields in SharePoint 2010 - Part III

 

This post is meant for those of you that have read the previous posts (or attended one of my sessions on Managed Metadata Fields), and want to know more in order to write better code.

 

To get the Term Store from code I was using the following code in the Using Taxonomy Fields in SharePoint 2010 series of posts:

 

// set up the field for my termstore
TaxonomySession session = new TaxonomySession(site);
 
if (session.TermStores.Count > 0)
{
      // get termstore
      TermStore ts = session.TermStores[0];
 
      // more code here...
}

 

This is not very robust code and should not be used in a production environment. The code above gets the first (default) Term Store from the Taxonomy Session. But what if there are multiple Term Stores associated with the Web Application? In this post I will show you how to get the Term Store programmatically the right way More...

Slide deck for my presentation on the European SharePoint Conference now available!

By bhoeijmakers at October 25, 2011 07:18
Filed Under: SharePoint 2010

I had a great time at the European SharePoint Conference in Berlin last week. Saw some great sessions and met a lot of cool new people. Thanks to everyone that attended our Managed Metadata black belt presentation. The slides are now available for download here

I’m speaking on the European SharePoint Conference in Berlin

By bhoeijmakers at September 13, 2011 08:07
Filed Under: SharePoint 2010

I’m very happy to announce that I will be giving a presentation on the European SharePoint Conference in Berlin. I will be doing a session on Managed Metadata together with my collegae Donald Hessing. Here is a description of the session:

 

The use of Managed Meta Data in SharePoint seems to be trivial. You link the managed meta data service application to the proxy group that you want to use in the webapplication, you add a managed meta data field to the list and link that to the termset you want to use. No magic here! But once we dive into the more advanced scenarios we will see that the use, development and management has a lot of dark sides. What is actually stored in a taxonomy field, do I need the note field, where is the TaxonomyHiddenList good for, can I use managed meta data in the sandbox, how do I use the taxonomy field with search, are there any restrictions from an architectural point of view?

The session will be on Thursday the 20th of October at 11:15.

 

Hope to meet you there!

Using custom CAS policy files in SharePoint 2010

By bhoeijmakers at September 04, 2011 12:42
Filed Under: SharePoint 2010

The other day I had to migrate a Microsoft Office SharePoint Server 2007 application to SharePoint 2010. This very simple database application uses a generated datalayer. This means, in this particular case, that the datalayer components of the application are in seperate DLL’s. I wanted to deploy these DLL’s to the BIN folder of the webapplication instead of to the Global Assembly Cache. This way I don’t need to put third party code in the GAC, and I have more control over what the code is allowed and not allowed to do. More...

About the author

Bart-Jan Hoeijmakers is Lead SharePoint Developer at VX Company. Since 2006 he is the driving force behind the development of several enterprise SharePoint projects within VX Company. He is a hardcore developer in both SharePoint and ASP.NET and loves to dive into the dark sides of SharePoint development.

Month List