Title, description and navigation Link in List Settings Throws a 'value does not fall within the expected range' Exception

June 30th, 2009 by John Scott

Recently I migrated a site from Development to Testing and then to Production using the SharePoint Deployment Wizard ( http://www.codeplex.com/SPDeploymentWizard ) from CodePlex.  For the most part everything migrated over smooth.

I have a subsite that is for all the InfoPath Forms.   All the InfoPath forms are displayed in a web browser using forms services.  Each form has a workflow that is kicked off when a form is submitted.   This all still worked. 

But when you click on the 'Title, description and navigation' Link in List Settings for the forms libraries for the 2 sites where it was migrated to (testing and production) you get the following error…

Value does not fall within the expected range.   at Microsoft.SharePoint.SPListTemplateCollection.FindServerTemplate(Guid featureId, Int32 templateType)
   at Microsoft.SharePoint.SPList.get_ServerTemplate()
   at Microsoft.SharePoint.SPList.get_OnQuickLaunch()
   at Microsoft.SharePoint.ApplicationPages.ListGeneralSettingsPage.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

It turned out that the 'Office SharePoint Server Enterpirese Site features' feature wasn't activated in the new site. 

This wasn't the logical place for me to look at first since…

  1. I assumed the deployment tool would of activated it.
  2. The forms were rendering in a web page and could be submitted.  Only this one list setting link didn't work.

I hope if your having this issue, this helps you out.

Programatically using OOTB SharePoint Error Handling

April 10th, 2009 by John Scott

Okay, so if you get an error in your custom code that you want to handle using the "out of the box" SharePoint mechanisms, use the following lines of code…  

Make sure you only call the 'TransferToErrorPage' method if you are handling errors in the a user interface (web part, page, etc…).  Don't call that method in a workflow, event handler, etc…

//This will write to SharePoint's log files.

Microsoft.Office.Server.Diagnostics.PortalLog.LogString("Your Error Message");

//This will redirect you to SharePoint's error page.

Microsoft.SharePoint.Utilities.SPUtility.TransferToErrorPage("Message to display on the page");

 

 

Turn off the "Powered by Forms Services" Logo on InfoPath Web Forms

March 19th, 2009 by John Scott

I don't understand why Microsoft stuck that logo on all the web based InfoPath forms by default.  I could maybe see the reasoning if Forms Services was free and came with WSS but it's a freakin MOSS Enterprise Feature.  Go figure.

Anyway, on my quest to find out how to turn it off, I came across a Microsoft Hotfix that is suppose to resolve this issue.  Not the way to go.  The hotfix must of been meant for a version of InfoPath forms services / MOSS prior to SP1. 

Then I found this blog by Michael Yeager: Using STSADM to set Form Services Properties (http://blogs.msdn.com/michael_yeager/archive/2008/12/01/using-stsadm-to-set-form-services-properties.aspx) that explained some STSADM options for Form Services.

To turn it off run, you simply run… stsadm -o setformsserviceproperty -pn AllowBranding -pv false

Thanks Again MY

Forcing the download of a SharePoint Document

December 19th, 2008 by John Scott

Recently, I implemented MOSS 2007 as a web content manager for a client's public website.  One of the things they wanted was the ability to force the "Save As…" dialog for certain documents (in this case, they were media files). 

The requirements were to get this working for Internet Explorer 7 and FireFox 2 and above, although I think this will work for most if not all the browsers.  We tested on a couple others but I don't remember for sure if Chrome and/or Safari were on that list.

The code below assumes that the web path to the file that needs to be downloaded is passed in via the 'file' URL parameter.

void Page_Load(object sender, System.EventArgs e)
{
   
if (Request.QueryString["file"] != null)
      DownloadFile(Request.QueryString[
"file"].ToString());
}

private void DownloadFile(string fileName)
{
   
string path = System.Web.HttpContext.Current.Server.MapPath( fileName );
   
string name = System.IO.Path.GetFileName( path );

    Microsoft.SharePoint.SPFile spFile =
        Microsoft.SharePoint.SPContext.Current.Web.GetFile(fileName);

    Response.ClearHeaders();
    Response.ClearContent();

    Response.ContentType = "application/force-download";
    Response.AppendHeader(
"content-disposition", "attachment; filename=" + name );
    Response.BinaryWrite(spFile.OpenBinary());
    Response.End();
}

Off the top of my head, I can think of 3 different ways you could use this code. 

  1. Using SharePoint Designer, put this code in the code behind for a page in the site.
  2. Create a page in visual studio, use a web deployment project to compile it to a DLL, Deploy the web page somewhere under the _layouts folder, and deploy the DLL to the Bin or the GAC.  See /jscott/archive/2008/04/15/integrating-asp-net-2-0-web-pages-into-sharepoint-2007.aspx for more details
  3. Create a HttpModule that will execute the above code.

To keep it simple for the non-technical content administrators, we went with option 1.  This option is my least favorite technically but I think the easist for the end user.  We create a SaveFile.aspx page in SharePoint designer and stuck it in the top most level of the root site (NOT in the pages library)

So the file is at www._company_.com/SaveFile.aspx.

We then would have the content administrators link to the document like they normally would throught the publishing GUI.  The URL would be something like, www._company_.com/site1/Documents/Medai.wmv

Then we would have them insert /SaveFile.aspx?file= right after www._company_.com resulting in www._company_.com/SaveFile.aspx?file=/site1/Documents/Medai.wmv

Hope this helps

Son of the The Dreaded 'Server Out Of Memory' Exception – 'The data source control failed to execute the insert command' Exception

July 12th, 2008 by John Scott

Here is the exception details…


Server Error in '/' Application.


The data source control failed to execute the insert command.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: Microsoft.SharePoint.WebPartPages.DataFormWebPartException: The data source control failed to execute the insert command.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

If you are getting this exception and you are using a Custom List Form (DataFormWebPart) to add/edit a list item and the user who is adding/editing the list item is anonymous and…

  1. A workflow is set to start whenever a list item is created and/or updated OR
  2. A custom event receiver is handling the created or updating event for that list

You are really getting The Dreaded 'Server Out Of Memory' Exception.  A different exception is being thrown because you are using a Custom List Form but it's still the same problem under the hood.

To verify this, try to add/edit an item in your list using the default list editor.  If you get a 'Server Out Of Memory' Exception, read this.

The Dreaded 'Server Out Of Memory' Exception

July 12th, 2008 by John Scott

Here is the exception details…


Server Error in '/' Application.


Server Out Of Memory

There is no memory on the server to run your program. Please contact your administrator with this problem.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.OutOfMemoryException: Server Out Of Memory

There is no memory on the server to run your program. Please contact your administrator with this problem.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

If a list item is being created or edited by a user who is anonymous and…

  1. A workflow is set to start whenever a list item is created and/or updated OR 
  2. A custom event receiver is handling the created or updating event for the lsit 

[We could probably draw the conclusion that any situation where a custom event receiver or a worflow is executed by the anonymous user will fail.]

So here is the bad news… as of right now, I have never found a fix for this.  I had opened a support case with Microsoft and they acknowledged it was an issue but never gave me any confirmation if and when it will be fixed.

And here is the worse news… if you are getting this error because you associated a workflow to a list (reason #1 above), this list will never be able to have an item created/updated by an anonymous user.  I told the workflow not to run when an item is created or updated.  Didn't work.  I deleted the workflow.  Didn't work.  I tried to back up the list as a template and restore it (with and without the data).  Didn't work.  I tried to go into the database and delete any associations I could find.  Didn't work.  I tried a few other things but nothing worked.  

I eventually had to recreate all my lists (close to 30) and recreate all the workflows for them, making sure not to set them up to start when an item is created or updated.  In my case, I only wanted to start the workflow when an item was created so I ended up putting a Yes/No field in every list indicating whether or not the workflow had been started for it and default it to no.  I then created a console application that that would get all list items that had that new field set to 'No' and fire off the workflows manually.  I scheduled the console application to run as the SharePoint Administrator in 30 minutes intervals throughtout the day. 

In hind sight, If I would of known about this issue up front, I would of created a custom web part or ASP.NET page to do the data entry and just did the actual list manipulation with elevated privelages.

Eventually Microsoft got back to me with this workaround… Use Forms Based Authentication instead of Windows Authentication and create a 'Visitor' Account that anonymouse users would use (without them knowing).  Anonymous users would automatically get logged in as 'Visitor' by a HttpModule.  The project had already come to an end so I never tried it.  But here it is for your viewing pleasure…

Here is a sample of an HTTP module that can be set up with forms based authentication (FBA) so that it logs you in as a visitor account by default. This enables you to control the visitor account just like a normal user account (since it is authenticated), and is transparent to the Sharepoint server.

This code has not been extensively tested, so don't deploy straight to your production environment, test it out thoroughly first. Be sure to set up an account called "Visitor" (It's hard coded that in the sample).
//=================================
using System;
using System.Security;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
 
 
namespace HTTPAnonAuth
{
    class AnonModule : IHttpModule
    {
 
        public void Init(HttpApplication app)
        {
           
            app.AuthenticateRequest +=
                (new EventHandler(this.Application_AuthenticateRequest));
            app.PreSendRequestHeaders +=
                (new EventHandler(this.Application_PreSendRequestHeaders));
           
        }
 
        private void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            if (app.User == null)
            {
                string[] roles = new string[1];
                roles[0] = "GuestUser";
                GenericIdentity id = new GenericIdentity("Visitor","Forms");
                GenericPrincipal p = new GenericPrincipal(id, roles);
 
                app.Context.User = p;
            }
 
 
        }
 
        private void Application_PreSendRequestHeaders(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            if (app.Response.RedirectLocation != null)
            {
                if (app.Response.RedirectLocation.Contains("AccessDenied.aspx?Source")
                        && app.User.Identity.Name == "Visitor")
                {
                    app.Response.Redirect("/_layouts/login.aspx?ReturnUrl=" + app.Request.RawUrl);
                }
            }
 
 
        }
 
        public void Dispose()
        {
        }
    }
}
//=================================
  

If you do end up using the HttpModule route OR find a better workaround OR find a fix, please let me know about it.

Creating a Basic WebPart and Integrating it into SharePoint 2007

April 20th, 2008 by John Scott

A web part is an object that displays information in SharePoints.  A web part can be added to any SharePoint page that has at least web part zone.  Sharepoint has some standard web parts out of the box, but typically you will need to write a custom web part to display any non-SharePoint data or to display SharePoint data in a non-SharePoint way.

Prerequisite


Reflector for .NET
You will need to be able to get the key information for you’re the assembly that contains your WebPart.  The easiest way to do this is to drop the compiled assembley into Reflector for .NET.  The information will be displayed at the bottom of the screen.  This can be downloaded from http://www.aisto.com/roeder/dotnet/.

Edit Permissions to the SharePoint Site Folder
You will need to be able to modify the web.config file for your site. This is typcially located at the {Local_Drive}:InetpubwwwrootwssVirtualDirectories/{Port or site}/bin

Write Permissions to the Bin Folder of the SharePoint Site
You will need to be able to deploy your class library assembly to site’s bin folder.  This is typcially located at the {Local_Drive}:InetpubwwwrootwssVirtualDirectories/{Port or site}/bin

Creating the Web Part

Create the Class Library Project
 In Visual Studio 2005, create a new class library project.   Right click on the project in solution explorer and select add a new item.  Then choose to add a new class.
Creating to the WebPart
Add the following using statements.
.
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

Modify the class so it inherits from System.Web.UI.WebContorls.WebParts.

Override the CreateChildControls method and add the code to create the visual objects your WebPart will display.

Your class should resemble the following.

using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace ColdCypress.Examples.SharePoint.Ex1
{
 public class Ex1 : System.Web.UI.WebControls.WebParts.WebPart
 {
  protected override void CreateChildControls()
  {
   base.CreateChildControls();

   Label lbl = new Label();
   lbl.Text = “This is an example web part”;
   Controls.Add(lbl);

   Literal litBr1 = new Literal();
   litBr1.Text = “<br />”;
   Controls.Add(litBr1);

   TextBox txt = new TextBox();
   Controls.Add(txt);

   Literal litBr2 = new Literal();
   litBr2.Text = “<br />”;
   Controls.Add(litBr2);

   Button btn = new Button();
   btn.Text = “Test”;
   Controls.Add(btn);
  }
 }
}

Modifying the AssemblyInfo.cs
Add the following using statements.

using System.Security;

Next add the following line of code.

[assembly: AllowPartiallyTrustedCallers()]

Singing the Assembely
Right click on the class library project and select Properties from the context menu. 

Select the Signing tab on the left. 

Check the Sign the Assembely option.

In the `Choose a strong key file:’ drop down, select <New.>.

Enter key.snk for the key name and uncheck the `protect my key file with a password’ checkbox.

Compile the assembly.

Deploy It 

Deploy the assembly to the SharePoint site’s bin folder.  This is typicall located at {Local_Drive}:InetpubwwwrootwssVirtualDirectories/{Port or site}/bin.

Editing the SharePoint Site’s Web.config

Open the SharePoint site’s web.config for editing. 

Registering your WebPart as a SafeControl

Use relector to get the assembly’s information and add the following between the <SafeControls></SafeControls> tags substituing your assembly’s informaiton.

<SafeControl Assembly=”{Assembly Name}, Version={Assembly Version}, Culture=neutral, PublicKeyToken={Key}” Namespace=”{WebPart’s namespace}” TypeName=”*” Safe=”True” AllowRemoteDesigner=”True” />

Increasing the trust level

Modify the trust level to WSS_Medium.  It should look like the following.

<trust level=”WSS_Medium” originUrl=”" />

Adding that WebPart to SharePoint

Registering your WebPart with SharePoint

From the top level site (not from any of the child sites).

1. Select “Site Actions”/”Site Settings”

2. Click the Web parts Link in the middle of the page

3. Click the “New” link at the top of the list.

4. Find your web part in this list, check the box in front of it and click “Populate Gallery”

Your web part should now be in the gallery list.

Add the WebPart to the screen

1. Navigate to the page you want the part on.

2. Select “Site Actions” / “Edit Page”

3. Click “Add Web Part”

4. Find your web part in the displayed list and click the check box

5. Click “Add”

6. Your web part should now be displayed on the page.

7. Click “Exit Edit Mode” to save the change

Your web part should now be displayed.

Integrating ASP.NET 2.0 Web Pages into SharePoint 2007

April 15th, 2008 by John Scott

One of the most useful features for developer’s in SharePoint 2007 is the ability integrate ASP.NET 2.0 pages into SharePoint 2007.  

Consider the following scenerios…

  1. A company has one or more stand alone ASP.NET 2.0 applications that uses a data store other than SharePoint.  They would like to integrate it into SharePoint but don’t want to redo the application to use SharePoint’s data store.  You could modify the application so it loads up inside SharePoint using the correct SharePoint master page.  The application can still pull it’s information from any data store it wants to it will only be using SharePoint to host the application.
     
  2. An application is written where all the data is stored in SharePoint but you want a specialized display of it.  You could create an ASP.NET 2.0 page that loads the data from SharePoint and then display it however you like. 

Prerequisites

Microsoft.SharePoint.dll

SharePoint’s .NET dll that contains the SharePoint objects.  At a minimum, this is needed to use the correct SharePoint master page.  This will be located on the machine that has SharePoint installed.  If your development machine does not have SharePoint installed, you will need to find this dll and copy it to s folder local on your machine.

Visual Studio Web Deployment Projects Add-In Installed

You will need to download and install a free Visual Studio add-in that enables an ASP.NET 2.0 website to be compiled to a single dll.  You will need to compile your website to a single dll to deploy the assembely to SharePoint. 

Write Permissions to the Bin Folder of the SharePoint Site

You will need to be able to deploy your website’s assembely to site’s bin folder.  This is typcially located at the {Local_Drive}:InetpubwwwrootwssVirtualDirectories/{Port or site}/bin


Write Permissions to the SharePoint’s Layouts Folder

You will need to be able to deploy your aspx pages to SharePoint’s Layout folder.  This is typically located at {Local_Drive}:Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATELAYOUTS

Create the ASP.NET Page

Create the ASP.NET Website Project

 In Visual Studio 2005, create a new website project.   Right click on the project in solution explorer and select add a new item.  Then choose web form and name it something that makes sense to the project.

Changes to the ASPX Page

Replace the system generated contents of the file with the following.

 

 <%@ Page Language=”C#” MasterPageFile=”" AutoEventWireup=”true” CodeFile=”example.aspx.cs” Inherits=”example” Title=”Example “ %> <asp:Content ID=”contentMain” ContentPlaceHolderID=”PlaceHolderMain” Runat=”Server”> 
    
//Page markup goes here
</asp:Content> 
 

The 2 most important parts of this code are the MasterPageFile=”" in the Page directive and the ContentPlaceHolderID=”PlaceHolderMain” attribute in the <asp:Content> tag.

Changes to the Code Behind File

Add the following using statements.

.

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

 

Override the pages OnPreInit method.  This is where you will tell it to use the SharePoint master page.  It should look like the code sample below.
 

protected override void OnPreInit(EventArgs e)
{
    
base.OnPreInit(e);
    
SPWeb web = SPControl.GetContextWeb(Context);
    
MasterPageFile = web.CustomMasterUrl;
}  

Deploying the Project

Right click on the project in solution explorer and select `Add Web Deployment Project.’.  Make note of the location you specify in the dialog that appears.  This is where you will get the files you need to copy to the machine running SharePoint.

 

Right click on the new deployment project and hit rebuild.  This will compile your website to a single dll (not including any other dll’s you might of referenced) and place the whole website to the location you specified when you created the web deployment project.

 

Copy all the dll’s from the location you specified’s debug/bin or release/bin (depending on how you built your site) folder (excluding the Microsoft.SharePoint.dll) and paste them to the bin folder for the SharePoint web application on the machine running SharePoint.  Note: The dll’s could also be deployed to the GAC so all SharePoint web applications on the server can use the pages.  This would require signing the dll.

 

Copy the example.aspx from the location you specified’s debug or release (depending on how you built your site) folder and paste them to the layouts folder under where you installed SharePoint.

 

Viewing the Page in SharePoint 

From the site you installed the dll’s in and all of the child sites created in that site, you can access your pages by going to http://{SiteName}/ _layouts/pageName.aspx.