Home | Blog | Screencasts | Projects
# Sunday, April 19, 2009

A little while ago, I was working with a customer who wanted to have the ability to write some annotations on a graph that was presented in a SharePoint site. The idea was that the graph was quite complex and it would help the end user understand it more if it was annotated by a domain expert.

So I put together a little proof of concept web part that makes use of all that JQuery goodness. I figured that it didn’t matter if you were annotating complex graphs, or tagging someone’s face like the way flickr and facebook does, the concept was the same:

 

image

 

image

 

image

 

So like I said the code is proof of concept, not production ready, but I thought I’d post it here anyway, if only to inspire ideas.

I’ve stored the data in a list with the schema of

 

Title:  default setting (single line of text)

JSON: single line of text

 

Or:

image

 

The data will look like this once some annotations have been added:

 

image

 

So I’ve just stored the JSON serialised object as is. The web part will iterate over each item on that list and pump that JSON into some JavaScript that is written to the page, so when the page load’s it will insatiate a JavaScript array of annotations and then render them. Which looks something like:

 

notes = [{ "x1": "11", "y1": "28", "height": "91", "width": "73", "note": "This is bill", "imgID": "0"}, { "x1": "86", "y1": "54", "height": "81", "width": "95", "note": "This is Kate", "imgID": "0"}];

 

You might ask why I have the imgID property, this is used if more than one image on the page is annotated.

 

To have a play around with the web part, you can download the WSP here, you just need to deploy the solution in the normal manner (stsadm –o addsolution –filename <path to httpcode.imageannotate.wsp>

 

Next step is to activate the Image Annotation web part feature on the site:

 

image

 

Add the web part as normal from the web part menu:

 

image

 

Once the web part is on the page, you need to set List setting to the SharePoint list that will store the JSON data (this list must conform to the schema above):

 

image

 

 

The client ID is the most technical part, this is a selector that gets used directly by JQuery, so any valid JQuery selector will work. A couple of examples:

This will find the default image on the homepage of a standard collabration portal:

img[src*='/PublishingImages/newsarticleimage.jpg']

 

All the images produced by a Dundas chart:

img[src*='SharePointChartAxd.axd']

 

Hopefully you get the idea.

 

I haven’t added any way to delete the annotation from the image itself, rather you need to go to the custom list and delete the item from there. The web part is smart enough to not allow users who can’t add items to the list. Credit should also go to odyniec.net for the imgAreaSelect JQuery plugin which I’ve made use of.

The web part injects lots of JavaScript into the page, so the code might look a little messy because of this, but the basic premise is pretty straight forward.

 

The source code can be found here. It includes a HttpHandler (ImageAnnotate.ashx) for handling all the ajax calls from the client side script. Remember this is just some sample code, use it at your own risk.

Sunday, April 19, 2009 6:49:54 PM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
code | JQuery | Sharepoint
# Tuesday, March 24, 2009

I came across an interesting problem the other day, I needed to do some string manipulation with SQL Server, normally dealing with this sort of stuff sucks, I wanted to split a string like  ‘item1, item1, item3’ .. so splitting on a given character. The first thing that popped to my mind was a Table Valued function, something like this:

 

-- Splits a column based on a specified delimiter
CREATE FUNCTION dbo.Split
(
      
@List nvarchar(2000),
      
@SplitOn nvarchar(5)
)
RETURNS @RtnValue table
(

      
Id int identity(1,1),
      
Value nvarchar(2000)
)
AS
BEGIN

       While
(Charindex(@SplitOn,@List)>0)
      
Begin
               Insert Into
@RtnValue (value)
              
Select  Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1)))
              
Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List))
      
End

       Insert Into
@RtnValue (Value)
              
Select Value = ltrim(rtrim(@List))

              
Return
END

 

There are many examples of this type of function on web, my point isn’t the actual implementation, rather the way you can use it.

I can now run the query:

 

select Value from dbo.Split('item1, item2, item3',',')

 

image

 

But my problem was a little different from the trivial example above, I wanted to pass data into this function that was the result of my query, rather than just passing arguments in statically like above and using the function as a table, I really wanted to apply the function to the data from my table, on a row by row level.

After a little searching I found the CROSS APPLY SQL syntax, with this I can now do exactly what I want:

 

select SF.Value from TestTable TT
cross apply dbo.Split(TT.Value, ',') SF

 

The above query simple selects the data from the TestTable, then cross apply’s the Split function passing it the TestTable’s value column (which contains the data ‘Item1, Item2, Item3, Item4’, also note that I’m selecting the column from the Split function.

 

This Produces the desired results:

image

 

Given a table like:

 

image

 

And data like:

 

image

 

I thought this was pretty cool. SQL can be fun.

Tuesday, March 24, 2009 10:51:29 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
code | SQL Server
# 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

Yesterday I presented at the Brisbane SharePoint User Group, my topic was Using the Business Data Catalog with User Profiles. It was loosely based on this screencast I did last year.

The entire presentation was recorded using Live Meeting, it can be viewed by going to: https://www112.livemeeting.com/cc/microsoft/viewRecordings

and use the Recording Code: 7B8B6D

I’ve put the PowerPoint presentation for my talk here.

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

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
# Thursday, March 12, 2009

My last post described a really simple scenario where I used a HttpHandler to configure StructureMap, then I showed some code that is used to replace the ‘new’ operation used to create a new instance like: ObjectFactory.GetInstance<NumberPrinter>()

 

This might seem a little clunky because you need to remember to use the StructureMap ObjectFactory, not all programmers are created equal, so it might slip through the cracks. What would a framework look like if it embraced the concept of DI?

Well it turns out that the ASP.MVC framework was designed from the ground up (or a mile up as the case may be, it was started on a plane flight). To configure StructureMap with ASP.NET MVC, firstly it’s OK to modify the global.asax (since this isn’t a SharePoint solution):

 

        protected void Application_Start()
        {
           
            StructureMapConfiguration.AddRegistry(new DIRegistry());

            ControllerBuilder.Current.SetControllerFactory( typeof(StructureMapControllerFactory)   );

        }

Here we configure StructureMap with the same method as my last post by using the StructureMapConfiguration.AddRegistry method. The second line is more interesting, we tell the MVC framework that we want StructureMapControllerFactory to be the factory class that creates our controllers. So the code to this class looks like:

 

public class StructureMapControllerFactory : DefaultControllerFactory
   
{
        protected override IController GetControllerInstance(Type controllerType)
        {
            try
           
{
                return ObjectFactory.GetInstance(controllerType) as System.Web.Mvc.Controller;

            }
            catch (StructureMapException x)
            {
                System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
                throw;
            }
        }       
    }

 

That’s pretty cool, so what it means now is that we can create our controllers to take an instance of anything we want to inject. Continuing from the example with a simple Number interface:

 

public class TestController : Controller
{
        INumber _number;
        public TestController(INumber number)
        {
            _number = number;
        }

        public ActionResult Index()
        {
           
            return View(_number.GetNumber());
        }

}

 

This means that the controller has been passed an instance of INumber that has been created by StructureMap. Once you do the initial setup, it’s now pretty hard to make any mistakes in regards to not calling the proper Create methods.

Thursday, March 12, 2009 11:30:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
ASP.NET MVC | code | StructureMap

One of my favourite Dependency Injection (DI) containers is Jeremy Miller’s StructureMap, it’s full featured and light weight, but what I really like the most is the fluent configuration API which means we can write code like this:

ForRequestedType<INumber>()
                .TheDefaultIsConcreteType<Number>();

 

I also like that you don’t need to put custom attributes in your code.

 

It’s all pretty abstract so lets assume we have a simple interface, I’m deliberately keeping it simple:

   

public interface INumber
{
     int GetNumber();
}

 

A simple implementation of this interface:

 

public class Number : INumber
{      
        public int GetNumber()
        {
            return 999;
        }      
}

 

 

I’ve built a really simple (read: don’t use this in anything other than an experiment, the DI container in SharePoint gets configured for every request, including for images and scripts). This handler calls StructureMapConfiguration.AddRegistry with a class that derives from Registry which contains our fluent configuration information.

 

Why have I implemented this as a HTTPHandler?

If you read the Guidance on How to enable Unity in a SharePoint Application (unity is Microsoft’s DI container), the first step is to modify the Global.asax file. I have a problem with doing this for the simple reason that your touching the SharePoint system files, any upgrade will likely cause problems. It really is a shame that you can’t access the application onstart event using another mechanism.

I most certainly agree that the application onstart event is the perfect place to setup your DI container and if your happy to modify and deploy your changes to a global.asax file then go right ahead, put the code below into this file.

 

So it got me thinking, would a DI container like StructureMap work if it was setup in the begin request method of a HttpHandler? so my test code is:

 

namespace DIHttpModule
{
    public class DIHttpModule : IHttpModule
   
{  
        public void Dispose()
        {
          
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            StructureMapConfiguration.AddRegistry(new DIServiceRegistry());

            INumber numberGen = ObjectFactory.GetInstance<INumber>();

            ((HttpApplication)sender).Response.Write("Number: " + numberGen.GetNumber().ToString());
        }      
    }

    public class DIServiceRegistry : Registry
   
{
        protected override void configure()
        {
            ForRequestedType<INumber>()
                .TheDefaultIsConcreteType<Number>();
        }
    }
}

 

So after I deploy and configure my HttpHandler I do in fact see the number ‘999’ display at the top of each page (it also breaks JavaScript etc. because it writes this value into every request)

What has happened is that the call ObjectFactory.GetInstance<INumber>() has created an instance of Number(), we didn’t have to explicitly new up a Number() object.

That is a pretty basic example, lets expand it a little:

 

public class NumberPrinter
{
        private INumber _number;

        public NumberPrinter(INumber number)
        {
            _number = number;
        }

        public string PrintNumber()
        {
            return _number.GetNumber().ToString();
        }
}

 

Notice the constructor, it takes an INumber interface, the constructor is special as far as StructureMap is concerned, if StructureMap is asked to create an instance of NumberPrinter it will see that the constructor takes an INumber parameter and will attempt to pass in an instance of that type.

 

So assuming we changed the HttpModule to the following code:

 

NumberPrinter printer = ObjectFactory.GetInstance<NumberPrinter>();
((HttpApplication)sender).Response.Write(" Number : " + printer.PrintNumber());

 

We can see that again our output is ‘999’, StuctureMap was smart enough to create an Instance of INumber and pass it in, if you think about it, that’s pretty cool. It means that you can replace any concrete Instance of INumber with a single configuration change, that is powerful when we want to test our object in isolation, which is a whole other topic.

 

That’s a pretty trivial example, we did the StructureMap configuration and called ObjectFactory.GetInstance in the same method, now lets try it out in a web part which will be invoked later in the page life cycle (also remove the response.write from the HttpModule):

 

public class NumberWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
        protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
        {
            NumberPrinter printer = ObjectFactory.GetInstance<NumberPrinter>();
            writer.Write("Web Part: " + printer.PrintNumber());
        }
}

 

Running this web part gives the expected result:

 

image

 

Again this is a really trivial example, that’s the point, you can clearly see that we are using a DI tool called StructureMap to create instances of our objects. Sure you could do away with the HttpHandler and move the configuration into the web.config file. But I do think the HttpHandler method warrants more thought however, because its useful when you introduce NHibernate to the mix, which is another framework that needs to do some expensive start up, which is also suited to the global.asax methods, but it does have some characteristics that should be managed per request, but that’s another post.

 

For now, hopefully I’ve proved some thought around DI and how can we manage the SharePoint deployments that really yell out for Application OnStart events without modifying the system file.

 

 

Thursday, March 12, 2009 9:10:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [0] - Trackback
code | Sharepoint | StructureMap
# Sunday, March 08, 2009

I thought it might be fun to play around with the people search of MOSS. I wanted to have an auto complete like experience, where you could start typing someone’s name and a list of suggestions are displayed below:

 

image

 

I started by including JQuery and the Autocomplete JQuery plugin into a style library.

 

Next I created a Handler called PeopleSearch.ashx, I placed this in the _layouts directory (or 12 hive \TEMPLATE\LAYOUTS )

The code for this handler is simple:

 

   1: <%@ WebHandler Language="C#" Class="GenericHandler1" %>
   2: <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3: <%@ Assembly Name="Microsoft.Office.Server.Search, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   4: <%@ Assembly Name="Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   5:  
   6: using System;
   7: using System.Web;
   8: using System.Data;
   9: using Microsoft.SharePoint;
  10: using Microsoft.Office.Server.Search.Query;
  11:  
  12: public class GenericHandler1 : IHttpHandler {
  13:     
  14:     public void ProcessRequest (HttpContext context) {
  15:         context.Response.ContentType = "text/plain";
  16:     
  17:         string prefixText = context.Request["q"]; 
  18:         using (SPSite siteCollection = SPContext.Current.Site)
  19:         {
  20:             // create a new FullTextSqlQuery class
  21:             FullTextSqlQuery query = new FullTextSqlQuery(siteCollection);
  22:             query.QueryText = string.Format("SELECT Title FROM SCOPE() WHERE FREETEXT(defaultproperties, '{0}*') AND \"Scope\"='People' ", prefixText);
  23:             query.ResultTypes = ResultType.RelevantResults;
  24:             query.RowLimit = 10;
  25:  
  26:             // execute the query
  27:             ResultTableCollection queryResults = query.Execute();
  28:             ResultTable queryResultsTable = queryResults[ResultType.RelevantResults];
  29:                         
  30:     
  31:             while(queryResultsTable.Read()){
  32:                 context.Response.Write(queryResultsTable.GetString(0) +  Environment.NewLine);              
  33:             }    
  34:         }      
  35:         
  36:     }
  37:  
  38:     public bool IsReusable {
  39:         get {
  40:             return false;
  41:         }
  42:     }
  43:  
  44: }

It simply executes a full text query on the People Search Scope with the current text as the argument. Download the handler here.

 

Next I added a content Editor web part to the PeopleSearch.aspx page and included the following JavaScript (in the HTML source view):

 

   1: <script type="text/javascript" language="javascript" src="http://server/Style%20Library/jquery-1.2.6.min.js"/>
   1:  
   2: <script type="text/javascript" language="javascript" src="http://server/Style%20Library/jquery.autocomplete.min.js"/>
   3:  
   4: <script type="text/javascript">
   5:  
   6:     $(document).ready(function() {
   7:  
   8:         $("input[id*='_InputKeywords']").autocomplete("/_layouts/PeopleSearch.ashx");
   9:         $("input[id*='_InputKeywords']").attr("autocomplete","off");
  10:     
  11:     });
  12:  
</script>

 

The first thing I do is add a new attribute to prevent IE (or Firefox) from showing the previous search items. The next thing is to add the call the autocomplete plugin on the search textbox (which is found with because we know the id always ends with _InputKeywords).

 

I also added some styles from the autocomplete css to the css of the site.

 

It’s really that simple to get look ahead searching on people in MOSS. In fact this same approach could work on all the search pages.

Sunday, March 08, 2009 11:07:00 AM (E. Australia Standard Time, UTC+10:00)  #    Comments [3] - Trackback
code | JQuery | MOSS
# 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
Statistics
Total Posts: 191
This Year: 0
This Month: 0
This Week: 0
Comments: 41