Home | Blog | Screencasts | Projects
# Saturday, October 17, 2009

I came across a rather interesting problem the other day (interesting enough to blog anyway).

We have a development server that we are building some SharePoint web parts on, all of the developers have local admin rights to the box. We asked a normal user to have a look at some functionality that should be available to them, but when they browsed to the site they got a 403 forbidden error message. However when the developer requested that very same page it rendered fine. The weird thing was that if the original user (not the dev) then requested the page once again, it all rendered fine.

We had a look in the SharePoint Logs and found that the assembly in the bin folder was denying access to the non developer, but once a dev hit the box the assembly was loaded fine and stayed in memory until the app pool was recycled.

So the solution was to grant all users access to the bin directory. This wouldn’t be an issue in production because we will eventually GAC deploy these assemblies.

But I did think it was a fun little exercise to track down the root cause.

Saturday, October 17, 2009 4:30:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Tip | Work
# Tuesday, September 22, 2009

Windows 7 contains a really nice tool called the Problem Steps Recorder:

 

It can be found via the Windows 7 start menu by typing ‘problem step’

image

 

Once it’s running you get the following UI:

 

 image

 

From here you can record all the clicks and keystrokes that your undertaking, you can even add comments to parts of your display. It finally saves the file as a zip file, which contains a .mht file that can be viewed in your browser. This output file will list things like version numbers of applications running as well as a range of screenshots of each major activity recorded.

 

Now this is all well and good for sorting your mum’s computer problems, but as an IT pro who has had to document some awfully boring processes, I really think this tool will help me the next time I need to document the install of some software, or some mundane configuration change.

Tuesday, September 22, 2009 2:25:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Tip | Windows 7

I’ve been working on a project that involves implementing a blogging system inside SharePoint, the out of the box SharePoint blogging system was unsuitable and the Community Kit for SharePoint didn’t solve our issues.

So the system we developed was lightly based on the open source .NET Blog Engine which includes comprehensive support for the MetaWebBlog API. This API allows a interaction with a blogging system so that blog posts can be added, deleted and updated, but it also provides provisions for managing things like categories and comments.

The main motivation for supporting the MetaWebBlog API is Windows Live Writer (WLW) this great tool really makes publishing to a blog a simple task. So I happily added the MetaWebBlog API and quickly found that windows live writer doesn’t support windows authentication. WLW supports a nice feature called Really Simple Discovery (RSD) where it can just be pointed to a blog’s home page and it can get all the configuration needs. By not supporting windows authentication we lost the auto discovery features.

 

So I could still enable anonymous access to the MetaWebBlog.axd and wlwriter.xml (a file that tells WLW what capabilities your blog has), so now with some manual steps in WLW I could select the MetaWebBlog API and give it the url to use. My next problem was that my blogging system was all based around windows authentication. Every user has a blog that is based around their network credentials, I needed my metawebblog API implementation to validate the user to the windows network:

 

With the following P/Invoke definitions:

 

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
 int dwLogonType, int dwLogonProvider, ref IntPtr phToken);                

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
 int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); 
 

Now in all of my metawebblog API calls I could use a method like:

 

 

                string username = string.Empty;
                string password = input.Password;
                string domain = string.Empty;

                if (input.UserName.Contains(\\))
                {
                    string[] usernameParts = input.UserName.Split('\\');
                    if (usernameParts.Length > 1)
                    {
                        domain = usernameParts[0];
                        username = usernameParts[1];
                    }
                }
                else
                {
                    username = input.UserName;
                }

                IntPtr tokenHandle = IntPtr.Zero;

                bool returnValue = LogonUser(username, domain, password,3, 0, ref tokenHandle);

                if (returnValue == false)
                {
                    //error not a valid user .. return
                    throw new MetaWeblogException("11", "User authentication failed");
                }
                
                    if (tokenHandle != IntPtr.Zero)
                        CloseHandle(tokenHandle);

This code will return an invalid authentication message to WLW if the user doesn’t provide the correct domain, username and password (you could easily remove the need for a domain, I needed to keep it).

I’d like to say that its all good but really end users won’t go to the effort of following steps to configure WLW, the RSD is a killer feature in making web blogs accessible to end users. Fingers crossed that WLW will support windows authentication in a future version.

Tuesday, September 22, 2009 1:32:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
code | Tip
# Saturday, April 25, 2009

By default when you edit the tool part settings of a SharePoint web part and you click on the ‘…’ if the property is a string, you will get the default property builder:

 

image

 

Clicking the above ‘…’ will launch the default string property builder:

Standard SharePoint Property Text Builder

 

This popup is actually the ‘zoombldr.aspx’ page located in the _layouts virtual directory.

 

There are a few problems with this builder, well it’s not so much the builder, the string property’s of the web part are serialised in a manner that strips out carriage returns. So if you were to spend time formatting the contents of this dialog, it will get wiped out when you save the contents. This is most apparent when you edit the XSLT of the core search results web part.

 

How can you override this property?

 

The key is to make use of the HtmlDesigner attribute on your web part property. There are two ways to make use of the attribute, the first way is to explicitly define the page which you want to load (i.e. change ‘url to page’):

 

        [System.Web.UI.WebControls.WebParts.WebBrowsable(true),
        System.Web.UI.WebControls.WebParts.WebDisplayName("Template"),
        System.Web.UI.WebControls.WebParts.WebDescription(""),
        System.Web.UI.WebControls.WebParts.Personalizable(
        System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared),
        System.ComponentModel.Category("Settings"),
        System.ComponentModel.DefaultValue("")
        ]
        [HtmlDesignerAttribute("url to page", DialogFeatures = "dialogHeight:500px;dialogWidth:650px;help:no;status:no;resizable:yes")]
        public string CustomProp
        {
            get { return customProp; }
            set { customProp = value; }
        }

 

Notice that you could also modify the parameters that get passed into the JavaScript popup window creation script, in the case above I have made the popup window larger than the default size. The problem with the above approach is that the URL that gets passed as the first parameter to the HtmlDesignerAttribute must be a constant value, since it’s used in the attribute declaration. However Microsoft have provided us with a nice way to change this behaviour.

 

        [System.Web.UI.WebControls.WebParts.WebBrowsable(true),
        System.Web.UI.WebControls.WebParts.WebDisplayName("Template"),
        System.Web.UI.WebControls.WebParts.WebDescription(""),
        System.Web.UI.WebControls.WebParts.Personalizable(
        System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared),
        System.ComponentModel.Category("Settings"),
        System.ComponentModel.DefaultValue("")
        ]
        [HtmlDesignerAttribute(BrowserBuilderType.Dynamic, DialogFeatures = dialogHeight:500px;dialogWidth:650px;help:no;status:no;resizable:yes")]
        public string CustomProp
        {
            get { return customProp; }
            set { customProp = value; }
        }

 

I’ve now added the BrowserBuilderType.Dynamic option. To get this to work, we now need to override the GetCustomBuilder method of your web part:

 

         protected override string GetCustomBuilder(stringpropertyName)
        {
            if(propertyName == "CustomProp")
            {
                return"url.aspx?"+ "some custom params";
            }
            return base.GetCustomBuilder(propertyName);
        }

 

Now every property that has BrowserBuilderType.Dynamic passed into the HtmlDesignerAttribute will get passed into the GetCustomBuilder method, this gives you the chance to create a URL that passes parameters to your custom builder page.

 

Ok, so now you got the web part covered, what about the JavaScript that needs to run on your custom property builder page?

 

The best thing to do is to look at the current zoomdldr.aspx page, when the page loads you can get the current arguments from:

 

window.dialogArguments

 

Then to save the arguments, save the string value back to:

 

window.returnValue

 

 

Now that you’ve got a fair idea about creating custom property builders, you can create builders that are specific to you needs, below is a screenshot of a property builder form that lets the user enter some c# code that gets compiled an injected into the web part, the need was to provide a nice interface that the end user (i.e. a programmer) could use. The property builder uses the EditArea control to format the code nicely. The user can then click the compile button which will do a compilation of the code and report any errors. I’ve also added some JavaScript code to get around the removal of the carriage return characters, which was a major pain point for us.

 

Custom Property Builder

 

 

This approach will give you the power to create property builders that more closely suit your needs and goals.

Saturday, April 25, 2009 12:44:51 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
code | Sharepoint | Tip
# Thursday, March 19, 2009

If you are using the BDC in your MOSS application, you may have noticed that the AUDEvent table in the SSP database can grow quite large and quickly. You might think that the stsadm command –o trimauditlog would do the trick in reducing this table, but in fact it does not work for the SSP database only content databases.

 

You can specify the audit setting in the Application Definition File. Simply add the Property ‘Audit’ to your Entity’s Properties section:

 

<Entities>
    <
Entity EstimatedInstanceCount="0" Name="dbo.Sales">
      <
Properties>
        <
Property Name="Audit" Type="System.Boolean">false</Property>
      </
Properties>

The setting of false will prevent any audit entries being written to the AUDEvent table.

Thursday, March 19, 2009 9:48:23 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
BDC | MOSS | Sharepoint | Tip

A while ago I wrote about a simple method to give web parts an easy to configure design experience. The method I came up with made use of the ASP.NET Page method ParseControl.

In my original example, the developer had to do some manual work like finding the templated control once it was added to the page, this was a tedious and ugly design. At the time it was more of an idea rather than something that I had build seriously, but recently I’ve put a bit more thought into the idea of web parts with a configurable UI template.

I’ve built on the original example, but with the goal of abstracting the ParseControl and ControlBinding implementation.

This example simply writes a title and description:

 

image

 

We want to give end users the ability to change the way this title and description look without any web part code changes.

This is done via a template, which is a property of the web part:

 

image

 

Notice this is ASP.NET syntax

 

The template can be easily changed:

 

image

 

To produce a different rendering, without the need for any developer assistance:

 

image

 

From a developers point of view, we really want to just declare some variables and be able to use them as if they were part of the web part, without thinking about FindControl or any implementation detail.

 

I put together a base web part that looks for any private variables with a custom attribute called ControlBinding and via reflection sets this variable to the control instance specified in the attribute, so for the above example the code for the web part would look like:

 

public class TemplateTest : WebPartTemplateBase
{
        [ControlBinding("titleLabel")]
        Label titleLabel = null;

        [ControlBinding("descriptionLabel")]
        Label descriptionLabel = null;

        protected override void OnPreRender(EventArgs e)
        {

            if (titleLabel != null)
            {
                titleLabel.Text = "Some text set from code";
            }

            if (descriptionLabel != null)
            {
                descriptionLabel.Text = "some text description that was set in code";
            }
           
            base.OnPreRender(e);
        }
}

 

So now all the developer needs to do is add an attribute to private variables with the name of the templated control they want to obtain an instance to. This fits very much with the code behind / partial class philosophy that web developers are used to working with.

 

If we look at some more complex scenario’s we start finding a few little issues, for example lets say that we want to use a GridView to do some data binding, in a normal aspx page we would use code nuggets to do the data binding:

 

<asp:GridView ID="GridView1" runat="server">
        <
Columns>
            <
asp:TemplateField>
                <
ItemTemplate>
                 <
asp:label id="dataItemLabel" runat="server"
                                   
Text='<%DataBinder.Eval(Container, "SomeValue"%>'></asp:label>
                </
ItemTemplate>
            </
asp:TemplateField>
        </
Columns>
</
asp:GridView>

 

If we used this in our template we would find that it doesn’t work. There is however a work around:

We can subscribe to the RowDataBound event and we can find the controls we wish to data bind to:

 

 

        [ControlBinding("GridView1")]
        GridView gridView = null;

        protected override voidOnPreRender(EventArgs e)

         {

            if(gridView != null)
            {
                gridView.RowDataBound += newGridViewRowEventHandler(gridView_RowDataBound);
                gridView.DataSource = GetData();
                gridView.DataBind();
            }
           
            base.OnPreRender(e);
        }

        void gridView_RowDataBound(objectsender, GridViewRowEventArgs e)
        {
            Label itemLabel = e.Row.FindControl("dataItemLabel") as Label;

            if(itemLabel != null)
            {
                itemLabel.Text = e.Row.DataItem.ToString(); //cast and use the data item
          
}
        }

 

In which case the template would look like:

 

<asp:GridView ID="GridView1" runat="server">
        <
Columns>
            <
asp:TemplateField>
                <
ItemTemplate>
                 <
asp:label id="dataItemLabel" runat="server"></asp:label>
                </
ItemTemplate>
            </
asp:TemplateField>
        </
Columns>
</
asp:GridView>

 

I’m still in the early stages of experimenting with this pattern, so it could be the case that it’s totally unsuitable for some scenario’s.

If your interested in exploring this pattern a little more, you can download the code to the base class here.

Thursday, March 19, 2009 9:07:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [1] - Trackback
code | Sharepoint | Tip
# Sunday, March 15, 2009

If your coming to SharePoint from a non .NET developer world, the web.config file might be a confusing and daunting file. I’ve broken out the major sections that any SharePoint administrator or newbie developer should know:

 

CallStack: By default SharePoint will display a nice friendly error message:

image

But this will often be a vague message that isn’t really helpful in troubleshooting the real problem. To enable a detailed error message, find the following line in your web.config file:

 

<SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">

 

Then change the CallStack="false" to CallStack="true" This should also be coupled with another change in the web.config file:

 

Custom Errors:

The default will be to show custom errors, this will hide the ‘yellow screen’ that is the ASP.NET error reporting page:

 

image

 

<customErrors mode="On" />

 

By changing mode="On" to mode="Off" The yellow screen will be enabled, which should provide a more detailed report of the error.

 

Safe Controls:

SharePoint has measures in place that ensures that only trusted controls are used throughout the system. SharePoint will only load controls that have a SafeControl entry in the web.config file. Normally the SharePoint solution will write these entries in the web.config file, which is under administrative control (because an administrator is deploying it). But often a developer won’t worry about packaging up a control if they are still developing, so they need to manually add a control to the Safe Controls section of the web.config file, a typical entry looks like:

 

<SafeControl Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint.Portal.WebControls.Alerts" TypeName="*" Safe="True" />

 

Blob cache:

A SharePoint administrator should be aware of the next setting, because it can increase the performance of your site. The idea is that SharePoint will write any images, CSS or JS to a folder on disk rather than requesting the file from the content database. The following entry should be modified to enable the blob cache (more info here).

 

<BlobCache location="C:\blobCache" path="\.(gif|jpg|png|css|js)$" maxSize="10" enabled="false" />

 

To enable the blob cache, change enabled="false" to enabled="true" and make sure that the location exists.

 

Trust level:

Another important concept that new developers need to come to terms with is that by default SharePoint will run under a custom trust level called ‘WSS_Minimal’. This means that they can’t deploy assemblies into the ‘bin’ directory, with the ‘WSS_Minimal’ setting they would need to deploy to the GAC. Normally in a development environment where the developer is constantly changing and testing the code, they will want to change the following line:

 

<trust level="WSS_Minimal" originUrl="" />

 

to: <trust level="Full" originUrl="" />

 

Proxy Settings:

Often in a corporate environment a proxy server will sit between your SharePoint farm and the internet. So operations like retriving external RSS feeds will not work with some configuration changes. The web.config file can be used to store the proxy information, by default the section will look like:

 

<system.net>
    <
defaultProxy>
      <
proxy autoDetect="true" />
    </
defaultProxy>
  </
system.net>

 

to add a new proxy:

 

<system.net>
    <
defaultProxy>
      <
proxy useSystemDefault="false" proxyaddress="http://proxy" bypassonlocal="false"/>
    </
defaultProxy>
  </
system.net>

 

Hopefully now the web.config file isn’t such a mystery for the new SharePoint administrator or developer.

Sunday, March 15, 2009 3:17:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Sharepoint | Tip
# Saturday, March 07, 2009

A few weeks ago I posted about an issue that we were having with our Windows Server 2008 machines Blue Screening, at the time I thought it was related to VMWare ESX Server, it turns out that it was a bug with Windows Server 2008. Thanks to Thomas Vochten for the pointer.

See: http://support.microsoft.com/kb/962943

 

“FIX: You receive a Stop 0x0000007e error message on a blue screen when the AppPoolCredentials attribute is set to true and you use a domain account as the application pool identity in IIS 7.0”

Note This problem typically occurs on Web servers that host Office SharePoint Server 2007. This problem occurs because of the configuration requirements of Office SharePoint Server 2007 when Kerberos authentication is used. However, the problem may occur for any kind of Web site that is using Kernel Mode authentication, Kerberos authentication, and a domain account as the custom application pool identity.”

Saturday, March 07, 2009 9:03:41 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [1] - Trackback
IIS 7 | Tip
# Thursday, March 05, 2009

I’ve worked with many ASP.NET developers who don’t really know much beyond the reach of their code. These are guys that work on top of IIS every day, but don’t really have much of an idea of some of the cool things it can do. IIS 7 is in my opinion the best web server platform around, it’s about time that all web developers took some time to learn more about the capabilities of the platform, a good way to start learning is to look at what other people (or companies) have done on the platform:

 

1. Integrated Pipeline

The integrated pipeline is the magic piece of the puzzle, it means that you can write managed code for all aspects of the request to IIS. Previously you would need to write ISAPI filters and extensions in something like C or C++, now you can write a module in c#. You could kind of get around this with previous versions of IIS, where you would map all requests to the ASP.NET ISAPI, with IIS7 this is no longer needed as a managed handler can be registered for all file types (in fact its possible to write a module that runs before a php script .. for example).

More information on managed handlers in IIS7 can be found here.

 

2. URL Rewrite (aka Mod_Rewrite)

 

The Apache web server has had Mod_Rewrite for years and it was always frustrating that IIS couldn’t match this feature. Until IIS7 the most common option for the rewriting of URL’s was to purchase a third party product such as Helicon’s ISAPI Rewrite, this changed in IIS 7 with the introduction of the IIS 7 Rewrite Module (x86 or x64).

There is a lot of valuable commentary around about the value of URL rewriting for things like Search Engine Optimisation and the ability to create ‘hackable’ URL’s or perhaps protecting your bandwidth, I don’t need to point this stuff out, every web developer should be able to understand the purpose and value of URL rewriting.

A good how-to on IIS 7 URL Rewriting can be found here.

 

3. Bit Rating Throttling Module

 

The Bit Rating Throttling module (x86 or x64) is essential for any web developer who is planning on delivering video via the web. The idea is simple, why send all the video down to the client when there is no guarantee that the client will watch all that content, wouldn’t it be better to send the first bit down fast and then slow down and progressively monitor and change the speed at which the user gets the data delivered. It doesn’t have to work with video either, you could use this module to slow down the speed of any content to certain users (maybe you have a photo site and unregistered users download stuff faster than registered ones).

A good place to start to find out more is here, also Hanselman gave this topic some coverage here.

 

4. Application Request Routing

 

The Application Request Routing feature of IIS7 (x86 or x64) might seem a little odd for the average web developer and sure it kind of borders between the realm of network engineer and software architect. This module is basically a fancy proxy, it can perform load balancing and all sorts of cool routing based on, well pretty much anything you want to define. It performs it’s routing based at the application level (as opposed to a firewall which is at the network level), it means that it can make routing decisions based on things like server variables and requested URL’s.

A good overview can be found here.

 

5. Dynamic IP Restriction Extension

 

Although still in beta, the IP restriction extension does exactly what you think it would do (and probably more). Things like blocking requests based on the number of requests they have made in a defined time period (see Jeff Atwood’s scenario). If your interested in protecting content from certain countries (like what Hulu does with it’s content) or if your just looking for some SPAM protection, you could do a lot worse than checking out the Dynamic IP Restriction Extension (x86, x64).

The best starting point is here.

Thursday, March 05, 2009 4:03:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
IIS 7 | Tip
# Wednesday, February 25, 2009

I’ve started working on a new project for work, it’s going to be a fairly large build job. Recently we started looking at various ORM’s, for a number of reasons we settled on the Telerik OpenAccess product. The Visual Studio integration is pretty nice and it has all the features that you would expect from a commercial ORM, the one complaint that I have is the limited LINQ support.

In any case I ran into a problem with some prototype code, I had setup a post build script to run that would copy the assembly to a SharePoint bin directory, but I would always get the following error message when I tried to execute any ORM related code:

 

“Telerik.OpenAccess: No enhanced assembly has been found for meta-data construction. This may be caused by a missing app.config file (use app.config as embedded resource then) or by an insufficient references section in the configuration file (add the referenced enhanced assemblies there too) or by a wrong enhancement setting; please check your configuration”

 

It turns out that the Telerik tool uses a tool called VEnhance which will inject IL into your assembly, this IL is responsible for tracking changes in your persisted entities. What was happening was the build event would run before the VEnhance tool, so it was copying the assembly without the ‘enhancements’. An easy way to tell is to compare the assembly size, obviously the ‘enhanced’ version will be larger.

Wednesday, February 25, 2009 8:50:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
ORM | Tip
# Wednesday, February 18, 2009

I was looking for a new smaller (i.e. lighter) laptop for out of work use, I settled on a Dell Mini 9 after reading a number of good recommendations. My only gripe so far is the keyboard, I’m still miss hitting keys and the keyboard layout still causes me to look at the keyboard more than I would like, but I can see that I will get used to it, it’s not unusable like the Asus eeepc.

 

I thought a new machine would be the perfect time to give Windows 7 a good try, so far it’s been great.

I really like the new taskbar of Windows 7, but one thing I found after a few days of using the keyboard shortcut of ‘windows key’ + m, was the ‘show desktop’ button at the far right of the taskbar, it’s a little button that when clicked will show the desktop. It seemed fairly hidden (at least for me).

 

image

Wednesday, February 18, 2009 9:26:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Tip | Windows 7
# Tuesday, February 03, 2009

I came across a weird problem with IE and the way it automatically passes credentials to an intranet site. Basically we had an intranet site in the form of http://<intranet name>.<domian name>, e.g. http://intranet.httpcode.com.

Now if users set their homepage directly to this, they would be prompted to authenticate on the first page load, however if you first browsed to another site first (didn’t matter what it was, it could be google.com), then the intranet URL, IE would not prompt you to authenticate, it would work as expected. It’s as if IE didn’t know that the intranet site was in the Intranet zone on the first load.

I found this KB article, I’ve highlighted the interesting bit below:

http://support.microsoft.com/kb/258063

  • Internet Explorer must consider the requested URL to be on the intranet (local). If the computer name portion of the requested URL contains periods (such as http://www.microsoft.com and http://10.0.0.1), Internet Explorer assumes that the requested address exists on the Internet and does not pass any credentials automatically. Addresses without periods (such as http://webserver) are considered to be on the intranet (local); Internet Explorer passes credentials automatically

We ended up just creating the intranet site without a period, i.e. http://intranet this seems to work, in that IE on the first load passes the credentials on properly.

I’m not really sure what to say about this problem (if it is really a problem), I couldn’t find any relevant references on the web about it. Any ideas?

Tuesday, February 03, 2009 12:33:07 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [1] - Trackback
Tip
# Saturday, January 31, 2009

 

The following code will create a site based on a template, then it will add a new contributor group:

 

//create the subsite .. subSite is an SPWeb object
SPWeb createdWeb = subSite.Webs.Add("Url", "Title", "Project Subsite", 1033, "Template Name", true, false);

createdWeb.BreakRoleInheritance(true);

SPMember member = createdWeb.Users[createdWeb.Author.LoginName];
//create the user groups ...

createdWeb.SiteGroups.Add(createdWeb.Title + " Contributors", member, createdWeb.Author, "Contributors to the site");
SPGroup newContribGroup = createdWeb.SiteGroups[createdWeb.Title + " Contributors"];

SPRoleDefinition contribRole = createdWeb.RoleDefinitions.GetByType(SPRoleType.Contributor);
SPRoleAssignment contribRoleAssignment = new SPRoleAssignment(newContribGroup);
contribRoleAssignment.RoleDefinitionBindings.Add(contribRole);
createdWeb.RoleAssignments.Add(contribRoleAssignment);

 

The above code will break the permission inheritance, so the created site will have unique permissions, this code could be refactored to also create Owners and Reader’s groups.

Saturday, January 31, 2009 11:24:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
code | Sharepoint | Tip
# Friday, January 16, 2009

I’ve been working with a client recently that had a problem with the Web Front End servers randomly rebooting. The servers were Windows Server 2008 running virtually on VMWare ESX. Interestingly the problem didn’t occur on any of the other Win 2008 servers that also ran on VMWare.

Firstly we discovered that the machines weren’t just rebooting they were in fact blue screening and then rebooting after they did a dump.

So we fired up WinDbg and had a look at some of the dumps.

We found that the offending method was:

 

FAILURE_BUCKET_ID:  X64_0x7E_BAD_IP_HTTP!UlAuthenticate+73

 

The loaded module was HTTP.sys

 

This seemed to fit, the environment that was crashing was the only one to have Kerberos enabled, so we suspected some interaction between Kerberos and VMWare to be the cause (hence these were the only servers crashing). But since Windows 2008 runs HTTP.sys which is a kernel mode driver, we knew that as part of the Kerberos setup we had to explicitly allow the kernel to authenticate as the app pool user (via the application host file). We also knew that we could use IIS manager to move this authentication out to user mode, if you open IIS manager, expand the web site, select Authentication from the right and select the advanced properties on the Windows Authentication item. This will present you with the following option to ‘Enable Kernel-mode authentication’:

 

 

KernelModeAuth

 

After we deselected this option our servers have been running solidly.

Friday, January 16, 2009 12:18:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [4] - Trackback
Kerberos | Tip
# Friday, January 09, 2009

I received an interesting error today while trying to ‘Manage Data Sources’ on a report “The resource object with classname ‘ReportServer’ and the key ‘DataSourceList’ was not found”:

MOSSError

I found that sometimes it would work, but other times it would fail. A bit of tracing showed that when I hit web1 in the farm it would fail, but web2 would succeed.

With this information in hand I hand a look at the App_GlobalResources folder under c:\inetpub\wwwroot\wss\virtualdirectories\<web application name>

 

Interestingly web2 (which worked) had some resources called ReportServer.resx, but web1 (which failed) did not have these resources, that was what was causing the failures.

I copied the resources across and the issue resolved itself.

I suspect that the report services add on wasn’t installed properly.

Friday, January 09, 2009 3:53:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Reporting Services | Tip
# Thursday, January 08, 2009

I was working with a client recently who had the idea that they could make use of Excel Calculation Services to render parts of a spreadsheet that they use heavily inside their business. The client hoped to be able to publish the spreadsheet in it’s current form.

Unfortunately if any of the following features are inside your spreadsheet, it will fail to render:

 

  • Spreadsheets with code.  This includes spreadsheets with VBA macros, forms controls, toolbox controls, MS 5.0 Dialogs, and XLM Sheets.
  • IRM-protected spreadsheets
  • ActiveX Controls
  • Embedded SmartTags
  • PivotTables based on “multiple consolidation” ranges
  • External references (links to other spreadsheets)
  • Spreadsheets saved in formula view
  • XML expansion packs
  • XML Maps
  • Data validation
  • Query Tables, SharePoint Lists, Web Queries, and Text Queries
  • Spreadsheets that reference add-ins
  • Spreadsheets that use the RTD() function
  • Spreadsheet that use spreadsheet and sheet protection
  • Embedded pictures or clip art
  • Cell and Sheet background pictures
  • AutoShapes and WordArt
  • Ink Annotations 
  • Organization Charts and Diagrams.
  • DDE Links

 

In my case the complex spreadsheet that the client was using contained a number of these features, which basically meant that they need to maintain a cut down spreadsheet just for rendering on the intranet.

Thursday, January 08, 2009 9:34:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Excel Services | Tip
# Tuesday, December 23, 2008

I’ve been working with a client this week getting Kerberos working on their SharePoint farm. As you would expect I spent most of my time working out what SPN’s needed to be created.

I created a simple little tool that will help you sort out the basic SPN’s:  SharePoint Kerberos SPN Creation Tool

 

image

The idea is that you enter the details about your farm and the tool will generate the SPN’s that you need to create (you can copy / paste from this site into your console window).

The client I was working with had a much more complex farm that included reporting services, analysis services and proxy servers that all needed SPN’s, this tool doesn’t cover those types of farms, but it will help you get the base portal services up and running, then you can work out what SPN’s to create in order to get the rest of the services functioning.

Don’t forget that you’ll also need to set up delegation for each of the accounts. By far the best SharePoint Kerberos reference is: http://blogs.msdn.com/martinkearn/archive/2007/04/23/configuring-kerberos-for-sharepoint-2007-part-1-base-configuration-for-sharepoint.aspx

Tuesday, December 23, 2008 9:47:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [1] - Trackback
Kerberos | Sharepoint | Tip
# Friday, December 19, 2008

This week I ran into an interesting problem. When adding a workflow to a content type we saw the following error:

 

Unable to validate data. at System.Web.Configuration.MachineKeySection.GetDecodedData(Byte[] buf, Byte[] modifier, Int32 start, Int32 length, Int32& dataLength) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)

 

I did the normal thing at searched on Google, only to find this KB (http://support.microsoft.com/kb/928028) which describes the error message, it gives the solution as ensuring that SharePoint is installed with the same path on each of the server. This seemed odd, since all our servers have a standard build.

The error message indicated that the view state has been modified between postbacks, so it was back to the drawing board looking for a solution that involved some change that could possibly have some effect on the view state. After talking with the designer it turned out that he had made some changes to the application.master page. We replaced the altered file with a backed up version of the application.master and sure enough the workflow could be added without any issues.

After a bit more experimentation it turned out that the problem was with this:

<SharePoint:DelegateControl ID="MyDelegateControl" runat="server" controlId="SmallSearchInputBox" />

It seems that the small search box alters the view state in some way to cause it not to validate on postback.

 

Hopefully this will save someone else the hassle of this error.

Friday, December 19, 2008 9:50:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Sharepoint | Tip
# Wednesday, December 17, 2008

I’ve been setting up Kerberos for a client that is using Windows Server 2008, I’ve found the following:

 

Since Windows Server 2008 uses http.sys which is a kernel mode driver designed to intercept web requests at the kernel level (thus improving performance) it required a little more configuration. By default http.sys will handle the authentication request using the local system account not the application pool account, this will cause problems if you want to use Kerberos. The solution is the following:

In the application.host file (located at: <system drive>/windows/System32/inetsrv/applicationHost.config )

 

Find the following xml fragment:

 

<configuration><system.webServer><security><authentication>

 

Change the windows authentication node:

 

<windowsAuthentication enabled=”true” useKernelMode=”true” useAppPoolCredentials=”true”/>

 

This just tells the http.sys kernel module to use the application pool credentials.

 

Enable Kerberos logging:

 

Run regedit:

Find: HKEY_LOCAL_MACHINE / SYSTEM / CurrentControlSet / LSA / Kerberos / Parameters

 

Add a new DWORD entry named: LogLevel and set it’s value to 1.

 

On windows server 2008 this will take effect immediately.

 

Now that logging has been turned on, you might want to reference the Common Kerberos Error Codes: http://support.microsoft.com/kb/230476

These error messages will show up in the System Tab of the Event Viewer.

 

Of course there are a few more steps involved in setting up Kerberos, but hopefully this will help with the windows server 2008 specific problems.

Wednesday, December 17, 2008 8:57:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Tip
# Wednesday, December 10, 2008

I was recently asked a question around this scenario:

If you log into a SharePoint Portal by using the ‘Sign in as Different User Button’ as User2 it works fine, however when you click on the ‘MySite’ link it will show the MySite of User1 not User2 as you would expect.

image

 

I should also point out that the MySite and Portal are running in separate web applications (this should give away the answer).

 

So what is happening here is that when you click on the MySite link, this web applications asks the browser for the users authentication details, since it is a different URL (i.e. because its running in a separate web application, it will be a subdomain or even a different domain name) the browser will forward the logged in users credentials i.e. User1 (provided that it is in the local intranet zone), the browser will not keep User2’s credentials and will not forward them on. So the end effect is the scenario described above which may seem odd to the end user.

 

The only way to get around this is to user the ‘RunAs’ command from windows and run the browser process as User2.

 

What we’ve normally found is that the ‘Sign in as Different User’ option is normally only used by power users, these people will generally understand the problem if you explain it to them.

Wednesday, December 10, 2008 9:16:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Sharepoint | Tip
# Tuesday, December 09, 2008

Just a quick note to point out the following link: http://www.visifire.com/

They provide open source Silverlight and WPF charts:

 

image image

 

Worth remembering next time you want to add a rich chart to your applications

Tuesday, December 09, 2008 9:09:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Silverlight | Tip
# Saturday, November 29, 2008

A couple of random tips for using lists inside of SharePoint:

  • Make use of the RSS features of Lists – Each document library publishes an RSS feed which really provides the user with a wealth of options, there is no site collection limits on how that feed is consumed, so it’s possible to use in their MySites etc. If you have Kerberos setup correctly it is possible that other systems can make use of the feed. RSS is a good option to supplement the alerts that a list can send, often users won’t want their email cluttered with alerts.
  • Alerts – Granularity is the key to successful alerts, a user can be alerted when a specific view of a list changes. This can make the alert more useful to the end user, we don’t want to spam them.
  • Folder Level Permissions beware – The ability to create folder-level and document level security permissions can really cause some headaches for new users and administrators. The feature is really powerful, but can also create complex problems that can be hard to solve. There has been lots of discussion around the need for folders in a document library, I think there is value to be gained from them personally.
  • Picture Libraries – It should be noted that the picture libraries have limited support for thumbnail view, it’s not a major limitation but it’s likely to come up in discussions / training with new users.
Saturday, November 29, 2008 2:03:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Sharepoint | Tip
# Wednesday, November 19, 2008

I was asked recently if the BDC search results (when indexed by the search) can be controlled by an access list. The answer is that yes, the Security trimmer is the SharePoint feature to accomplish this. In fact any search result can be trimmed, so if you wanted to index some website that used custom permissions (i.e. a content access account that has full rights to a website) but you didn’t want to show that information to say public users of your site, this same security trimmer functionally can be used.

The important things to note are:

  • The security trimmer is attached to a crawl rule
  • The security trimmer is a class that implements the ISecurityTrimmer interface, the registration process defines the full assembly name, as such it must be loaded into the GAC.
  • After the security trimmer is registered, you will need to recreate the content source and perform a full crawl
  • Performance might be an issue, since every search result will be access checked, if your looking for insight on how to approach this refer to this MSDN article
Wednesday, November 19, 2008 10:49:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
BDC | Search | Tip
# Friday, October 31, 2008

With little effort you can make your site a little more search friendly, it’s possible to embed some xml into your site which your browser can use in its search box. Most modern browsers support OpenSearch, which is what this xml fragment is using.

 

The first step is to create the following xml, but replace the bits that are specific to your site:

 

   1: <?xml version="1.0" encoding="UTF-8"?>  
   2: <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">  
   3:     <ShortName>SharePoint Search</ShortName>  
   4:     <Description>Search for SharePoint</Description>  
   5:     <Url type="text/html" method="get" template="http://YourSite/SearchCenter/results.aspx?k={searchTerms}"/>  
   6:     <Image width="16" height="16">http://YourSite/favicon.png</Image>  
   7:     <InputEncoding>UTF-8</InputEncoding>  
   8:     <SearchForm>http://YourSite/SearchCenter/</SearchForm>  
   9: </OpenSearchDescription>  

 

In the master page, you will need to refer to this xml file:

 

   1: <link rel="search" type="application/opensearchdescription+xml" href="/Style%20Library/OpenSearch.xml" title="SharePoint Search">    

 

Finally you can drop down the search provider box in your browser to select your new search provider, there is no need to browse to the search centre again.

 

image

 

Little things like this can help entrench searching as the primary navigation method in an organisation.

Friday, October 31, 2008 12:18:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Search | Sharepoint | Tip
# Tuesday, October 28, 2008

So last week I rebuild my work laptop, previously it was running Windows XP with 2GB of RAM. These days I’m almost always running a virtual machine running some form of SharePoint and I would constantly get frustrated with the performance of my laptop.

I did some pricing and found that 4GB of laptop RAM was around $110, I was shocked, so I headed down to the shop to pick it up. I knew that if I continued using a 32 bit OS that I wouldn’t be able to take full advantage of all the RAM.

 

xp

 

So my next step was to upgrade to 64 bit Vista, I grabbed my MSDN disk with Vista x64 SP1 and installed, I wasn’t to sure how it would go installing all of the 64 bit drivers for my Dell Latitude D630, but it turns out that Dell has great support for 64 bit, I downloaded them all and had a fully functional system in no time. As anyone who knows me will tell you that I’m a huge Vista fan, I really missed having all the cool Vista features on my work laptop, it really does feel to me that I’m more productive on a Vista machine.

So now a week later I wish I had upgraded sooner, I can now run two virtual machines both with 1GB of RAM allocated to them, but best of all I can swap between applications very smoothly.

Just for giggles this is what I see now:

 

image

Tuesday, October 28, 2008 10:00:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Tip
# Sunday, October 26, 2008

You may have noticed in your coding adventures that some column names have had the spaces replaced with _x0020_. To understand why this is happening a little background is needed, a site column has two types of ID’s, the first is a unique name and the second is a unique ID. The ID is a GUID, however the unique name has two parts, the internal name and the display name, it is the internal name that has it’s space characters replaced with the hex value of the HTML space character: %20.

Now that you know why this happens, the way to prevent the _x0020_ characters using the web UI is to firstly create the column without any spaces (this will create the ID and the unique name), then after it has been created, you can go back and rename it (this will just updated the display name).

Sunday, October 26, 2008 10:09:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [1] - Trackback
Sharepoint | Tip
# Tuesday, October 21, 2008

By default SQL Server will auto grow your databases by 1 MB for your data file and 10% for your log files. There have been numerous discussions about the usefulness of this default value, but at the end of the day you should really understand how this will effect your database.

In the world of SharePoint it’s common for users to upload multiple mega-byte files, which will be stored in the content database and would cause the database file to grow and could potentially cause performance issues.

Another SharePoint scenario that needs consideration is the SSP databases, the indexing of content performs a large number of write operations of the metadata associated with the crawled content. It might be wise to monitor the performance of these databases to determine if changing the auto growth rate would help.

 

databasegrowth

 

If you came to the conclusion that you did want to change the default options for all new databases, then you can simply change the default values of the model database, you can do this by right clicking on the model database and selecting the button next to the file you wish to change:

 

defaultsizes

 

Like all performance related tips, it’s best if you conduct some of your own analysis.

Tuesday, October 21, 2008 11:17:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
SQL Server | Tip
# Monday, October 20, 2008

Scott Hanselman recently posted about the IIS 7 Rewrite module and how easy it is to setup and use, he covers the topic extensively, I just wanted to point out that this tool will also work with SharePoint.

I was recently in a position where the marketing guys had decided that the URL should be the promotion name of the marketing campaign, but it was both impractical and impossible (the URL had to point to a survey) to create a page in SharePoint that would suit their needs. Since the site was running IIS 7 we used the IIS 7 Rewrite module.

For example:

Say the requested URL was:  http://server/marketing/promo/

But we needed to post to:  http://server/Lists/Marketing Survey 1/overview.aspx

 

The first step after installing the rewrite module is to create a ‘Rule with rewrite map’:

 

rule1

 

Then choose the rule action type, in this case it is a rewrite action, give it a meaningful name:

 

rule2

 

Then add the mapping (right click in the panel that gets opened after the last step), the Original value is the URL you want your users to navigate to:

 

rule3

 

That’s it your done, now you can browse to your URL and your users will end up in the correct location:

 

endresult

Monday, October 20, 2008 8:48:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
IIS 7 | Sharepoint | Tip
# Thursday, October 16, 2008

By default SharePoint will create a content source called ‘Local Office SharePoint Server sites’ such as:

 

contentS

 

This will contain the starting addresses of all the sites on your SharePoint server such as:

editContentS

 

Notice how it also includes the sps3://, this is the indexing of your user profiles.

 

My tip is to remove the sps3:// link from the default content source and add it as a new content source on it’s own.

 

The reasons why I think this is helpful:

  • By default you need to crawl all your other content just to update your user profile information.
  • You can schedule your profile crawls at a time that suits your active directory imports

In any case it’s worth considering breaking the profile crawl into it’s own content source.

Thursday, October 16, 2008 10:55:00 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
Search | Sharepoint | Tip
Statistics
Total Posts: 190
This Year: 3
This Month: 0
This Week: 0
Comments: 38