Lars Nielsen's Discoveries

October 1, 2012

Session State problems with SharePoint custom pages

Filed under: Development,SharePoint — Lars Nielsen @ 7:37 pm
Tags: , ,

It’s a common requirement to host or embed web applications within an Intranet in SharePoint. The quick-but-dirty solution to this is to use a Page Viewer Web Part or a custom HTML page that displays an external ASPX page within a SharePoint page inside an IFRAME. The problem with this is what happens when the content within the IFRAME changes – you’ll see either a big patch of white space in the frame (if it shrinks) or an embedded scrollbar (if it grows) – neither of which is very nice for end users.

But because SharePoint is itself written in .NET, you can do something more clever and you can create ASPX pages in a SharePoint site that reference exactly the same master page and branding as the site itself. I use this technique to create web applications outside of SharePoint and then copy the ASPX pages over into a SharePoint project so that they can be provisioned into a SharePoint site via feature activation. This has the neat advantage that a single application can be deployed several times into different SharePoint sites, simply by activating the feature on each site. And because SharePoint master pages are dynamic (if you have the Publishing features activated), the same ASP.NET web application can even be branded differently on different sites.

The original great articles by Andrew Connell describe this technique very well here  and here. Although these are rather old now, the same technique can be adapted to SharePoint 2010 and Visual Studio 2010.

Recently when I was working on this I came across a problem when trying to use Session State in the code behind to persist a value between 2 different pages. Everything worked fine outside SharePoint, in a native ASP.NET web application. But when I migrated the pages into a SharePoint site, and tried them, I got this error:

Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the \<system.web>\ section in the application configuration.

I checked to see that session state was enabled in SharePoint and had a quick look at the web.config file for the web application. In the web.config there is a line in – <system.web> like this:

<pages … enableSessionState=”false” … />

So I thought that turns off session state for all ASPX pages by default. To use session state on my pages I added to the Page directive an attribute to turn on session state:

<%@ Page EnableSessionState=”true” … %>

I refreshed the main page and saw this error instead:

The enablesessionstate attribute on the page directive is not allowed in this page

At this point I looked around the web and found this discussion.  But I didn’t want to mess around with the PageParserPaths element in the web.config. I thought there must be a better way, and found this discussion ( where it seems that resetting the pages to the site definition will fix it.  I tried resetting to the site definition, but it didn’t help.  Then I found this gave me a clue.

I tried changing the master page in my SharePoint site, which was a custom master page, to the out-of-the-box default.master.  Suddenly the error disappeared!  I switched back to my custom master page and the error came back.  I even created my own custom master page which was a copy of the standard default.master page, and applied this to the site, and that copy still caused the same exception.   It seems session state will not work unless the master page is uncustomized.

For the moment I don’t how to get around this and I just design my code assuming that session state is not available, but if anyone has any good ideas how to use session state please let the world know!

Advertisements

May 6, 2011

My Links loses the orange gradient background on hover – A CSS case-sensitivity issue

Filed under: Branding,SharePoint — Lars Nielsen @ 7:39 pm
Tags: ,

In trying to create CSS to style a custom master page in SharePoint, I discovered a strange quirk (you’ll see the significance of that word later) in the way SharePoint out-of-the-box styles and controls work.

The “My Links” link at the top of the page next to the “Welcome” box is rendered by the following line in a master page:

<SharePoint:DelegateControl runat="server" ControlId="GlobalSiteLink2" Scope="Farm"/>

If you look at the HTML that comes out on the page, it’s marked up with HTML like this:

<TD class="ms-globallinks">
  <SPAN id="ctl00_ctl16_MyLinksMenu">
    <SPAN style="DISPLAY: none">
      <MENU id="ctl00_ctl16_MyLinksMenuMenuTemplate" type="ServerMenu" largeIconMode="true"></MENU>
    </SPAN>
    <SPAN title="Open Menu">
        <span id="ctl00_ctl16_MyLinksMenuMenu_t" class="ms-SPLink ms-hovercellinactive" onmouseover="MMU_PopMenuIfShowing(this);MMU_EcbTableMouseOverOut(this, true)" onclick="javascript:FetchCallbackMenuItems('ctl00_ctl16_MyLinksMenuMenuTemplate'); MMU_Open(byid('ctl00_ctl16_MyLinksMenuMenuTemplate'), MMU_GetMenuFromClientId('ctl00_ctl16_MyLinksMenuMenu'),event,true, null, 0);" nowrap="nowrap" foa="MMU_GetMenuFromClientId('ctl00_ctl16_MyLinksMenuMenu')" hoverInactive="ms-SPLink ms-hovercellinactive" hoverActive="ms-SPLink ms-hovercellactive">
          <a style="white-space: nowrap; cursor: hand;" onkeydown="MMU_EcbLinkOnKeyDown('ctl00_ctl16_MyLinksMenuMenuTemplate'), MMU_GetMenuFromClientId('ctl00_ctl16_MyLinksMenuMenu'), event);" id='ctl00_ctl16_MyLinksMenuMenu' oncontextmenu="this.click(); return false;" onfocus="MMU_EcbLinkOnFocusBlur(byid('ctl00_ctl16_MyLinksMenuMenuTemplate'), this, true);" onclick="javascript:return false;" href="#" serverclientid="ctl00_ctl16_MyLinksMenuMenu" menuTokenValues="MENUCLIENTID=ctl00_ctl16_MyLinksMenuMenu,TEMPLATECLIENTID=ctl00_ctl16_MyLinksMenuMenuTemplate">
            My Links
            <IMG border=0 alt="Use SHIFT+ENTER to open the menu (new window)." src="/_layouts/images/blank.gif">
          </A>
          <IMG alt="" align="absBottom" src="/_layouts/images/menudark.gif">
        </SPAN>
    </SPAN>
  </SPAN>
</TD>

I’m sure your first thought on seeing this is: yuck! It’s the familiar wonky SharePoint HTML, but I want to point out this class assignment in the inner <SPAN> tag:

class=”ms-SPLink ms-hovercellinactive”

and this attribute:

hoverActive=”ms-SPLink ms-hovercellactive”

What happens here is that as the user runs the mouse over “My Links” the onmouseover attribute calls the Javascript function MMU_PopMenuIfShowing. That reads the hoverActive attribute and then dynamically changes the CSS class for the SPAN tag from “ms-SPLink ms-hovercellinactive” to “ms-SPLink ms-hovercellactive”, and that’s what creates the orange gradient background on “My Links” when you hover over it. Now if we look in the out-of-the-box core.css file, which is always on every SharePoint page, it has a CSS definitions for classes ms-hovercellinactive and ms-hovercellactive – here’s the extract from core.css:

.ms-HoverCellInActive,.ms-SpLinkButtonInActive
{
border:none;
margin:1px;
color:#4c4c4c;
vertical-align:top;
background-color:transparent;
}
.ms-HoverCellActive,.ms-SpLinkButtonActive
{
border:#6f9dd9 1px solid;
vertical-align:top;
background-color:#ffbb47;
background-image:url("/_layouts/images/menubuttonhover.gif");
}

So core.css defines the class as “ms-HoverCellActive” but in the HTML SPAN tag the class attribute is “ms-hovercellactive”. Does it matter that they have different case? Well, yes and no. Normally the SharePoint default.master page has no DOCTYPE definition at the top. This puts IE (8, not sure about 9) into Quirks Mode, and in Quirks Mode it ignores the case of CSS classes so it will render correctly. However, best practice in web design is to include a DOCTYPE and to take IE out of Quirks Mode. In my master page I’m using:

<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

As soon as you put a DOCTYPE at the start of the page, and take IE out of Quirks mode, it starts to treat CSS class names as case-sensitive and expects the case to match. When you hover over “My Links” you lose the orange gradient background. To fix this, you need to define CSS for ms-hovercellactive and ms-hovercellinactive explicitly, in your own custom CSS file.  You can either replicate what’s in core.css, or define your own CSS for these classes.

July 30, 2010

Custom Application master page: traps and workarounds

Filed under: Branding,SharePoint — Lars Nielsen @ 8:48 pm
Tags: , , ,

I’ve been having some fun trying to change the master page for some of the application pages in the _layouts folder in SharePoint.  I’ve created a special HttpModule that applies my custom master page to some of the pages – just the ones that are normally seen by people who have member level (contribute) permission on a team site.  Most of the application pages are only visible to people with higher level permission than contribute, but a few pages (for example, setting up a new alert, or uploading a file) are visible to members. In my case the client wanted those pages to be branded to look like the rest of the site, not the standard blue-and-orange SharePoint branding that you get with application.master. I managed to apply the standard site master page to a couple of the application pages (the ones for uploading documents and for setting an alert) with no problems.  But as I began to apply it other pages in the _layouts folder, I started getting errors about missing placeholders, or Javascript null reference errors.   The missing placeholder errors are OK to fix – it’s just a question of finding the placeholder in the application.master file and adding it to the custom master page.  I follow Heather Solomon’s advice and have an invisible panel at the bottom of the page, and all the placeholders go in there (unless they need to be visible like PlaceHolderLeftActions – see later). The fun starts when you start getting other kinds of errors which don’t tell you what the real problem is.  All you have to go on is the HTML that comes down to the browser.  Using IE 8 you have a pretty good developer toolbar, which helps to track down what exactly has gone wrong.  But that only takes you part of the way; you still have to work out what’s actually wrong on the master page itself.  That can take a lot of guesswork and trial and error, trying to work out which SharePoint or ASP.NET controls are the source of the problem.

The Design Console

The standard design console in SharePoint is the one that appears when you edit a page without the publishing features activated (.e.g. in a regular team site)

In the standard master page this is generated by the DesignModeConsole control in the WSSDesignConsole placeholder, like this:

ContentPlaceHolder ID="WSSDesignConsole" runat="server">
       <wssuc:DesignModeConsole id="IdDesignModeConsole" runat="server"/>
ContentPlaceHolder>

I added this code into my master page but strangely the design console bar refused to show up on the page when I edited it. Eventually, by looking at the HTML source of the page when it was being edited, and working backwards from the master page, I figured out that the HTML rendered by this control starts with a <TR> tag.  This means it won’t work unless it’s sitting inside an HTML table.   Well of course using tables for layout is bad practice (although it’s something you find all over the place in SharePoint pages) so I had stripped out as much of the table-based layout as I could from the my master page.  As  a result, my placeholder was not inside a table and the design bar refused to render in the browser.

The fix was to embed the placeholder inside an HTML table like this:

<table width="100%">
       <tbody>
             <asp:ContentPlaceHolder ID="WSSDesignConsole" runat="server">
                    <wssuc:DesignModeConsole id="IdDesignModeConsole" runat="server"/>
             </asp:ContentPlaceHolder>
        </tbody>
</table>

Picture Library thumbnails and film strip views

With my custom master page, when I looked at a picture library, the thumbnails didn’t show up by default, and the filmstrip views just did nothing.  Only details view was showing. After some research, some reverse engineering on the HTML for the Picture Library views, and some trial and error, I found this was because I had to put in a PlaceHolderLeftActions control in the master page, and it has to be before PlaceHolderMain.  The PlaceHolderLeftActions control adds some essential Javascript in the page which the dropdown relies on.

Create View or Modify View pages Javascript breaks

When I created a new view or modified an existing view, the ViewNew.aspx or ViewEdit.aspx pages both displayed OK but the clickable plus sign icons next to “Group By”, “Total”, “Styles” etc. were missing, and the panels underneath them (which are normally hidden until you click the plus sign) were all visible.  I eventually found a clue in the documentation about SearchBoxEx that the problem is caused by a second copy of the ShowHideGroup Javascript function on the page when you have a search box on the master page.  To make things more difficult, this second copy is in Search.js so it’s not even listed in the source HTML of the page –  hard to track down!

To fix this, I took the Javascript of the ShowHideGroup function from the Search.js file and and put it in a <script> tag on the bottom of the master page.  This becomes the third definition of the function on the page, and overrides the second definition of the function from the search box.

Datasheet View locks up the browser

Another problem happened when I switched from standard view to datasheet view in a list.  Doing this caused the browser tab to lock up until I closed down the tab.  Fortunately this one wasn’t quite so bad because there were clues here and here; SharePoint does some fancy scripting to resize the element dynamically, but this doesn’t work once you move the navigation controls around.  I adapted the Javascript code to cope with the fixed-width div that I was using for the main content placeholder.

Scroll Bars and Overflow

If you have a fixed-width page design you might need to make use the CSS Overflow attribute to cope with cases where the main content gets really wide.  This could happen for example if you create a view of a list with a load of columns that can’t be wrapped around.  Here’s an example where the navigation has been moved from left to right, and when you view a document library with a lot of columns it runs over into the right hand navigation at the Content Type column:

Without overflow the view runs into the navigation

To get around this you can use the CSS Overflow attribute to force a horizontal scrollbar on the div that’s too wide, so it looks like this:

Overflow with IE7

Well this is better because at least you can scroll the view horizontally to see the missing columns.  But the field headers are not overflowing properly, and there’s a spurious vertical scrollbar on the right hand side as well.  This is a peculiarity of IE and the way its vertical scrollbar works.  That’s how the view displays in IE7, or in IE8 when the page is set to IE7 mode.  Switch the browser to pure IE8 mode and it looks much better:

Overflow In IE8

To get the master page to force IE 8 to use IE 8 standards when rendering the page, change this meta tag in the <head> of the master page like this:

<meta http-equiv="X-UA-Compatible" content="IE=8">

Can’t delete the master page

When you try to delete the custom master page from the master page gallery, you get an error:

This item cannot be deleted because it is still referenced by other pages

Microsoft says to work around this by hiding the master page but that’s not ideal.  Katrien De Grave has a better solution by copying the master page to a temporary folder and then deleting the folder.

Create a free website or blog at WordPress.com.