Home | Blog | Screencasts | Projects
# 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
# 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
Statistics
Total Posts: 191
This Year: 0
This Month: 0
This Week: 0
Comments: 41