SharePoint ULS Logging Permissions Required (Not Logging)

log

Is your custom ULS logging not appearing in the SharePoint ULS logs?

I have had the (sometimes torturous) pleasure of developing custom SharePoint solutions for a number of years now and one of the issues I encounter from time to time is when my custom ULS logging is not being written to the standard SharePoint ULS logs. I usually encounter this when most other developers don’t. This is primarily because I always build out my SharePoint development environments using several service accounts in an effort to replicate the target production environment as much as possible. Doing this allows me to catch and reproduce security related design and coding issues that would otherwise go undetected in my development environment, but are most certainly exposed in QA or Production. This logging issue (entries missing) is likely to occur when using a web application pool service account that differs from the farm account. This is simply a best practice that all developers should follow, but many don’t out of laziness.

So, to successfully log to the SharePoint ULS logs the application pool service account must be in the Performance Log Users group in Active Directory. This group is located in the Builtin folder in Active Directory Users and Computers. Any SharePoint service account that executes your custom logging will need this access.

Cheers!

How to correct: The security validation for this page is invalid (FormDigest)

How to correct the security error on a custom SharePoint web page:
The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again.

Short Answer:

Use SPUtility.ValidateFormDigest() and do not use AllowUnsafeUpdates.

A Less Desirable Solution (but more commonly used)

One way to get around this issue is to set the web’s (SPWeb) AllowUnsafeUpdates property to true. This is not ideal, especially when there is a more secure option.

A Better Solution

This method configures the web page to properly cache and revalidate the necessary credentials preventing the “security validation” error noted above. And, there is no need to set the AllowUnsafeUpdate spweb property to true.
Coding Steps:
Register the SharePoint web controls assembly in your aspx. Place this at the top of the .aspx file:
<%@ Register TagPrefix="SharePoint"
Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Place the FormDigest control on the .aspx page (I place it near the end of the page):
<SharePointWebControls:formdigest id="FormDigest1" runat="server" />
In your page code-behind, call the ValidateFormDigest() method during the page OnInit() event to revalidate the page security. It is important to call the ValidateFormDigest method as early as possible in the page cycle.
using Microsoft.SharePoint.Utilities
protected override void OnInit(EventArgs&nbsp;e)
{
	if (Page.IsPostBack)
	{
		SPUtility.ValidateFormDigest();
		base.OnInit(e);
	}
}
That’s it. Your custom SharePoint page should now successfully pass the security validation. It is also important to remember that you will need to also add the FormDigest control and call the ValidateFormDigest method in any custom user controls that are performing updates to SharePoint data.

References:

SharePoint Feature Activation Extension Methods

Extend your SharePoint Features collection with an IsActivated, EnsureActivated, and EnsureDeactivated methods. These extensions will be available for activating or deactivating features for a Web, Site Collection, Web Application, and Farm.

public static class SPFeatureCollectionExtensions
{
  public static bool IsActivated(this SPFeatureCollection features, Guid featureId)
   {
    return features.Cast<SPFeature>().FirstOrDefault(f => f.DefinitionId.Equals(featureId)) != null;
   }
  public static bool IsActivated(this SPFeatureCollection features, string featureId)
   {
    return IsActivated(features, new Guid(featureId));
   }
  public static void EnsureActivated(this SPFeatureCollection features, Guid featureId)
  {
    if (!IsActivated(features, featureId))
      features.Add(featureId);
  }
  public static void EnsureActivated(this SPFeatureCollection features, string featureId)
  {
    EnsureActivated(features, new Guid(featureId));
  }
  public static void EnsureDeactivated(this SPFeatureCollection features, Guid featureId)
  {
    if (IsActivated(features, featureId))
      features.Remove(featureId);
}
public static void EnsureDeactivated(this SPFeatureCollection features, string featureId)
  {
    EnsureDeactivated(features, new Guid(featureId));
  }
}

Usage Examples:

web.Features.IsActivated("999974A3-E65F-4426-AC75-FAD64EF49999");
site.Features.EnsureActivated("999974A3-E65F-4426-AC75-FAD64EF49999");
webApp.Features.EnsureActivated("999974A3-E65F-4426-AC75-FAD64EF49999");
farm.Features.EnsureActivated("999974A3-E65F-4426-AC75-FAD64EF49999");

Create Custom SharePoint Web Service WSDL and Disco ASPX Files Automatically

I just completed a SharePoint developer tool called SPDev.exe. The initial purpose of this utility is to auto-generate the web service WSDL.aspx and Disco.aspx files needed for a custom SharePoint web service.

icon_shout Automatically generate your SharePoint disco.aspx and wsdl.aspx files in seconds!
icon_shout No need to manually copy or deploy your .asmx first!
icon_shout No manual editing!
icon_shout No Disco.exe needed!
icon_shout Automatically recycles the application pool (ensuring the newest assembly is loaded)!
icon_shout Automatically deploys the final SharePoint web service files (using the -deploy option)!
icon_shout No UI to enter data each time.  A command tool you can script for fast, consistent re-use!

After having to manually modify the disco.aspx and wsdl.aspx files by hand for the last three years, I finally found it tedious enough to create this utility.  There are other tools out there, but they require you to enter information into a Windows UI, they are not script-able, and still felt to tedious for me.  Call me lazy.  :)  Time is money.  This tool is a command line utility.  Simply execute the SPDev.exe command and your MyServiceDisco.aspx and MyServiceWsdl.aspx files are immediately ready for deployment.  SPDev also allows you to script the process.  Create a .cmd or .bat file and you’ll never have to enter any parameters again.  Another big benefit is you don’t need to use the Disco.exe utility since SPDev uses IIS and .NET instead which will always be on your development machine – since you are developing for SharePoint.  And, there are no temp files are generated (unless you want them generated).

Documentation for this utility is on my blog here: https://blog.crsw.com/spdev/

SharePoint RunWithElevatedPrivileges Example

The following example sends an email using elevated privileges.  This will elevate the privileges to execute using the service account.

The SPSecurity.RunWithElevatedPrivileges method taks a delegate method as its argument and executes that code with the service account.

SPSecurity.RunWithElevatedPrivileges( 
    delegate()
    {
        // Your code needing elevated permissions goes here.
    }
)

Example:

public void SendEmail(Email email) 
{ 
   SPSecurity.RunWithElevatedPrivileges(delegate() 
   { 
        SmtpClient mail = new SmtpClient();    MailMessage message = new MailMessage(); 
        message.From = new MailAddress(this.SenderAddress); 
        message.To.Add(email.To); 
        message.IsBodyHtml = email.IsHtml; 
                    
        if (!string.IsNullOrEmpty(email.Cc))            
            message.CC.Add(email.Cc); 
                    
        if (!string.IsNullOrEmpty(email.Bcc))            
            message.Bcc.Add(email.Bcc); 
                    
        if (!string.IsNullOrEmpty(this.ReplyToAddress))             
            message.ReplyTo = new MailAddress(this.ReplyToAddress); 
                    
        if (!string.IsNullOrEmpty(email.Subject))            
            message.Subject = email.Subject; 
                    
        if (!string.IsNullOrEmpty(email.Body))            
            message.Body = email.Body; 

        mail.Host = this.CentralAdminOutboundServerAddress; mail.Send(message); 
    });
}

SharePoint Module tag

Module:

– The Module tag is used to deploy files ‘logically’ to SharePoint when the given

feature is activated. This means they liv in the database, not physcally on disk

in the SharePoint 12 hive.

Module Attributes:

  • Path is relative to the current web site.

  • Url – is the relative url to the web site root (blank) or to the document library (i.e. "MyLibrary").

    • URL – This is the target location for your file. Effectively, this is the relative URL that points to the list that you want your files to be placed in. The relative url to the web site.

  • Path – this is the relative location between the feature and the physical file that you want to install. So if your file is in a sub-folder of the featue called "Images" then you would place "Images" as the Path. If your file is in the root feature folder (next to your feature.xml) then the "Path" would be an empty string ("").

  • RootWebOnly – this is a boolean value. If set to true, then this will only install when activated at the top-level site collection.

File Attributes:

  • Url is relative to the web site and contains the name of the file (i.e MyPage.aspx).

How to Create a Custom List with a Custom Content Type and Views

 

Steps to creating a new list with custom views and a custom content type:

Why use a custom content type?

  1. Create your site columns (fields) and content type, and deploy it to your development farm.
  2. Create a new generic Custom list on any site of your choosing.  Enable content type management on the list.
  3. Remove the default Item content type from the list.
  4. Add your new custom content type to the list, it should be the default.
  5. Customize your views as needed.
  6. Use the SharePoint Solution Generator to generate a List Definition for your new list.  The resulting generated Visual Studio project will contain a folder for the list that contains several form files (DispForm.aspx, EditForm.aspx, and NewForm.aspx) and an .aspx file for each view you created such as AllItems.aspx.  You will also have a schema.xml file which contains the content type definition, the views definition, and the fields section.  Leave the Fields and Views nodes/sections alone as they contain the definitions you defined.
  7. In the schema.xml file, in the ContentTypes node you will find a ContentType node defining your custom content type.  Comment (or delete) this entire node.  We will add this content type to the list via code instead of defining its association here declaratively.

The Major Task content type is commented out here because we are going to add
it programmatically via the ListInstances feature receiver.  This allows us to
properly promote all the fields in the content type to the list and enable
content type management on the list much more easily.

Logging to the SharePoint Log Files

Thanks to Brad Younge for sharing this a while back.  Below is an example on how to write to the SharePoint log files (located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\LOGS folder).

catch(Exception e) 
{
   Microsoft.Office.Server.Diagnostics.PortalLog.LogString("Exception: {0} - {1}", e.Message, e.StackTrace);
}

You’ll likely want to prefix your log entries with a date and time stamp.

DisableLoopbackCheck – Unauthorized (401.1) Exception calling Web Services in SharePoint

Published on 10/14/2008

After upgrading to .NET Framework 3.5 Service Pack 1 on my SharePoint web servers I began to get the following Unauthorized exception.

Type: WebException, Exception Message: The request failed with HTTP status 401: Unauthorized.

This error really has nothing to do with SharePoint, and is really just an IIS web services related item.  This problem is due to an added bit of security included in the .NET Framework 3.5 Service Pack 1.  Here is the Microsoft KB article explaining the issue and how to work around the problem.  This Microsoft article refers to the problem coming after applying other service packs for Windows XP and Server 2003, but .NET Framework 3.5 Service Pack 1 is also now using this same bit of added security – the loopback check.

You will likely not encounter this problem on a single web server configuration and if you are using the server name to access the web site.

However, most enterprise SharePoint farms consist of at least two web servers that are load balanced.  This is where the problem exists.

Likely Cause:

  • You are calling your web services from your web servers using the load-balanced URL, not the server name.

This isn’t a bug.  There was a security fix built into the Windows networking stack that prevents a machine name that resolves to the loopback address from accepting a connection unless that machine name matches the NETBIOS name.

One option is to use the server name instead of the load balanced IP.  This should remedy the problem.  However, the standard method to apply configuration changes across a SharePoint farm is via SharePoint solution files.  This usually requires the configuration entries to be the same across all the web servers in the SharePoint farm, and using the load balanced URL is likely the most appropriate.

Suggested configuration changes to resolve this:

  • Add the DisableLoopbackCheck registry entry discussed in this Microsoft KB article.  Note: you will need to reboot your server before the DisableLoopbackCheck takes effect.
  • Be sure to add your load balanced host name for your web farm to the Hosts file on each front end web server.  Use the loop-back IP address (127.0.0.1).  This will ensure that each web server looks at itself to access the web services preventing any trips back out to the load-balancer – and possibly calling the web service another web server in the farm.  This will be much less efficient.
    • If this problem appeared to be inconsistent (sometimes erroring, sometime successful), this is most likely due having multiple web servers.  The call to the web service will be successful if by chance the load balance redirected the call to the same (self) web server to access the web service.  It will fail when trying to call across to a different web server.

References:

I’m mentioned (twice) in an MSDN Magazine article – SWEET!

It is an exciting moment to have two articles on my blog discussed and referenced in the May 2008 edition of MSDN Magazine.  Thanks to Ethan Wilansky for a great article in MSDN Magazine, and for making this happen!

MSDN-Mag-May2008CoverHere is the link to the MSDN Magazine article:
MOSS 2007: Automate Web App Deployment with the SharePoint API

Here are the links to two of my blog articles that are referenced in this MSDN Magazine article:
How To: Create a SharePoint Solution for an InfoPath Form 
How To: Modify the web.config file in SharePoint using SPWebConfigModification

Also, Shawn Feldman, a coworker, was mentioned for his terrific work in deploying SQL Reports.