﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>ADAM Blog</title><link>http://blogs.adamsoftware.net</link><description>About ADAM: tips and tricks, how to's and more</description><item><title>Extending the classification browser</title><link>http://blogs.adamsoftware.net/Web_Development/Extendingtheclassificationbrowser.aspx</link><description>&lt;div&gt;&lt;p&gt;Ever wanted to display records via a classification browser? The ADAM ClassificationTree control makes this easy for you. All you need is a... ClassificationTree control and a couple lines of code.&lt;/p&gt;&lt;p&gt;This example shows you how to accomplish this.&lt;/p&gt;&lt;h3&gt;Example&lt;/h3&gt;&lt;p&gt;
                                Create a web page containing an &lt;b&gt;AdamPageManager&lt;/b&gt; and a &lt;b&gt;ClassificationTree&lt;/b&gt;.
                                The AdamPageManager (required on all ADAM pages) manages all kinds of page events,
                                such as gathering and showing messages when needed.
                                &lt;br /&gt;
                                Obviously, we also need a ClassificationTree control on this page.
                            &lt;/p&gt;&lt;pre name="xml"&gt;
&amp;lt;awc:AdamPageManager id="ctrAdamPageManager" runat="server" /&amp;gt;
&amp;lt;awc:ClassificationTree ID="ctrTree" 
   OnClassNodeChildAdding="ctrTree_ClassNodeChildAdding"
   OnSelectedNodeChanged="ctrTree_SelectedNodeChanged" 
   AutoPostBack="NodeSelect" runat="server" /&amp;gt;&lt;/pre&gt;&lt;p&gt;
                                IIn the code-beside, the &lt;b&gt;ClassNodeChildAdding&lt;/b&gt; event is used to create new
                                textnodes where we:
                                &lt;ol&gt;&lt;li&gt;load the records, classified in the current classification and containing at least
                                        one file.&lt;/li&gt;&lt;li&gt;determine the imageurl based on the resolution of the record's master file. This
                                            will give the user a quick view on the resolution of the record's file.&lt;/li&gt;&lt;li&gt;create a new textnode where the label is the record's filename.&lt;/li&gt;&lt;li&gt;add this textnode to the list of childnodes of the current ClassNode.&lt;/li&gt;&lt;/ol&gt;&lt;pre name="c#"&gt;
protected void ctrTree_ClassNodeChildAdding(object sender, ClassNodeCancelEventArgs e)
{
  ClassificationHelper classHelper = new ClassificationHelper(AdamHelper.DefaultApplication);
  if (!classHelper.HasChildren(e.Classification.Id))
  {
    // Search for records with the  following restrictions:
    // 1: The number of files should be at least 0
    // 2: The records should be classified in the current classNode
    string expression = "FileCount &amp;gt; 0 AND DirectClassification.Id = ?";
    RecordCollection records = new RecordCollection(AdamHelper.DefaultApplication);
    RecordLoadOptions options = new RecordLoadOptions();
    options.PreLoadClassifications = false;
    options.PreLoadFields = string.Empty;
    options.PreLoadFileFields = string.Empty;
    options.PreLoadFiles = PreLoadFile.FilesVersions;
    options.LockMode = LockMode.ReadUncommitted;

    records.Load(new SearchExpression(expression, new object[] { e.Classification.Id }), string.Empty, options);
    foreach (Record record in records)
    {
       ImageUri uri = new ImageUri(record, ImageType.Preview);
       TextNode node = new TextNode(record.Files.LatestMaster.FileName, record.Id.ToString(),
       this.GetImageUrl(record.Files.LatestMaster), uri.ToString(), "_blank");
       e.Node.ChildNodes.Add(node);
    }
  }
}
                            &lt;/pre&gt;&lt;h4&gt;
                                    A remark on performance&lt;/h4&gt;&lt;p&gt;
                                    It's important to know that we need to minimise the number of record loads as
                                    much as possible. &lt;b&gt;Recordloadoptions&lt;/b&gt; are very useful to do that. In these
                                    options we specify:
                                    &lt;ul&gt;&lt;li&gt;that the record's fields and classifications should not be loaded because the're
                                            not used.&lt;/li&gt;&lt;li&gt;the lockmode is set to &lt;b&gt;readuncommitted&lt;/b&gt;, which basically means that the data
                                            is gathered with an optimal performance. This makes the impact on the sql server
                                            lower than when using the default lockmode.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;/p&gt;&lt;p&gt;
                                Running this web page will give you the result shown below. As you can see, this
                                example makes it  easy to distinguish high-res from low-res images:
                            &lt;/p&gt;&lt;br /&gt;&lt;img src='http://blogs.adamsoftware.net/Files/1caaeb5256a94c788223de20e62550af.jpg' title="Classification-Tree displaying records." /&gt;&lt;/div&gt;</description></item><item><title>Hacking with Fiddler to make cross-site XmlHttpRequest work in FireFox</title><link>http://blogs.adamsoftware.net/Web_Development/HackingwithFiddlertomakecrosssiteXmlHttpRequestworkinFireFox.aspx</link><description>&lt;div&gt;&lt;p&gt;Today's web is all about AJAX. Google Mail, Facebook, Twitter, and just about everyone else uses it these days thanks to the helping hand of libraries such as Microsoft AJAX, jQuery and others. At the base of all of this technology is the XMLHttpRequest object that performs background requests to provide asynchronous updates. While being the cornerstone of today's web, it has also spawned interest from the wrong kind of developers, and security became a concern.&lt;/p&gt;&lt;p&gt;In the older days, this problem was 'fixed' by browsers in different ways. But more recently, a new standard was adopted by W3C (the folks that set the web standards) called &lt;a target='_blank' href="http://www.w3.org/TR/access-control/"&gt;Cross-Origin Resource Sharing"&lt;/a&gt;. It has been introduced in Firefox 3.5 and Safari 4.&lt;/p&gt;&lt;p&gt;This is why you'll have a hard time calling web services from JavaScript in these browsers, unless the service specifically implements the access control features described in the standard. And since most services that our outside of your domain are also outside your control, you can't change them to include support for this new standard.&lt;/p&gt;&lt;p&gt;Which is why I was having a hard time implementing my client-side proof of concept for a future version of our product. It took me a while to figure out that the problem came from this new implementation, since FireFox does not let your request fail, it simply strips out the content.&lt;/p&gt;&lt;p&gt;If you look in FireBug and see a response like this, you'll know why:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/c1b6d46f929e4e4694212c88c7fc564b.png' /&gt;&lt;p&gt;To your code, the request will have succeeded (unless you specified that the result was of the form 'xml' or 'json'), but there won't be any result to parse. This can be quite a nuisance if you're just trying something out in a local html document, and at least in FireFox 3.6, there is &lt;a target='_blank' href="http://stackoverflow.com/questions/667519/firefox-setting-to-enable-cross-domain-ajax-request"&gt;no way&lt;/a&gt; to turn this 'restriction' off.&lt;/p&gt;&lt;p&gt;However, I was able to trick it by using &lt;a target='_blank' href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt;. Fiddler is a web proxy used to diagnose HTTP requests and responses, but it can do much more than just inspecting. You can do all sorts of nifty things like changing requests and replies in flight.&lt;/p&gt;&lt;p&gt;I added a custom rule to Fiddler, using the following code:&lt;/p&gt;&lt;pre name="javascript"&gt;
 static function OnBeforeResponse(oSession: Session)
    {
        ...
        
  if (oSession.HostnameIs("services.aonaware.com")) {
   oSession.oResponse.headers["Access-Control-Allow-Origin"] = "*";
  }
  
  ...
    }
&lt;/pre&gt;&lt;p&gt;This rule adds the required header for FireFox to allow the result to be parsed by your client-side code:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/a1b301512b9e4f8b9767ec0acb2e899a.png' /&gt;&lt;p&gt;Note that this doesn't work unless you have Fiddler with the custom rule running on the client machine, so you'll have to resort to other options when creating real applications, but to me it's fine for quick tinkering.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Strongly Typed Searching in ADAM, part 2</title><link>http://blogs.adamsoftware.net/Engine/StronglyTypedSearchinginADAMpart2.aspx</link><description>&lt;div&gt;&lt;p&gt;
                                Remember &lt;a target='_blank' href="http://blogs.adamsoftware.net/Engine/StronglytypedsearchinginADAM.aspx"&gt;
                                    part 1&lt;/a&gt; of Søren Trudsø Mahon's article of &lt;a target='_blank' href="http://www.dxp.dk"&gt;DXP&lt;/a&gt;?
                                Who's up for part two? Here goes:&lt;/p&gt;&lt;p&gt;
                                In part 1 we saw how to use the API, in this post we’ll have a look at the implementation
                                behind this.
                            &lt;/p&gt;&lt;h3&gt;
                                The interface of the API&lt;/h3&gt;&lt;p&gt;
                                To do this, we've created a fluent API for searching ADAM objects: inspired
                                by this series of blog posts:&lt;br /&gt;&lt;a target='_blank' href="http://www.lostechies.com/blogs/gabrielschenker/archive/2010/01/03/fluent-silverlight-fluent-api-and-inheritance.aspx"&gt;
                                    http://www.lostechies.com/blogs/gabrielschenker/archive/2010/01/03/fluent-silverlight-fluent-api-and-inheritance.aspx&lt;/a&gt;&lt;br /&gt;&lt;a target='_blank' href="http://www.lostechies.com/blogs/gabrielschenker/archive/2010/01/03/fluent-silverlight-fluent-api-and-inheritance.aspx"&gt;
                                    http://www.lostechies.com/blogs/gabrielschenker/archive/2010/01/03/fluent-silverlight-fluent-api-and-inheritance.aspx&lt;/a&gt;&lt;/p&gt;&lt;p&gt;
                                To start off with we created an extension method (new feature in c# / .net 3.5)
                                on the &lt;b&gt;Application&lt;/b&gt; object like this:&lt;/p&gt;&lt;pre name="c#"&gt;namespace Adam.Core 
{
    public static class ApplicationSearchExtensions 
    {
        public static AdamSearch Search(this Application @this) 
        {
            return new AdamSearch(@this);
        }
    }        
}&lt;/pre&gt;&lt;p&gt;
                                We have put this inside of the &lt;b&gt;Adam.Core&lt;/b&gt; namespace, this way we don’t have
                                to remember to include our namespace wherever we want to call &lt;b&gt;Search&lt;/b&gt; on the
                                &lt;b&gt;Adam.Core.Application&lt;/b&gt; object. (We’ll probably end up putting the &lt;b&gt;AdamSearch&lt;/b&gt;
                                behind an interface, and having a factory for creating the &lt;b&gt;AdamSearch&lt;/b&gt;, enabling
                                us to mock our search). The &lt;b&gt;AdamSearch&lt;/b&gt; class is our entry into searching,
                                in here we define the root types you can search on:&lt;/p&gt;&lt;pre name="c#"&gt;public class AdamSearch 
{
    private readonly Application application;

    public AdamSearch(Application application) 
    {
       this.application = application;
    }
        
    public IUserSearchRoot User 
    {
       get { return new UserSearch(this.application); }
    }

    …
}&lt;/pre&gt;&lt;p&gt;
                                The class xxxSearch represents the adam object we are searching for, this is hidden
                                behind an interface IxxxSearchRoot. The keywords are defined in interface, &lt;b&gt;IUserSearchKeywords&lt;/b&gt;
                                and &lt;b&gt;ISearchKeywords&lt;/b&gt;:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/c269fabe1bc94bbcaf6b8e8e0afe7716.png' /&gt;&lt;pre name="c#"&gt;public interface IUserSearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt;
    : ISearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt; 
{
    TSearchParent Name(string name);
}

public interface ISearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt; 
{
    IUserSearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt; CreatedBy 
    { 
      get; 
    }

    TSearchParent Id(Guid id);

    TSearchParent Id(Operator @operator, Guid guid);

    TSearchParent Id(IEnumerable&amp;lt;Guid&amp;gt; ids);

    TSearchParent CreatedOn(Operator @operator, DateTime time);
}&lt;/pre&gt;&lt;p&gt;
                                We have methods and properties which correspond to the keywords in the Adam Help.
                                Properties are links to other objects. For example:&lt;br /&gt;&lt;code&gt;CreatedBy.Name("administrator")&lt;/code&gt; corresponds to &lt;code&gt;createdby.name
                                    = administrator&lt;/code&gt;&lt;/p&gt;&lt;p&gt;
                                Methods are actual criteria. For example:&lt;br /&gt;&lt;code&gt;Id(user.Id)&lt;/code&gt; correspondents to &lt;code&gt;id = 'C899EFCB-440E-487F-A007-09A9043E678F'&lt;/code&gt;&lt;/p&gt;&lt;p&gt;
                                Pretty simple, but showing that our API correspondents to the Adam search.&lt;/p&gt;&lt;p&gt;
                                The &lt;b&gt;TSearchParent&lt;/b&gt; generic parameter is used as a placeholder for the kind
                                of search we are performing. That is, if we are performing a &lt;b&gt;RecordSearch&lt;/b&gt;
                                this will refer back to an &lt;b&gt;IRecordSearch&lt;/b&gt; where the keywords for searching
                                for records are defined. This enabled me to chain the keywords like this:&lt;/p&gt;&lt;pre name="c#"&gt;Application.Search()
  .User.CreatedBy.Name("dxp-stm")
  .CreatedOn(Operator.LessThan, DateTime.Now);&lt;/pre&gt;&lt;h3&gt;
                                Implementing the API:&lt;/h3&gt;&lt;p&gt;
                                We've created a “big” base class where all of the main loading functions and
                                common keywords are implemented:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/4859118e23ff4cde90c9978b59c9d3fe.png' /&gt;&lt;p&gt;
                                This class has the responsibility of:
                            &lt;/p&gt;&lt;ul&gt;&lt;li&gt;All the search operators that are common to all Adam objects (&lt;b&gt;Id&lt;/b&gt;, &lt;b&gt;CreatedBy&lt;/b&gt;,
                                    &lt;b&gt;CreatedOn&lt;/b&gt;...)&lt;/li&gt;&lt;li&gt;Executing queries (delegated to the &lt;b&gt;SearchExecutor&lt;/b&gt;).&lt;/li&gt;&lt;li&gt;Collection all search expressions (delegated to &lt;b&gt;SearchExpressionProvider&lt;/b&gt;)&lt;/li&gt;&lt;li&gt;Executing queries when we have no search expression yet (&lt;b&gt;Load(Guid Id)&lt;/b&gt; and
                                    &lt;b&gt;Load(IEnumerable&amp;lt;Guid&amp;gt; ids)&lt;/b&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;
                                Interesting bits are the implementation of keywords which lead to adding a search
                                criteria to our search expression. But also how we refer to other ADAM objects.&lt;/p&gt;&lt;p&gt;
                                Implementation of keywords in SearchBase.cs:&lt;/p&gt;&lt;pre name="c#"&gt;public TSearchParent Id(Guid id) 
{
    return AddEq("Id", id);
}

protected TSearchParent AddEq(string path, object value) 
{
            return Add(path, Operator.Equal, value);
}

protected TSearchParent Add(string path, Operator @operator, object value) 
{
    ExpressionProvider.Add(ParentPath + path, @operator, value);
    return this.SearchParent;
} &lt;/pre&gt;&lt;p&gt;
                                Implementation of keywords in SearchBase.cs -&amp;gt; SearchExpressionProvider:&lt;/p&gt;&lt;pre name="c#"&gt;public void Add(string expression, Operator @operator, object value) 
{
    expression = string.Format("{0} {1} ?", expression, 
        GetOperator(@operator));
    Add(expression, value);
}

public void Add(string expression, params object[] parameters) 
{
    this.expressions.Add(new SearchExpression(expression, parameters));
}&lt;/pre&gt;&lt;p&gt;
                                Implementation of “references” to other objects go like this:&lt;/p&gt;&lt;pre name="c#"&gt;public IUserSearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt; CreatedBy 
{
    get 
    {
        return new UserSearch&amp;lt;TSearchParent, TItem, TCollection&amp;gt;(
            Application, ExpressionProvider, SearchParent, 
            ParentPath, "CreatedBy");
    }
}&lt;/pre&gt;&lt;p&gt;
                                And specifically for &lt;b&gt;User&lt;/b&gt; we have two classes called &lt;b&gt;UserSearch&lt;/b&gt; and
                                &lt;b&gt;UserSearch&amp;lt;TSearchParent,&lt;/b&gt;&lt;b&gt;TItem, TCollection&amp;gt;&lt;/b&gt;:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/bb050c6e050a450780f2e635b808ac5c.png' /&gt;&lt;p&gt;
                                The source for these are trivial, and the keywords are like in &lt;b&gt;SearchBase&lt;/b&gt;,
                                so it’s mostly constructors, but a couple of things to note about &lt;b&gt;UserSearch&lt;/b&gt;
                                is that this closes our chain of parents and inside the constructor it “closes”
                                our chain of parents by setting this to parent. (And this is maybe what I hate most
                                about our current implementation, I would like to put this responsibiliy within
                                my base class, but I just can get my head around that).&lt;/p&gt;&lt;pre name="c#"&gt;public class UserSearch
    : UserSearch&amp;lt;IUserSearch, User, UserCollection&amp;gt;, 
      IUserSearchRoot, IUserSearch 
{
    public UserSearch(Application app)
        : base(app) 
    {
        this.SearchParent = this;
    }
}

public class UserSearch&amp;lt;TSearchParent, TItem, TCollection&amp;gt;
    : SearchBase&amp;lt;TSearchParent, TItem, TCollection&amp;gt;,
      IUserSearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt;,
      IUserItemLoader&amp;lt;TItem&amp;gt;,
      IUserSearchLoader&amp;lt;TItem, TCollection&amp;gt;
    where TItem : ExtendedItemBase
    where TCollection : ExtendedItemBaseCollection 
{
    public UserSearch(Application app)
        : base(app) 
    {
    }

    public UserSearch(Application app, SearchExpressionProvider expressionProvider, TSearchParent searchParent, string parentPath, string path)
        : base(app, expressionProvider, searchParent, parentPath, path) 
    {
    }

    #region Implementation of IUserSearchKeywords&amp;lt;TSearchParent,TItem,TCollection&amp;gt;

    public TSearchParent Name(string name) 
    {
        return AddEq("Name", name);
    }

    #endregion
}&lt;/pre&gt;&lt;p&gt;
                                And then we've got a lot of interfaces:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/090ec3edf29a475ea570764a54d4bd9d.png' width="600" /&gt;&lt;p&gt;Basically we have interfaces for doing
                            &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;Load(Guid id)&lt;/code&gt; and &lt;code&gt;Load(IList&amp;lt;Guid&amp;gt; ids)&lt;/code&gt;:&lt;br /&gt;&lt;code&gt;IUserItemLoader&amp;lt;TItem&amp;gt;: IExtendedItemLoader&amp;lt;TItem&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;A &lt;code&gt;Load()&lt;/code&gt; using searchexpressions:&lt;br /&gt;&lt;code&gt;IUserItemLoader&amp;lt;TItem&amp;gt;: IExtendedItemLoader&amp;lt;TItem&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Keywords:&lt;br /&gt;&lt;code&gt;IUserSearchKeywords&amp;lt;TSearchParent, TItem, TCollection&amp;gt;: ISearchKeywords&amp;lt;TSearchParent,
                                        TItem, TCollection&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;
                                These interfaces are all implemented by &lt;code&gt;UserSearch&amp;lt;TSearchParent, TItem, TCollection&amp;gt;&lt;/code&gt;,
                                but we never expose that class in our API. That way we can control which operations
                                are available to the consumer at anytime.&lt;/p&gt;&lt;h3&gt;
                                Conclusion&lt;/h3&gt;&lt;p&gt;
                                That’s where we are now, we got the foundation, but we still need to add keywords,
                                but adding keywords is pretty easy, add it to the IXxxKeywords interface and then
                                implement it in the class that “complaints”, so it’s something we will add along
                                the way and whenever Adam adds new keywords.
                                &lt;br /&gt;
                                And also we’ve created a Resharper template for creating a new Adam object for searching
                                because the object structure and the interfaces needed are very similar, they only
                                differ on the adam object name.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Strongly typed searching in ADAM</title><link>http://blogs.adamsoftware.net/Engine/StronglytypedsearchinginADAM.aspx</link><description>&lt;div&gt;&lt;p&gt;This article is soooo cool, and it is so for several reasons.&lt;/p&gt;&lt;p&gt;First, I didn't write it. The idea, the development and writing the article are all done by &lt;b&gt;Søren Trudsø Mahon&lt;/b&gt; from our ADAM partner &lt;b&gt;&lt;a target='_blank' href="http://www.dxp.dk/"&gt;DXP&lt;/a&gt;&lt;/b&gt;.
Second, this isn't going to be a single blog post. This is only part one of three blog posts! This one gets you interested I'm sure, more details (and code!) will follow in the coming days. Stay tuned if you want to learn more about this!
Third. It's one of those things that any self respecting developer will see and say "Cooool". But that's just my humble opinion.&lt;/p&gt;&lt;p&gt;Anyway. Enough said. Next is Søren speaking:&lt;/p&gt;&lt;p&gt;Adam’s search is strong, very strong indeed. But as a developer we don’t like to write magic strings in our code:&lt;/p&gt;&lt;pre name="c#"&gt;new SearchExpression("Ancestor.Id = ?", 
  new object[] { classification.Id })&lt;/pre&gt;&lt;p&gt;And also we don’t have any type safety with regards to the value we are searching for:&lt;/p&gt;&lt;pre name="c#"&gt;new SearchExpression("Ancestor.Identifier = ?", 
  new object[] { classification.Id })&lt;/pre&gt;&lt;p&gt;Which will give us a runtime error.
So, what we would like to be able to write is a query like this:&lt;/p&gt;&lt;pre name="c#"&gt;Application.Search()
  .Classification
     .Ancestor.Id(classification.Id)&lt;/pre&gt;&lt;p&gt;This combines the power of strongly typed statements and the familiarity of Adam search.&lt;/p&gt;&lt;h3&gt;Using the api:&lt;/h3&gt;&lt;p&gt;The api is created as an extension method on &lt;b&gt;Adam.Core.Application&lt;/b&gt; called
    &lt;b&gt;Search()&lt;/b&gt;, from there you select what you want to search on fx. &lt;b&gt;App.Search().Record&lt;/b&gt; or 
    &lt;b&gt;App.Search().Classification&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;On “the” first level of the “chain” you can use the Adam Load methods &lt;b&gt;Load(Guid id)&lt;/b&gt; or 
                                &lt;b&gt;Load(IList&amp;lt;Guid&amp;gt; ids)&lt;/b&gt; to just directly load object of that type&lt;/p&gt;&lt;pre name="c#"&gt;IEnumerable&amp;lt;Record&amp;gt; enumerable = app.Search().Record.Load(
  new[] {record1.Id, record2.Id})&lt;/pre&gt;&lt;p&gt;Or you can perform an actual search.&lt;/p&gt;&lt;pre name="c#"&gt;IRecordSearch identifier = app.Search().Record
    .Classification.Identifier("First");
RecordCollection records = identifier.Load();&lt;/pre&gt;You could also just the &lt;b&gt;SearchExpression&lt;/b&gt; without loading any items and use that against a helper:
&lt;pre name="c#"&gt;IRecordSearch identifier = app.Search().Record
    .Classification.Identifier("First");
new RecordHelper(app).Exists(identifier.Expression);&lt;/pre&gt;

And you can refine your search expression in multiple lines:
&lt;pre name="c#"&gt;IRecordSearch identifier = app.Search().Record
    .Classification.Identifier("First");
identifier = identifier.CreatedBy.Name("administrator");&lt;/pre&gt;

Search examples:
&lt;pre name="c#"&gt;var rootIdentifier = "First";

// "Searching for a single Classification"
var rootClassification = app.Search().Classification
  .Identifier(rootIdentifier).Single();

// "Searching for underneath classification with identifier 'First'"
var classificationSearch = app.Search().Classification
  .AncestorOrSelf.Identifier(rootIdentifier);
classificationSearch.Print();

// "Refining the expression to include only those created 
// by 'administrator'"
classificationSearch = classificationSearch
  .CreatedBy.Name("administrator");
classificationSearch.Print();

// "Using search expression against helper"
SearchExpression classificationSearchExpression = 
  classificationSearch.Expression;
Console.WriteLine("SearchExpression:{0}", classificationSearchExpression);
var exists = new ClassificationHelper(app)
  .Exists(classificationSearchExpression);
Console.WriteLine(exists);

// Load using just the id (actually uses ExtendedItemBase.Load(Guid id))                
Classification classification = app.Search().Classification
  .Load(rootClassification.Id);&lt;/pre&gt;&lt;h3&gt;Using it in real life:&lt;/h3&gt;&lt;p&gt;Creating some kind of custom UI, where a user inputs for example a date or just  a string combined with some other criteria and then we can build a searchexpression for that:&lt;/p&gt;&lt;pre name="c#"&gt;Console.WriteLine("Input ancestor identifer and press 'Enter':");
var ancestorIdentifier = Console.ReadLine();
Console.WriteLine("Input search expression and press 'Enter':");
var searchExpression = Console.ReadLine();
var classifications = app.Search().Classification
    .AncestorOrSelf.Identifier(ancestorIdentifier)
    .Add(new SearchExpression(searchExpression))
    .Load();
classifications.Print();
Console.ReadKey();&lt;/pre&gt;&lt;p&gt;That’s where we are now, we got the foundation, but we still need to add keywords, but adding keywords is pretty easy, so it’s something we will add along the way and whenever Adam adds new keywords.&lt;/p&gt;&lt;p&gt;Wanna see the code? Wait a few more days. :-)&lt;/p&gt;&lt;p&gt;&lt;a target='_blank' href="http://www.dxp.dk"&gt;&lt;img src='http://blogs.adamsoftware.net/Files/6fbad473082742519b7f40c7e7faac1c.png' /&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Creating your own AdministrationProvider</title><link>http://blogs.adamsoftware.net/Web_Development/CreatingyourownAdministrationProvider.aspx</link><description>&lt;div&gt;&lt;h3&gt;Introduction&lt;/h3&gt;&lt;p&gt;As you might remember from one of our previous &lt;a target='_blank' href="http://blogs.adamsoftware.net/Webinars/TroubleshootingPerformanceTuningWebinar.aspx"&gt;webcasts&lt;/a&gt;, we provide a set of pages that provide a number of useful administration and monitoring tools for Adam, such as clearing translation or watermark caches, enabling auto-translations or viewing statistics. This set of pages is handled by the Admin Handler.&lt;/p&gt;&lt;p&gt;What few of you will know is that this handler is also designed with the well known Adam Provider Model in mind. Therefore, you can plug-in your own handler in this page and add additional monitoring tools.&lt;/p&gt;&lt;p&gt;In this blog post, I'll create my own handler that checks the state of the different servers participating in my Adam server environment.&lt;/p&gt;&lt;h3&gt;Prerequisites&lt;/h3&gt;&lt;p&gt;The code presumes that you've created an XML setting called "AdamServerList" that contains a list of all servers you want to monitor. For this example, I've used the following value:&lt;/p&gt;&lt;pre name="xml"&gt;&amp;lt;servers&amp;gt;
  &amp;lt;add name="ADAMS01" type="Database Server" /&amp;gt;
  &amp;lt;add name="ADAMS02" type="Fileserver" /&amp;gt;
  &amp;lt;add name="ADAMS03" type="Maintenance Server" /&amp;gt;
  &amp;lt;add name="ADAMS04" type="Indexing Server" /&amp;gt;
  &amp;lt;add name="ADAMS05" type="Web Server" /&amp;gt;
  &amp;lt;add name="ADAMS06" type="Workflow Server" /&amp;gt;
&amp;lt;/servers&amp;gt;&lt;/pre&gt;&lt;h3&gt;The code&lt;/h3&gt;&lt;p&gt;The only thing you'll need to do is create a class that inherits the  Adam.Web.Administration.Providers.AdministrationProvider that can be found in the Adam.Web.dll.&lt;/p&gt;&lt;p&gt;To implement this abstract class, you will need to develop the following methods and properties:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;CreateControlHierarchy&lt;/b&gt;: this is your hook to add controls to the page. In this method you can create a table, panel, ... basically any webcontrol and add it to the control hierarchy by calling this.Controls.Add().
&lt;/li&gt;&lt;li&gt;&lt;b&gt;GetMasterResetItems&lt;/b&gt;: this method needs to provide the calls that can be invoked when a user clicks the "Master Reset"-link in the Administration page. The calls that are chosen are then passed to the Reset method that can also be overridden.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;Title&lt;/b&gt;: the title of the page
&lt;/li&gt;&lt;li&gt;&lt;b&gt;Description&lt;/b&gt;: the description that will be displayed below the title
&lt;/li&gt;&lt;li&gt;&lt;b&gt;VendorName&lt;/b&gt;: your name. This will also appear at the bottom of the provider page.
&lt;/li&gt;&lt;li&gt;&lt;b&gt;VendorUrl&lt;/b&gt;: the url to your website. This will appear at the bottom of the provider page.&lt;/li&gt;&lt;/ul&gt;Once implemented, you can plugin your provider by adding the following configuration section to the web.config file of your Adam site:
&lt;p&gt;&lt;/p&gt;&lt;pre name="xml"&gt;&amp;lt;configSections&amp;gt;
  ...
  &amp;lt;section name="Adam.Web" type="Adam.Web.Configuration.AdamWebSection, Adam.Web" /&amp;gt;
  ...
&amp;lt;/configSections&amp;gt;
...
&amp;lt;Adam.Web&amp;gt;
  &amp;lt;administration&amp;gt;
    &amp;lt;providers&amp;gt;
      &amp;lt;add type="Monitoring.ServerStatusAdministrationHandler, Monitoring"/&amp;gt;
    &amp;lt;/providers&amp;gt;
  &amp;lt;/administration&amp;gt;
&amp;lt;/Adam.Web&amp;gt;
                            &lt;/pre&gt;&lt;h3&gt;The result&lt;/h3&gt;&lt;p&gt;If everything is configured correctly, you should be able to navigate to the AdamAdmin.axd page and view a link to the new provider at the left hand side of the page. Clicking on it, will give you a view of the basic connectivity status of your Adam servers:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/7d07613370a54236a587866c9164de90.png' width="600" /&gt;&lt;br /&gt;&lt;p&gt;The full source code for this sample can be found at the bottom of this post.&lt;/p&gt;&lt;h3&gt;Note&lt;/h3&gt;&lt;p&gt;Please note that this code is simplified for purposes of example. In a production environment, you should add 
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;additional code for checking input parameters of all methods
&lt;/li&gt;&lt;li&gt;additional code for trapping all errors that can be generated by the ping command
&lt;/li&gt;&lt;li&gt;an XSD Schema for the XML setting that contains the server list
&lt;/li&gt;&lt;li&gt;...&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Using the ping command presumes that the network connecting the different servers allows sending the necessary ICMP packets. The ping command also doesn't tell you anything about health parameters of the servers such as disk space, memory consumption,...&lt;/p&gt;&lt;p&gt;That's it! Have fun with this! Looking forward to seeing your work!&lt;/p&gt;&lt;/div&gt;</description></item><item><title>The case of the strange filenames.</title><link>http://blogs.adamsoftware.net/Web_Development/Thecaseofthestrangefilenames.aspx</link><description>&lt;div&gt;&lt;p&gt;
    A recent support call that came in discussed a problem concerning downloading 
    files from an ADAM system with the Internet Explorer family of browsers. The 
    problem occured when downloading files with non-ASCII characters in the 
    filename, using the following code:&lt;/p&gt;&lt;pre name="c#"&gt;
    AdamDownloader.DownloadFile(this, path, true);
&lt;/pre&gt;&lt;p&gt;
    On the client side, this results in the following dialog shown to the user:&lt;/p&gt;&lt;img style="margin-top: 10px;" src='http://blogs.adamsoftware.net/Files/dca1e294d2a74f488453db03da91604b.png' /&gt;&lt;p&gt;
    This is a particular hard problem to solve, as there is no single solution that 
    will work for all browsers. Let me explain...&lt;/p&gt;&lt;p&gt;First, I need to explain that this is not a problem with ADAM itself. The same 
    problem can be reproduced in a simple Web Application project. You use the 
    following code to specify the filename in ASP.NET:&lt;/p&gt;&lt;pre name="c#"&gt;
    string filename = "test.jpg";
    Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
    Response.TransmitFile(MapPath("~/Content/file.jpg"));
&lt;/pre&gt;&lt;p&gt;This particularly small snippet of code works fine, as long as your filenames do 
                                not contain any non-ASCII characters.&lt;/p&gt;&lt;p&gt;By default, all headers are encoded in UTF-8 by the webserver. This is not 
                                standard behaviour, as &lt;a target='_blank' href="http://www.ietf.org/rfc/rfc2047.txt"&gt;RFC 2047&lt;/a&gt; recommends that headers are encoded in ISO 
                                8859-1. However, it seems that allmost all browsers are broken when it comes to 
                                supporting this encoding.&lt;/p&gt;&lt;p&gt;&lt;a target='_blank' href="http://greenbytes.de/tech/tc2231/"&gt;Here&lt;/a&gt; you can find a detailed test for various methods to specifying filenames in 
                                response headers, and how different browsers respond to it. It seems that 
                                Internet Explorer is the more strict, in treating all headers as ISO 8859-1 as 
                                per standard, while FireFox 3 is more relaxed in allowing this header to be 
                                encoded in UTF-8. That also means that &lt;a target='_blank' href="http://greenbytes.de/tech/tc2231/#attwithutf8fnplain"&gt;an ISO 8859-1 string that resembles an UTF-8 string&lt;/a&gt; is misunderstood by FireFox as being UTF-8. 
                                This can lead to interesting effects.&lt;/p&gt;&lt;p&gt;At first one would think changing the default encoding in IIS 7 from UTF-8 to ISO 
                                8859-1. Alas, this doesn't work. I've tried it and the fairly common é is 
                                returned as byte sequence 0xBF, 0xEF, 0xBD, which is a disaster to all browsers. 
                                Why this happens I haven't found out yet.&lt;/p&gt;&lt;p&gt;Changing the header encoding in code, did work for me, however:&lt;/p&gt;&lt;pre name="c#"&gt;
    string filename = "tést.jpg";
    Response.HeaderEncoding = System.Text.Encoding.GetEncoding("iso-8859-1");
    Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
    Response.TransmitFile(MapPath("~/Content/file.jpg"));
&lt;/pre&gt;&lt;p&gt;This worked in IE8, FF3, Chrome and Safari, but not Opera. It will also not work with filenames that contain characters outside of ISO 8859-1, as those 
                                characters cannot be represented in any way in this encoding, unlike UTF-8.&lt;/p&gt;&lt;p&gt;Another candidate solution is to use &lt;a target='_blank' href="http://www.faqs.org/rfcs/rfc2231.html"&gt;RFC 2231&lt;/a&gt; compliant encoding of URLs in this 
                                header. This is easily accomplished:&lt;/p&gt;&lt;pre name="c#"&gt;
    string filename = HttpUtility.UrlPathEncode("tést.jpg");
    Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
    Response.TransmitFile(MapPath("~/Content/file.jpg"));
&lt;/pre&gt;&lt;p&gt;And this will work in IE8 and Chrome, but not in FF3, Safari or Opera which will 
                                show garbled filenames. These browsers only support the following way:&lt;/p&gt;&lt;pre name="c#"&gt;
    string filename = HttpUtility.UrlPathEncode("tést.jpg");
    Response.AppendHeader("Content-Disposition", "attachment; filename*=utf-8''\"" + filename + "\"");
    Response.TransmitFile(MapPath("~/Content/file.jpg"));
&lt;/pre&gt;&lt;p&gt;&lt;a target='_blank' href="http://www.brettle.com/ForumThreadView.aspx?thread=719&amp;pageindex=7"&gt;This forum post&lt;/a&gt; also discusses a third method using path info, but that is also 
                                not a general solution as it can only be used in IIS, not the Development 
                                Server, and only if you can somehow treat your downloads as a file from a 
                                certain server path.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;/div&gt;</description></item><item><title>Showing the image of a record when using DataSources</title><link>http://blogs.adamsoftware.net/Web_Development/ShowingtheimageofarecordwhenusingDataSources.aspx</link><description>&lt;div&gt;&lt;h3&gt;Introduction&lt;/h3&gt;&lt;p&gt;Since we have added a data source for ADAM in version 4.4, you got an easy way to consume ADAM objects in standard ASP.NET controls, like e.g. a &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;System.Web.UI.WebControls.&lt;a target='_blank' href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.aspx"&gt;&lt;span style="color:#2B91AF"&gt;GridView&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;Next to this, we have added at that time the &lt;span style="color:#2B91AF;font-size:10.0pt;font-family:Courier New;"&gt;FieldBinder&lt;/span&gt; mechanism to easily show the content of a &lt;span style="color:#2B91AF;font-size:10.0pt;font-family:Courier New;"&gt;Field&lt;/span&gt; when using the data sources framework.&lt;/p&gt;&lt;p&gt;But did you know that you have also an easy solution for showing images of a record? They are called 
    image binders and out-of-the-box, we provide you six of them:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;ClassificationImageBinder&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;FileTypeImageBinder&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;LanguageImageBinder&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;RecordImageBinder&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;UserImageBinder&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;WatermarkImageBinder&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;Usage&lt;/h3&gt;&lt;p&gt;Using them is similar to a &lt;span style="color:#2B91AF;font-size:10.0pt;font-family:Courier New;"&gt;FieldBinder&lt;/span&gt;. In the template of a data bound control, add a control that is capable of showing an image. Next, add e.g. an &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;Adam.Web.UI.WebControls.&lt;span style="color:#2B91AF;"&gt;RecordImageBinder&lt;/span&gt;&lt;/span&gt;, in the case you are binding to records of cource. On the &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;RecordImageBinder&lt;/span&gt;&lt;/span&gt;, specify in the &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;TargetControlID&lt;/span&gt; the &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;ID&lt;/span&gt; of the control that must show the image. Basically, that’s it 
    - as demonstrated in the sample below.&lt;/p&gt;&lt;pre name="ASPX"&gt;&amp;lt;asp:GridView ID="recordGrid" runat="server" 
              AutoGenerateColumns="false" 
              DataSourceID="recordDataSource" 
              PageSize="5" 
              AllowPaging="true"&amp;gt;
  &amp;lt;Columns&amp;gt;
    &amp;lt;asp:TemplateField HeaderText="Image"&amp;gt;
      &amp;lt;ItemTemplate&amp;gt;
        &amp;lt;asp:Image ID="recordImage" runat="server" /&amp;gt;
        &amp;lt;awc:RecordImageBinder ID="recordImageBinder" runat="server" 
                               TargetControlID="recordImage" /&amp;gt;
      &amp;lt;/ItemTemplate&amp;gt;
    &amp;lt;/asp:TemplateField&amp;gt;
  &amp;lt;/Columns&amp;gt;
&amp;lt;/asp:GridView&amp;gt;

&amp;lt;awd:AdamDataSource ID="recordDataSource" runat="server"
                    DataProviderType="Adam.Web.UI.DataSources.DataProviders.RecordProvider, Adam.Web"
                    DataOptionsProviderID="recordLoadOptions"
                    SelectExpressionMode="All" /&amp;gt;
&amp;lt;awd:RecordOptionsProvider ID="recordLoadOptions" runat="server"&amp;gt;
    &amp;lt;LoadOptions PreLoadFiles="FilesVersionsPreviews" /&amp;gt;
&amp;lt;/awd:RecordOptionsProvider&amp;gt;&lt;/pre&gt;&lt;p&gt;These image binders are not limited to &lt;span style="color:#2B91AF;font-size:10.0pt;font-family:Courier New;"&gt;Image&lt;/span&gt; controls only. If you have another 
    (custom) control with a different property than the &lt;span style="color:#2B91AF;font-size:10.0pt;font-family:Courier New;"&gt;Image&lt;/span&gt;&lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;.ImageUrl&lt;/span&gt; 
    property, you can 
    specify the &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;TargetPropertyName&lt;/span&gt; 
    on the image binder. This enables you to set for example the 
    &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;NavigationUrl&lt;/span&gt; of an &lt;span style="color:#2B91AF;font-size:10.0pt;font-family:Courier New;"&gt;HyperLink&lt;/span&gt; control, as demonstrated below.  &lt;/p&gt;&lt;pre name="ASPX"&gt;&amp;lt;asp:HyperLink ID="imageLink" runat="server" 
               Text="show preview" /&amp;gt;
&amp;lt;awc:RecordImageBinder ID="imageLinkBinder" runat="server" 
                       ImageType="Preview" 
                       TargetControlID="imageLink"
                       TargetPropertyName="NavigateUrl" /&amp;gt;&lt;/pre&gt;&lt;p&gt;Some of these image binders have even more options that allow you to control what 
    is shown. On a &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;RecordImageBinder&lt;/span&gt;&lt;/span&gt;, you can e.g. specify whether you want to 
    display the thumbnail or the preview of the record. Or specify whether a watermark must be 
    applied. Have a look at the controls to get a complete view.&lt;/p&gt;&lt;h3&gt;As a bonus&lt;/h3&gt;&lt;p&gt;Next to these image binder controls in the  
    &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;Adam.Web&lt;/span&gt; assembly, you'll find an 
    additional control, the &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;&lt;span style="color:#2B91AF;"&gt;ImageBox&lt;/span&gt;&lt;/span&gt; control. This control generates an image HTML 
    element, but allows the developer to set more behavior options. &lt;/p&gt;&lt;p&gt;If you set a  
    &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;Width&lt;/span&gt; and a  
    &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;Height&lt;/span&gt; on the control, you can specify how the image 
    must be resized to fit the specified dimensions. This is controlled by the 
    &lt;span style="font-size:10.0pt;font-family:Courier New;"&gt;SizeMode&lt;/span&gt; property, which has 4 possible values:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Normal&lt;/b&gt;&lt;br /&gt;The ImageBox is sized equal to the size of the image that it contains.&lt;br /&gt;
 &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;StretchImage&lt;/b&gt;&lt;br /&gt;The image within the ImageBox is stretched or shrunk to fit the size of the ImageBox.&lt;br /&gt;
 &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Clipped &lt;/b&gt;&lt;br /&gt;The image is placed in the ImageBox depending on the ImageLocation property. The image is clipped if it is larger than the ImageBox it is contained in. 
        &lt;br /&gt;
 &lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Zoom&lt;/b&gt;&lt;br /&gt;The size of the image is decreased maintaining the size ratio. When the image is larger than the ImageBox, the ImageLocation property is used to determine the location of the image in the box boundaries. &lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</description></item><item><title>Achieving the right look for your DataPager with a custom DataPagerField</title><link>http://blogs.adamsoftware.net/Web_Development/AchievingtherightlookforyourDataPagerwithacustomDataPagerField.aspx</link><description>&lt;div&gt;&lt;p&gt;One of the new controls introduced in ASP.NET 3.5 is the &lt;b&gt;ListView&lt;/b&gt; control. It gives you the same flexibility as the 
    &lt;b&gt;Repeater&lt;/b&gt; control, but with the features of the &lt;b&gt;GridView&lt;/b&gt; and &lt;b&gt;DetailsView&lt;/b&gt;, and then some! One of the niceties of this new control is that it uses the new 
    &lt;b&gt;DataPager&lt;/b&gt; control, and that it lets you place this anywhere on your page, not just inside your ListView.&lt;/p&gt;&lt;p&gt;This new DataPager gives you a lot more control over its looks than what was available before. This control leaves all the rendering of the output to one of the 
    &lt;b&gt;DataPagerField&lt;/b&gt; objects that you add to it, like so:&lt;/p&gt;&lt;pre name="ASPX"&gt;
&amp;lt;asp:DataPager runat="server" ID="pager" PageSize="10" &amp;gt;
  &amp;lt;Fields&amp;gt;
    &amp;lt;asp:NumericPagerField /&amp;gt;
    &amp;lt;asp:NextPreviousPagerField /&amp;gt;
    &amp;lt;asp:TemplatePagerField&amp;gt;
      &amp;lt;PagerTemplate&amp;gt;&amp;lt;/PagerTemplate&amp;gt;
    &amp;lt;/asp:TemplatePagerField&amp;gt;
  &amp;lt;/Fields&amp;gt;
&amp;lt;/asp:DataPager&amp;gt;
&lt;/pre&gt;&lt;p&gt;ASP.NET 3.5 ships with three such pager fields: the &lt;b&gt;NextPreviousPagerField&lt;/b&gt;, which displays buttons for the next or previous page, the 
    &lt;b&gt;NumericPagerField&lt;/b&gt;, which displays a series of buttons for pages, and last but not least the 
    &lt;b&gt;TemplatePagerField&lt;/b&gt;, which gives you fine control over the rendered output using a template. This, however, can lead to pretty complex markup in your ASPX page. You can, however, create your own custom DataPagerField, and it isn’t terribly difficult. In this article, I will explain you how.&lt;/p&gt;&lt;p&gt;For one of our customers, we needed a pager that would show a series of buttons, but that would follow the current page and provide a “window” around it, instead of simply “paging the pager” like the NumericPagerField would. Given a ListView with a content of 97 items and a PageSize of 10, we would want to display the following while on the first page:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/044470c869d44e1392b5644ab934a486.png' /&gt;&lt;p&gt;When the user moves further in the pages, the list of pages would start to follow, and center the current page:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/dc93cb251f424d688bbfed423e1e341b.png' /&gt;&lt;p&gt;And when at the end, obviously, it would stop scrolling:&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/b0e5d6c7d5314cd49623437582d16f1f.png' /&gt;&lt;p&gt;The “next” and “prev” buttons would also not move a whole 10 pages, but work the same as the NextPreviousPagerField and move one page up or down.&lt;/p&gt;&lt;p&gt;The HTML required for this look would look like this (as specified by the designer):&lt;/p&gt;&lt;pre name="ASPX"&gt;
&amp;lt;div class=”pager”&amp;gt;
    &amp;lt;a href=”#”&amp;gt;&amp;amp;lt;&amp;amp;lt; prev&amp;lt;/a&amp;gt;
    &amp;lt;a href=”#”&amp;gt;1&amp;lt;/a&amp;gt;
    &amp;lt;span&amp;gt;2&amp;lt;/span&amp;gt;
    &amp;lt;a href=”#”&amp;gt;3&amp;lt;/a&amp;gt;
    &amp;lt;a href=”#”&amp;gt;next &amp;amp;gt;&amp;amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;&lt;p&gt;At first I felt a combination of two NextPreviousPagerFields and TemplatePagerField would do the trick, but this resulted in bloated and incomprehensible markup. So I turned to implementing my own custom DataPagerField descendant called 
    &lt;b&gt;FollowingPagerField&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Firstly, we create a class that derives from DataPagerField. The documentation states that three methods must be overridden for this to work: 
    &lt;b&gt;CreateField&lt;/b&gt;, &lt;b&gt;CreateDataPagers&lt;/b&gt; and &lt;b&gt;HandleEvent&lt;/b&gt;.&lt;/p&gt;&lt;pre name="C#"&gt;
public class FollowingPagerField : DataPagerField
{
    protected override DataPagerField CreateField()
    {     
        return new FollowingPagerField();
    }

    public override void CreateDataPagers(
        DataPagerFieldItem container, int startRowIndex, 
        int maximumRows, int totalRowCount, int fieldIndex)
    {
    }

    public override void HandleEvent(CommandEventArgs e)
    {
    }
}
&lt;/pre&gt;&lt;p&gt;&lt;b&gt;CreateField()&lt;/b&gt; is required to return a new instance of this class, and is used when cloning the PagerFields collection of the DataPager, so we’re not going to pay further attention to it.&lt;/p&gt;&lt;p&gt;&lt;b&gt;CreateDataPagers()&lt;/b&gt; is called by the DataPager, and in this method we must produce all the controls required for rendering. We can use the parameters to calculate the page that we’re on so we can completely render our pager.&lt;/p&gt;&lt;p&gt;&lt;b&gt;HandleEvent()&lt;/b&gt; is called when the user clicks on one of the buttons that we render. These buttons contain a 
    &lt;b&gt;CommandName&lt;/b&gt; and optionally a &lt;b&gt;CommandArgument&lt;/b&gt; that we get here to decide what to do with the DataPager: move a page up or down, or move to a specific page.&lt;/p&gt;&lt;p&gt;I added a couple of properties to allow the user of the component to modify the look a little bit, but these can certainly be expanded upon later:&lt;/p&gt;&lt;pre name="C#"&gt;
private string _previousText = "&amp;lt;&amp;lt;";
private string _nextText = "&amp;gt;&amp;gt;";
private int _buttonCount = 5;

public string PreviousText{
    get { return this._previousText; }
    set { this._previousText = value; }
}

public string NextText
{
    get { return this._nextText; }
    set { this._nextText = value; }
}

public int ButtonCount
{
    get { return this._buttonCount; }
    set { this._buttonCount = value; }
}
&lt;/pre&gt;&lt;p&gt;Implementing &lt;b&gt;CreateDataPagers()&lt;/b&gt; was pretty straightforward, using a couple of helper methods:&lt;/p&gt;&lt;pre name="C#"&gt;
private void CreatePages(Control container, 
    IEnumerable&amp;lt;int&amp;gt; pages, int current)
{
    foreach (int page in pages)
    {
        if (page == current)
        {
            container.Controls.Add(new HtmlGenericControl 
            { 
                TagName = "span", 
                InnerHtml = page.ToString() 
            });
        }
        else
        {
            container.Controls.Add(new LinkButton
            {
                Text = page.ToString(),
                CommandName = "Page",
                CommandArgument = page.ToString()
            });
        }
    }
}

private void CreateLink(Control container, string caption, 
    string command, bool enabled)
{
    LinkButton button = new LinkButton 
    { 
        Text = caption, 
        CommandName = command, 
        Enabled = enabled 
    };

    if (!enabled)
    {
        button.CssClass = "disabled";
    }

    container.Controls.Add(button);
}

public override void CreateDataPagers(
    DataPagerFieldItem container, int startRowIndex, 
    int maximumRows, int totalRowCount, int fieldIndex)
{
    // The pages here are 0-based. (Page 1 = 0, Page 2 = 1, ...)
    int page = (startRowIndex / maximumRows);
    int totalPages = (totalRowCount / maximumRows);

    // Create a container.
    HtmlGenericControl pagerDiv = new HtmlGenericControl("div");
    pagerDiv.Attributes["class"] = "pager";
    container.Controls.Add(pagerDiv);

    CreateLink(pagerDiv, PreviousText, "Prev", page &amp;gt; 0);

    int firstPage = Math.Max(page - (this._buttonCount / 2), 0);
    int lastPage = Math.Min(firstPage + this._buttonCount, totalPages);
    int count = lastPage - firstPage;

    if (count &amp;lt; this._buttonCount)
    {
        firstPage = Mth.Max(lastPage - this._buttonCount, 0);
        count = lastPage - firstPage;
    }

    CreatePages(pagerDiv, 
        Enumerable.Range(firstPage + 1, count), page + 1);

    CreateLink(pagerDiv, NextText, "Next", (page + 1) &amp;lt; totalPages);
}
&lt;/pre&gt;&lt;p&gt;A simple container control is created to contain all the elements, which needs to be a div element with a specific CSS class. Again, this can be changed to find the classname in properties, but that’s beside the point here. The heart of the problem is calculating which pages to show.&lt;/p&gt;&lt;p&gt;The &lt;b&gt;HandleEvent()&lt;/b&gt; method was even simpler, simply matching the CommandName parameter and parsing the CommandArgument parameter and decide what to do with the current view:&lt;/p&gt;&lt;pre name="C#"&gt;
public override void HandleEvent(CommandEventArgs e)
{
    int newStartRowIndex = -1;

    if (e.CommandName.Equals("Prev"))
    {
        if (this.DataPager.StartRowIndex &amp;gt;= this.DataPager.PageSize)
        {
            newStartRowIndex = this.DataPager.StartRowIndex - 
                this.DataPager.PageSize;
        }
    }
    else if (e.CommandName.Equals("Next"))
    {
        if ((this.DataPager.StartRowIndex + this.DataPager.PageSize) &amp;lt; 
            this.DataPager.TotalRowCount)
        {
            newStartRowIndex = this.DataPager.StartRowIndex + 
                this.DataPager.PageSize;
        }
    }
    else if (e.CommandName.Equals("Page"))
    {
        int page;

        if (int.TryParse(e.CommandArgument.ToString(), out page))
        {
            int newIndex = (page - 1) * this.DataPager.PageSize;

            if ((newIndex &amp;gt;= 0) || 
                (newIndex &amp;lt; this.DataPager.TotalRowCount))
            {
                newStartRowIndex = newIndex;
            }
        }
    }

    if (newStartRowIndex &amp;gt;= 0)
    {
        this.DataPager.SetPageProperties(newStartRowIndex, 
            this.DataPager.MaximumRows, true);
    }
}
&lt;/pre&gt;&lt;p&gt;Since we create the links in the rendered output, we know what to expect when handling this event. I think the code speaks for itself.&lt;/p&gt;&lt;p&gt;Lastly, we need to register our new toy in the page, and instantiate it in the DataPager:&lt;/p&gt;&lt;pre name="ASPX"&gt;
&amp;lt;%@ Register assembly="OurAssembly" Namespace="OurNamespace" TagPrefix="us" %&amp;gt;

&amp;lt;asp:ListView runat="server" ID="lv" DataSourceID="rs" DataKeyNames="Id"&amp;gt;
  &amp;lt;LayoutTemplate&amp;gt;
    &amp;lt;asp:DataPager runat="server" ID="pager" PageSize="5" &amp;gt;
      &amp;lt;Fields&amp;gt;
        &amp;lt;us:FollowingPagerField NextText="next &amp;gt;&amp;gt;" 
           PreviousText="&amp;lt;&amp;lt; prev" ButtonCount="10"/&amp;gt;
      &amp;lt;/Fields&amp;gt;
    &amp;lt;/asp:DataPager&amp;gt;
  &amp;lt;/LayoutTemplate&amp;gt;
&amp;lt;/asp:ListView&amp;gt;
&lt;/pre&gt;&lt;p&gt;So there you have it, a working custom pager by implementing two methods!&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Using Adam as a SaaS solution</title><link>http://blogs.adamsoftware.net/Engine/UsingAdamasaSaaSsolution.aspx</link><description>&lt;div&gt;&lt;p&gt;
                A couple of our partners are using Adam to provide &lt;a target='_blank' href="http://en.wikipedia.org/wiki/Software_as_a_service"&gt;
                  SaaS&lt;/a&gt; solutions to their customers and we try to keep that in the back of our
                mind whenever we’re designing a new module, studio or feature. A couple of examples:
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;Sites are most often used to specify different setting values depending on the
                    physical server that connects to the Adam database. However, they can also be used
                    to set different setting values depending on the site that a user uses. In that
                    case you need to mutiple sites and setup multiple site registrations (check Admin Guide &amp;gt; System
                    Configuration &amp;gt; Sites &amp;gt; Sites for more info on how to do this) on one physical
                    server. After that, your Adam.Core.Server.exe.config file will look somewhat 
                    like this:
                    &lt;pre name="xml"&gt;&amp;lt;databaseregistrations&amp;gt;
  &amp;lt;add name="AdamCustomer1" sqlServer="LOCALHOST" sqlDatabase="AdamSaas"
  workingFolder="D:\Adam\AdamCustomer1" siteName="Customer1"/&amp;gt;
  &amp;lt;add name="AdamCustomer2" sqlServer="LOCALHOST" sqlDatabase="AdamSaas"
  workingFolder="D:\Adam\AdamCustomer2" siteName="Customer2"/&amp;gt;
&amp;lt;/databaseregistrations&amp;gt;&lt;/pre&gt;
                    After this you simply install a separate AssetStudio/ConfigStudio/Custom Studio
                    for each of the sites and make them connect to the corresponding registrations.
                    That way, a user logging in through &lt;a target='_blank' href="#"&gt;http://customer1.yoursaasprovider.com&lt;/a&gt;
                    will use different setting values compared to one logging in at &lt;a target='_blank' href="#"&gt;http://customer2.yoursaasprovider.com&lt;/a&gt;.
                  &lt;/li&gt;&lt;li&gt;Another useful concept is Adam Organizations. These help you to shield of the
                    working areas of your different customers. Start by creating an organization for
                    each customer. Next you can create different user groups that belong to a specific
                    organization and assign different permissions to them. Once this is done, you’ll
                    automatically see new roles in the Security &amp;gt; Organization section of a user group
                    profile:&lt;br /&gt;&lt;img src='http://blogs.adamsoftware.net/Files/afdcc5c52457416dbcd479a01cd64d75.jpg' width="600" /&gt;
                    In a similar way you’ll also be able to make certain groups manage or view
                    fieldgroups, languages, filetypes, ... : just click a couple of the other links
                    of the Security-section of a user group profile.&lt;/li&gt;&lt;li&gt;The final piece of the puzzle
                      is where the actual work starts for a SaaS customer: simply create a root classification
                      node for each customer and given the right permissions, the customer will be able
                      to create/edit/delete classifications, fields, field groups, user groups and users
                      that only his users can see.
                      &lt;img src='http://blogs.adamsoftware.net/Files/35235cf26b064b6cba51c1ee9a294714.jpg' width="600" /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;
                  As you can imagine, putting all of this together can lead up to challenging situations
                  and results that –at first sight- seem to be quite unexpected. When fine-tuning
                  and debugging these things, the Permission Viewers can be very useful tools: try
                  them out; you can find them in the Config Studio in Advanced Features.&lt;/p&gt;&lt;p&gt;
                  Hope someone finds this useful. Looking forward to your feedback!&lt;/p&gt;&lt;/div&gt;</description></item><item><title>ADAM Kick Off 2010 Conference, Tuesday January 26th, Ghent - Belgium</title><link>http://blogs.adamsoftware.net/Announcements/ADAMKickOff2010ConferenceTuesdayJanuary26thGhentBelgium.aspx</link><description>&lt;div&gt;&lt;br /&gt;&lt;b&gt;IT is DAM business&lt;/b&gt;&lt;p&gt;Why are ADAM customers such as LEGO, Microsoft, Elopak and many more shifting their focus from cost control to proven ROI? ADAM Software has changed the perception on Digital Asset Management from a super file system into a business execution system.&lt;/p&gt;&lt;p&gt;At the 5th ADAM Kick Off conference, we present customer cases, product introductions and analyst's insights.&lt;/p&gt;&lt;p&gt;Take the opportunity, together with more than 120 professionals from leading organizations, to discuss what's happening in your world of DAM.&lt;/p&gt;&lt;p&gt;For complete details and registration, visit &lt;a target='_blank' href="http://www.adamsoftware.net/kickoff"&gt;http://www.adamsoftware.net/kickoff&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Create a preview player for Flash Video (FLV)</title><link>http://blogs.adamsoftware.net/Web_Development/CreateapreviewplayerforFlashVideoFLV.aspx</link><description>&lt;div&gt;&lt;p&gt;Flash Video (FLV files) became a popular file format for delivering video on the web. These files cannot be embedded on a web page on their own. A FLV player, created in Flash, is required to play those video files.&lt;/p&gt;&lt;p&gt;One solution could be to create your own FLV player in Flash. Or you can search the web for an existing FLV player, there is enough choice out there. For this article, we are going to use the player of &lt;a target='_blank' href="http://flv-player.net/"&gt;http://flv-player.net/&lt;/a&gt;, an open source Flash Video player. This should not be considered as 'the way to go'. We just needed one to demonstrate the idea of playing FLV files in ADAM.  &lt;/p&gt;&lt;h3&gt;About FLV player&lt;/h3&gt;&lt;p&gt;Before we create our FLV preview player, we first need to understand how the player is working. Luckily, the flv-player.net website has a wizard that helps us to generate the look-and-feel of the player: &lt;a target='_blank' href="http://flv-player.net/players/maxi/generator/"&gt;FLV Player generator&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you look at the generated HTML code, you'll see two important parameters for the OBJECT tag: the actual movie and the FlashVars. The actual movie is the SWF file that is capable of playing the actual FLV file  The FlashVars instruct the player how it should behave.&lt;/p&gt;&lt;p&gt;The generated HTML code can be used as-is, but we can improve the code by loading the Flash movie through JavaScript, which resolves issues related to different browsers and makes it easy to build the OBJECT tag. To do so, we can rely on a framework called &lt;a target='_blank' href="http://code.google.com/p/swfobject/"&gt;SWFObject&lt;/a&gt;. A full explanation on why you should use such a framework can be found in this web page: &lt;a target='_blank' href="http://www.alistapart.com/articles/flashembedcagematch/"&gt;Flash Embedding Cage Match&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Converting the HTML code to JavaScript using SWFObject is pretty simple and constructing the FlashVars is much easier this way, as you can see in the following code snippet (for more information about the SWFObject features, see &lt;a target='_blank' href="http://code.google.com/p/swfobject/wiki/documentation"&gt;SWFObject documentation&lt;/a&gt;).&lt;/p&gt;&lt;pre name="JavaScript"&gt;var flashvars = {"flv": "myvideo.flv"};
swfobject.embedSWF(swfUrl, 
                   idOfTargetElement, 
                   width, 
                   height, 
                   requiredFlashVersion, 
                   expressionInstallationSwfUrl, 
                   flashvars);&lt;/pre&gt;&lt;p&gt;For this article, you need to download the next two files:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a target='_blank' href="http://flv-player.net/medias/player_flv_maxi.swf"&gt;player_flv_maxi.swf&lt;/a&gt;&lt;br /&gt;This is the SWF file which is capable of playing the FLV file.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a target='_blank' href="http://swfobject.googlecode.com/files/swfobject_2_2.zip"&gt;swfobject_2_2.zip&lt;/a&gt;&lt;br /&gt;A JavaScript library to dynamically load SWF files.&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;The Visual Studio project&lt;/h3&gt;&lt;b&gt;&lt;br /&gt;Embedding resources&lt;/b&gt;&lt;p&gt;Playing an FLV file requires more than some C# code and an FLV file. You'll also need the SWF file (the actual player) and when using the SWFObject approach, the JavaScript file containing the SWFObject code. Since the ADAM preview players are added to a .NET Class Library, there is no actual directory available where you can place the extra SWF and JavaScript files. This is a common problem when developing web solutions and therefore the ASP.NET framework provides us with a solution: embedded resources.&lt;/p&gt;&lt;p&gt;In your Visual Studio class library project, add a new folder '&lt;b&gt;Files&lt;/b&gt;' and drag-and-drop the files &lt;b&gt;player_flv_maxi.swf&lt;/b&gt; and &lt;b&gt;swfobject.js&lt;/b&gt; into this folder in Visual Studio&lt;br /&gt;&lt;br /&gt;&lt;img src='http://blogs.adamsoftware.net/Files/31f0307d93624db0b8405957c5d4e1dd.jpg' /&gt;&lt;br /&gt;&lt;br /&gt;Now, select both files in the Visual Studio Solution Explorer, right-click them and choose '&lt;b&gt;Properties&lt;/b&gt;'. &lt;br /&gt;&lt;br /&gt;&lt;img src='http://blogs.adamsoftware.net/Files/6a30203b8e36474a8908fa9ce4a00db0.jpg' /&gt;&lt;br /&gt;&lt;br /&gt;In the properties window, change the Build Action from '&lt;b&gt;Content&lt;/b&gt;' to '&lt;b&gt;Embedded Resource&lt;/b&gt;'. This ensures that those files are embedded in the compiled assembly.&lt;br /&gt;&lt;br /&gt;&lt;img src='http://blogs.adamsoftware.net/Files/4ea71a371f444261a6d90b9a75cd4d8b.jpg' /&gt;&lt;/p&gt;&lt;p&gt;After embedding the files in the assembly, we need to tell the ASP.NET framework that these files must be accessible from an URL request. To do so, add a new C# file to your solution and name it &lt;span style="FONT-FAMILY: Courier New, Courier"&gt;AssemblySetup.cs&lt;/span&gt;. Clear the complete contents of the file and add the following code. This code actually instructs ASP.NET to make the embedded resources available from an URL request (how to get an URL to those embedded resources is shown later on).&lt;/p&gt;&lt;pre name="C#"&gt;using System.Web.UI;

[assembly: System.Web.UI.WebResource("FLVPlayer.Files.player_flv_maxi.swf", "application/x-shockwave-flash")]
[assembly: System.Web.UI.WebResource("FLVPlayer.Files.swfobject.js", "text/js")]&lt;/pre&gt;&lt;b&gt;&lt;br /&gt;The actual preview player&lt;/b&gt;&lt;p&gt;Creating the preview player is pretty much the same as described in the blog article &lt;a target='_blank' href="CreateapreviewplayerforFlashSWFfiles.aspx"&gt;Create a preview player for Flash (SWF) files&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;However, there are some differences between both articles:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The preview player requires the inclusion of an additional JavaScript 
&lt;/li&gt;&lt;li&gt;The SWF file is not the FileVersion, but the player embedded in the assembly 
&lt;/li&gt;&lt;li&gt;The file that must be previewed is a parameter for the Flash movie&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To include an embedded JavaScript file in the generated HTML of a Page, use the &lt;span style="FONT-FAMILY: Courier New, Courier"&gt;GetWebResourceUrl&lt;/span&gt; method of the &lt;span style="FONT-FAMILY: Courier New, Courier"&gt;System.Web.UI.&lt;/span&gt;&lt;span style="COLOR: #2b91af; FONT-FAMILY: Courier New, Courier"&gt;ClientScriptManager&lt;/span&gt; class, as demonstrated in the following code snippet:&lt;/p&gt;&lt;pre name="C#"&gt;// Include the JavaScript.
ClientScriptManager manager = this.Page.ClientScript;

// Test if the script file is not already included in the HTML output.
if (manager.IsClientScriptIncludeRegistered(typeof(FLVPreviewPlayer), "FLVPlayer.Files.swfobject.js") == false)
{
  // Get the url to the embedded resource.
  String scriptUrl = manager.GetWebResourceUrl(typeof(FLVPreviewPlayer), "FLVPlayer.Files.swfobject.js");
  // Add the script to the HTML output.
  manager.RegisterClientScriptInclude(typeof(FLVPreviewPlayer), "FLVPlayer.Files.swfobject.js", scriptUrl);
}&lt;/pre&gt;&lt;p&gt;All the rest is very similar to the previous article, except for the fact that we now need to generate some JavaScript.&lt;/p&gt;&lt;pre name="C#"&gt;protected override void CreateChildControls()
{
    FileVersion version = this.DataItem as FileVersion;
    if (version != null &amp;amp;&amp;amp; string.IsNullOrEmpty(version.Path) == false)
    {
        // Include the JavaScript.
        ClientScriptManager manager = this.Page.ClientScript;

        // Test if the script file is not already included in the HTML output.
        if (manager.IsClientScriptIncludeRegistered(typeof(FLVPreviewPlayer), "FLVPlayer.Files.swfobject.js") == false)
        {
            // Get the url to the embedded resource.
            String scriptUrl = manager.GetWebResourceUrl(typeof(FLVPreviewPlayer), "FLVPlayer.Files.swfobject.js");
            // Add the script to the HTML output.
            manager.RegisterClientScriptInclude(typeof(FLVPreviewPlayer), "FLVPlayer.Files.swfobject.js", scriptUrl);
        }

        // Get the url to the FLV player (the SWF file).
        string swfUrl = manager.GetWebResourceUrl(typeof(FLVPreviewPlayer), "FLVPlayer.Files.player_flv_maxi.swf");

        // Get the url to the FLV file being previewed.
        ServerFileUri uri = new ServerFileUri(version.Path, "application/x-unknown-content-type");
        string flvUrl = uri.ToString();

        // Create a placeholder for the FLV player on the client.
        HtmlGenericControl placeholder = new HtmlGenericControl("div");
        placeholder.ID = "container";
        placeholder.InnerText = "No Flash player installed";
        this.Controls.Add(placeholder);

        // Prepare variables for the SWFObject framework.
        int width = 470;
        int height = 320;
        String requiredFlashVersion = "9.0.0";

        // Create the script to load the FLV player...
        StringBuilder script = new StringBuilder();
        // Create the flash variables object.
        script.AppendFormat("var flashvars = {{'flv': '{0}', 'autoplay': '1', 'showtime': '1', 'showfullscreen': '1', 'buffermessage': ''}};", HttpUtility.UrlEncode(flvUrl));
        // And embed the SWF file in the HTML document.
        script.AppendFormat("swfobject.embedSWF('{0}', '{1}', '{2}', '{3}', '{4}', null, flashvars, {{'allowfullscreen': 'true'}});", new Object[] { swfUrl, placeholder.ClientID, width, height, requiredFlashVersion });

        // Register the script that loads the FLV player for the FLV file being previewed.
        manager.RegisterStartupScript(typeof(FLVPreviewPlayer), "load", script.ToString(), true);
    }
    else
    {
        this.Controls.Add(new LiteralControl("No FileVersion available or the file could not be found."));
    }
}&lt;/pre&gt;&lt;p&gt;The steps to register the preview player in ADAM are identical to the ones described in the &lt;a target='_blank' href="CreateapreviewplayerforFlashSWFfiles.aspx"&gt;Create a preview player for Flash (SWF) files&lt;/a&gt; article.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Disabling Search Operators</title><link>http://blogs.adamsoftware.net/Engine/DisablingSearchOperators.aspx</link><description>&lt;div&gt;&lt;p&gt;The search framework in ADAM has a small and little known feature that can 
    improve the search experience of your users. By default, the search framework 
    supports a whole bunch of operators like OR, AND, NOT, CONTAINS, =, &amp;gt;, &amp;lt;&amp;gt; and so 
    on. Next to that, there are also characters that give a keyword in search 
    expression a special meaning like an ampersand (@), a question mark (?), a dot 
    (.) and others.&lt;/p&gt;&lt;p&gt;These operators and special characters give you the developer, or the users using 
                                your custom ADAM website, access to some of the advanced search functionality. 
                                However, sometimes these features are overkill and hardly used by your users. In 
                                this case, you can disable the search keywords that you don't want your users to 
                                use. Once a keyword is disabled, it is treated by the search framework as any 
                                other ordinary character and it looses its special meaning.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre name="c#"&gt;SearchExpression expr = new SearchExpression("2009 not on the road");
expr.DisabledKeywords = DisabledKeyword.QuestionMark | DisabledKeyword.Dot |
  DisabledKeyword.At | DisabledKeyword.Contains | 
  DisabledKeyword.Or | DisabledKeyword.Not;&lt;/pre&gt;&lt;p&gt;The previous code sample creates a search expression that has the specified keywords disabled. 
    This ensures for example that your users don't have to quote the &lt;i&gt;not &lt;/i&gt;they 
    specified in &lt;i&gt;not on the road&lt;/i&gt;.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>FireFox slow when browsing your local ASP.NET apps?</title><link>http://blogs.adamsoftware.net/Web_Development/FireFoxslowwhenbrowsingyourlocalASPNETapps.aspx</link><description>&lt;div&gt;&lt;p&gt;
    There's an issue with FireFox when used to debug ASP.NET applications together with the ASP.NET Development Server on Windows Vista/Windows 7. 
    Performance seems sluggish, especially compared to Internet Explorer. The solution is pretty simple, once you know what the problem is.
&lt;/p&gt;&lt;p&gt;
    The problem is related to an issue with FireFox on these new operating systems to resolve the IPv6 address of localhost. 
    This results in such slow perceived performance, while Internet Explorer doesn't suffer the same fate. 
    To solve the problem, there's two solutions:
&lt;/p&gt;&lt;p&gt;
    The first solution is to disable IPv6 in FireFox alltogether. If you feel this is a bit drastic (as I do) then you can read on to the next solution.
    Follow these steps:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;
        Type in &lt;b&gt;about:config&lt;/b&gt; in the address bar of your browser. Heed the warning about the dragons, then proceed to the list of settings.
    &lt;/li&gt;&lt;li&gt;
        Search or scroll to the setting named &lt;b&gt;network.dns.disableIPv6&lt;/b&gt;.
    &lt;/li&gt;&lt;li&gt;
        Double-click the value to set it to &lt;b&gt;true&lt;/b&gt;.
    &lt;/li&gt;&lt;li&gt;
        Restart your browser.
    &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;
    The second solution is very similar, but instead of disabling all of IPv6 you simply add "localhost" as a domain to the list of domains to ignore IPv6 on, like so:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;
        Type in &lt;b&gt;about:config&lt;/b&gt; in the address bar of your browser. Skip the warning, then proceed to the list of settings.
    &lt;/li&gt;&lt;li&gt;
        Search or scroll to the setting named &lt;b&gt;network.dns.ipv4OnlyDomains&lt;/b&gt;.
    &lt;/li&gt;&lt;li&gt;
        Double-click the value to edit it, and add &lt;b&gt;localhost&lt;/b&gt;.
    &lt;/li&gt;&lt;li&gt;
        Restart your browser.
    &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;
    That should make browsing much faster. The original article can be found &lt;a target='_blank' href="http://dotnetslackers.com/ASP_NET/re-122146_Speeding_Up_FireFox_When_Using_the_ASP_NET_Development_Server_from_Localhost.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Scripting ADAM with IronPython</title><link>http://blogs.adamsoftware.net/Engine/ScriptingADAMwithIronPython.aspx</link><description>&lt;div&gt;&lt;p&gt;
    IronPython is an implementation of the Python language for the .NET framework, 
    using the new Dynamic Language Runtime (DLR) as language services layer on top 
    of the Common Language Runtime (CLR). The DLR's reusable hosting model makes it 
    extremely suitable to add scripting capabilities to existing products.&lt;/p&gt;&lt;p&gt;
                                In this post we'll create an ADAM command line utility that will allow us to run 
                                IronPython scripts against an ADAM application.&lt;/p&gt;&lt;h3&gt;
                                Getting IronPython&lt;/h3&gt;&lt;p&gt;
                                IronPython can be downloaded from its CodePlex project page:
                                &lt;a target='_blank' href="http://ironpython.codeplex.com/"&gt;http://ironpython.codeplex.com/&lt;/a&gt;. 
                                For this post we're using version 2.6 RC3. After downloading, installation is 
                                pretty straight-forward.&lt;/p&gt;&lt;h3&gt;
                                Setting up a console application project&lt;/h3&gt;&lt;p&gt;
                                Using Visual Studio 2008, create a new console project named 
                                Adam.Scripting.CommandLine and add references to the following assemblies (the 
                                IronPython assemblies can be found in the IronPython installation directory, 
                                which defaults to C:\Program Files\IronPython-2.6):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Adam.Core.dll&lt;/li&gt;&lt;li&gt;Adam.Tools.dll&lt;/li&gt;&lt;li&gt;IronPython.dll&lt;/li&gt;&lt;li&gt;Microsoft.Scripting.dll&lt;/li&gt;&lt;li&gt;Microsoft.Scripting.Core.dll&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;
                                The Adam.Tools assembly contains a set of classes that make life simpeler for 
                                console application developers, and this is a nice occassion to elaborate on 
                                some of these helpers. The
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Arguments&lt;/span&gt; 
                                class exposes
                                methods for parsing command line parameters and executing commands, much like 
                                the standard Adam.Core.CommandLine.exe and Adam.Core.DatabaseManager.exe work.&lt;/p&gt;&lt;p&gt;
                                Our command line tool will expose a single command, RunScript, that will take in 
                                ADAM connection information and a path to a Python file to execute:&lt;/p&gt;&lt;pre name="c#"&gt;static readonly Command[] ProgramCommands =
{
  new Command("RunScript", RunScript, RunScriptHelp)
};&lt;/pre&gt;&lt;p&gt;As you can see, a &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Command&lt;/span&gt; 
                                is defined by a command name (which is used to identify the command passed 
                                through the command line), and two delegates: one that handles the execution of 
                                the command, and one that displays the help information for the command. These 
                                delegates are automatically invoked when calling the 
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Arguments.ExecuteCommand(Command[], DisplayHelpDelegate)&lt;/span&gt; method. &lt;/p&gt;&lt;h3&gt;
                                Hosting the IronPython engine&lt;/h3&gt;&lt;p&gt;
                                In the RunScript command, we allow the user to specify the location of a Python 
                                script file, which will then be executed by the IronPython engine. For this to 
                                work, we need to initialize an IronPython hosting environment within our command line tool:&lt;/p&gt;&lt;pre name="c#"&gt;// Initialize the IronPython engine.
ScriptEngine engine = Python.CreateEngine();

// Preparing the scope for the script.
ScriptScope scope = engine.CreateScope();
scope.Engine.Runtime.LoadAssembly(typeof(Application).Assembly);
scope.SetVariable("adamApp", app);

// Loading the script file.
ScriptSource source = engine.CreateScriptSourceFromFile(path);
source.Execute(scope);&lt;/pre&gt;&lt;p&gt;
                                First of all, we're creating an instance of the IronPython engine, which is a 
                                factory for all IronPython-related work. As a side-note, the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ScriptEngine&lt;/span&gt; class 
                                is really a part of the DLR, and can be used to host other dynamic languages as 
                                well (such as IronScheme, IronRuby, ...).&lt;/p&gt;&lt;p&gt;
                                Next, we're creating and initializing a &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ScriptScope&lt;/span&gt; for the file we're going to 
                                execute. This involves preparing the assembly references and global variables 
                                that should be available to the script. In this case, we're adding a reference 
                                to the Adam.Core assembly, and pass the logged on &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Application&lt;/span&gt; object as the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;adamApp&lt;/span&gt; variable.&lt;/p&gt;&lt;h3&gt;
                                Your very first ADAM IronPython Script&lt;/h3&gt;&lt;p&gt;
                                At this point we have a command line utility that can be run like this:&lt;/p&gt;&lt;pre name="text"&gt;
 Adam.Scripting.CommandLine.exe -path=C:\Temp\ListUsers.py
  -registration=AdamTest -userName=Administrator
  -password=password&lt;/pre&gt;&lt;p&gt;
                                And now to test this, let's create a Python script that lists all users known to 
                                ADAM. Open your favorite Python editor, and enter the following:&lt;/p&gt;&lt;pre name="python"&gt;import Adam.Core

users = Adam.Core.Management.UserCollection(adamApp)
users.Load(Adam.Core.Search.SearchExpression('*'))

for user in users:
  print user.Name&lt;/pre&gt;&lt;p&gt;
                                Now, if we save the file to ListUsers.py, and run the script using our command 
                                line tool, the output should list all ADAM users. Please note that the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;adamApp&lt;/span&gt;
                                variable is available in the script (as passed through the scope), and the 
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;import Adam.Core&lt;/span&gt; statement is required to make the Adam.Core namespaces 
                                available.&lt;/p&gt;&lt;h3&gt;
                                Wrapping it up&lt;/h3&gt;&lt;p&gt;
                                And now it is up to you to experiment. Go nuts. You could use this little 
                                application to create import scripts (yes, you &lt;b&gt;can&lt;/b&gt; add records, users and 
                                other ADAM objects using script), create maintenance jobs, or even, given some 
                                modifications, execute workflows using script. Feel free to share your 
                                experiences in the comments. Happy coding!&lt;/p&gt;&lt;/div&gt;</description></item><item><title>The impact of User Account Control (UAC) on the Adam command line tools</title><link>http://blogs.adamsoftware.net/Engine/TheimpactofUserAccountControlUAContheAdamcommandlinetools.aspx</link><description>&lt;div&gt;&lt;p&gt;
        By default applications run without any administrative permissions and therefore they cannot make any changes to the system.  For some Adam commands, administrator privileges are required though.  In Windows XP / Windows Server 2003 you could open your command prompt with "Run this program with restricted access" unchecked. In that case and if you do have administrator privileges, you are running the command with administrator privileges, but still as the logged on user.  So these commands have access to your profile information like user folder, etc.
       &lt;/p&gt;&lt;p&gt;
        Windows Vista / Windows Server 2008 / Windows 7 on the other hand uses User Account Control forcing you to select "Run As Administrator" to be able to run a command with administrator privileges.  In that case you are not executing this command with the logged on user, but with the administrator account, thus these commands don't have access to your profile information and have access the administrator's profile information instead.  This can lead to unexpected results regarding Adam tools&lt;/p&gt;&lt;h3&gt;Adam Commandline Tool&lt;/h3&gt;&lt;p&gt;When starting the Adam Commandline Tool, runned as Administrator, you no longer end up in the Adam installation folder, but in the C:\Windows\system32 folder instead.  So before proceeding you should navigate to the installation folder yourself.&lt;/p&gt;&lt;p&gt;&lt;h3&gt;Install Visual Studio Templates&lt;/h3&gt;&lt;p&gt;When running as administrator, the same problem occurs as above: instead of running from the adam installation folder, the C:\Windows\system32 folder is used.  Since this batch command needs the adam installation folder to continue properly, this results in an error. To bypass this you should execute the following steps:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Fire up the command prompt with administrator rights.&lt;/li&gt;&lt;li&gt;Move to the VSTemplates folder within the Adam installation folder.&lt;/li&gt;&lt;li&gt;Start InstallTemplates.bat&lt;/li&gt;&lt;/ol&gt;&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Webinar about the StatefulFormView control</title><link>http://blogs.adamsoftware.net/Webinars/WebinarabouttheStatefulFormViewcontrol.aspx</link><description>&lt;div&gt;&lt;p&gt;This webinar walks you through the new ADAM StatefullFormView web control. Forget the standard ASP.NET FormView control who don’t always match with the highly dynamic nature of ADAM objects. The new StatefullFormView caches data object on the server so that e.g. default values will be calculated on a correct way.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Defensive programming with ADAM</title><link>http://blogs.adamsoftware.net/Engine/DefensiveprogrammingwithADAM.aspx</link><description>&lt;div&gt;&lt;p&gt;
    Defensive programming is a set of techniques for writing more comprehensible, 
    less error-prone code, and gracefully handling unexpected input or rare runtime 
    conditions. Using these techniques along with unit testing will improve code 
    quality as well as reduce bug count considerably.&lt;/p&gt;&lt;p&gt;
                                The ADAM API consistently exposes methods that lend themselves quite well for 
                                defensive programming. In this article, I'm going to delve deeper into the 
                                realms of the ADAM API and use code examples that explain how to defensively 
                                program against ADAM.&lt;/p&gt;&lt;h3&gt;
                                User input validation&lt;/h3&gt;&lt;p&gt;
                                First of all, all user input should be validated and checked. Never leave it to 
                                the user to enter a valid number in a text field where you can enter any 
                                alphanumeric character. Make sure all public methods check their parameters and 
                                make sure all casting/parsing is done safely.&lt;/p&gt;&lt;p&gt;
                                In the Adam.Tools assembly, the ADAM API provides a few helper converter classes 
                                to help with input validation. These classes consistently expose &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;TryParse(...)&lt;/span&gt;
                                methods that can be used to safely convert string values to their respective 
                                value types. These methods also have a &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Parse(...)&lt;/span&gt; counterpart, which will throw 
                                a &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;FormatException&lt;/span&gt; when the parsing fails.&lt;/p&gt;&lt;pre name="c#"&gt;decimal number;

// Non-defensively parsing a decimal from a string.
number = DecimalConverter.Parse("3.14159", CultureInfo.InvariantCulture);

// Defensively parsing a decimal from a string.
if (!DecimalConverter.TryParse("3.14159", CultureInfo.InvariantCulture, out number))
{
  // Gracefully handle invalid values, or revert to default value...
}&lt;/pre&gt;&lt;h3&gt;
                                Defensively logging on to ADAM&lt;/h3&gt;&lt;p&gt;
                                The first example I'm giving is the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;
                                Application.LogOn(...)&lt;/span&gt; method (and its overloads). As you 
                                should know, this is the method that connects the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Application&lt;/span&gt; object to an ADAM 
                                registration. The return type of this method is &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;LogOnStatus&lt;/span&gt;, 
                                and the method will not throw an exception if the registration name, user name 
                                or password is incorrect.&lt;/p&gt;&lt;p&gt;
                                One of the main reasons for this is to prevent the method from exposing 
                                information that might be used by malevolent users to launch an attack on the 
                                system.&lt;/p&gt;&lt;p&gt;
                                You can use the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;LogOnStatus&lt;/span&gt; 
                                enumeration returned by the method defensively to ensure connecting to ADAM 
                                succeeded:&lt;/p&gt;&lt;pre name="c#"&gt;if (app.LogOn(null, userName, password) != LogOnStatus.LoggedOn)
{
  // Handle connection failure gracefully...
}&lt;/pre&gt;&lt;h3&gt;
                                Defensively loading ADAM objects&lt;/h3&gt;&lt;p&gt;
                                As an ADAM developer, you're probably familiar with the 
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Record.Load(...)&lt;/span&gt; method (and its overloads). Suppose we are using 
                                this method to load a record from ADAM, you might write a piece of code like 
                                this:&lt;/p&gt;&lt;pre name="c#"&gt;Record record = new Record(app);
record.Load(id);
// Do some work...&lt;/pre&gt;&lt;p&gt;
                                However, the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Record.Load(Guid)&lt;/span&gt; might throw an &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ItemNotFoundException&lt;/span&gt; when no 
                                record is found with the specified id. Other overloads of the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Record.Load(...)&lt;/span&gt;
                                method might also throw an &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;InvalidNumberOfMatchesException&lt;/span&gt; when more than one matches are found. Therefore, 
                                you might change the code above to this:&lt;/p&gt;&lt;pre name="c#"&gt;Record record = new Record(app);

try
{
  record.Load(id);
  // Do some work...
}
catch (ItemNotFoundException ex)
{
  // Log the exception, show some output to the user, or throw
  // a different exception, ...
}&lt;/pre&gt;&lt;p&gt;
                                In the above code, the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ItemNotFoundException&lt;/span&gt; 
                                can be anticipated, and even avoided. Exceptions are expensive in terms of 
                                resources and additional overhead they incur, and whenever you can, you should 
                                prevent them from being thrown in the first place.&lt;/p&gt;&lt;p&gt;
                                In order to fix this situation, let's take a look at the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;Record.TryLoad(...)&lt;/span&gt; method (again 
                                with its overloads), which can be used to &lt;b&gt;defensively&lt;/b&gt; load a record.&lt;/p&gt;&lt;p&gt;
                                The return type of the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;TryLoad(...)&lt;/span&gt; method is the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;TryLoadResult&lt;/span&gt; enumeration, 
                                which you can use to check wether loading was successful, the item was not found 
                                or multiple items were found matching your query.&lt;/p&gt;&lt;p&gt;
                                With this knowledge, we can now rewrite the example above in a defensive way, 
                                making it more robust and maintainable:&lt;/p&gt;&lt;pre name="c#"&gt;Record record = new Record(app);

if (record.TryLoad(id) != TryLoadResult.Success)
{
  // You could create the record you're expecting here, or query the
  // user for input, or throw a meaningful exception, or ...
}

// Do some work...&lt;/pre&gt;&lt;p&gt;As a side note, when you only need to assert the existence of a 
                                specific record/classification, without necessarily loading it; using the 
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;RecordHelper.Exists(SearchExpression)&lt;/span&gt;/ 
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ClassificationHelper.Exists(SearchExpression)&lt;/span&gt; method is a more performant way to 
                                go.&lt;/p&gt;&lt;h3&gt;
                                Exception handling&lt;/h3&gt;&lt;p&gt;
                                As already briefly mentioned above, exceptions are to be avoided whenever 
                                possible. However, sometimes unexpected things are bound to happen. In that 
                                case, good exception handling comes to the rescue. General guidelines for 
                                exception handling can be found here:                                 &lt;a target='_blank' href="http://msdn.microsoft.com/en-us/library/ms229005.aspx"&gt;
                                http://msdn.microsoft.com/en-us/library/ms229005.aspx&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;
                                The &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ExceptionManager&lt;/span&gt; class, which can be found in the Adam.Tools assembly, adds 
                                some additional functionality to exceptions, and provides factory methods for 
                                creating common exception types.&lt;/p&gt;&lt;p&gt;
                                When developing custom ADAM studios, you can use the 
                                &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;ExceptionManager.SetExceptionData(Exception, boolean)&lt;/span&gt; to set the &lt;span style="color: #2B91AF; font-family: Courier New, Courier"&gt;IsSensitive&lt;/span&gt; 
                                custom property, which is used by the web interface to determine whether or not 
                                to hide the exception message from normal users.&lt;/p&gt;&lt;h3&gt;
                                Putting it all together&lt;/h3&gt;&lt;p&gt;
                                In this post we've shared a few techniques to program defensively in general, 
                                and with the ADAM API specifically. We've shown that user input should not be 
                                trusted until proven trustworthy, that every exception that can be avoided 
                                should be avoided and, when really unexpected circumstances occur, your code must be ready to handle them gracefully.&lt;/p&gt;&lt;p&gt;
                                As much as I hate automobile industry comparisons, I cannot resist adding this 
                                one: exception handling is much like car insurance. Even when you've got good 
                                insurance, having an accident is never a happy experience. Defensive driving 
                                significantly lowers the probability of having an accident, so it is the smart 
                                thing to do. Happy coding!&lt;/p&gt;&lt;/div&gt;</description></item><item><title>UpdateSchema fails</title><link>http://blogs.adamsoftware.net/Engine/UpdateSchemafails.aspx</link><description>&lt;div&gt;&lt;p&gt;
                                Recently, a support ticket came in with the following problem:
                                Executing "Adam.Core.DatabaseManager.exe UpdateSchema" failed with the error message 'You can only specify the READPAST lock
                                in the READ COMMITTED or REPEATABLE READ isolation levels' (see screenshot).
                            &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;img src='http://blogs.adamsoftware.net/Files/9a9e62f2d6df4a0ea55465e7f6ff453b.jpg' /&gt;&lt;p&gt;
                                Cause from this problem? Replication was on enabled on the specific database. Because ADAM does NOT
                                support replication on databases, you should temporary disable replication when executing UpdateSchema.
                            &lt;/p&gt;&lt;/div&gt;</description></item><item><title>Setting up an adam development environment quickly</title><link>http://blogs.adamsoftware.net/Engine/Settingupanadamdevelopmentenvironmentquickly.aspx</link><description>&lt;div&gt;&lt;p&gt;
                                What's the absolutely quickest way to set up a new adam environment? The way that is described in the installation manual is the one that gives
                                you the must control over your setup, but it takes a bit too long to do if you simply
                                want to set up a new dev environment on your laptop.
                            &lt;/p&gt;&lt;p&gt;
                                Here comes the &lt;code&gt;Adam.Core.DatabaseManager SetupLocalDemo&lt;/code&gt; command to
                                the rescue! It creates and activates the database for you, installs the StudioSelector,
                                Config Studio and Asset Studio. All you need to do after running this command, is
                                to install your license manually.&lt;/p&gt;&lt;p&gt;
                                There are a few limitations built into this tool to ensure that you only need to
                                do a minimum amount of configuration.&lt;/p&gt;&lt;p&gt;
                                For example, it will always create a directory under C:\ with the name of the registration.
                                This directory will contain the databases, documents and studios. Everything will
                                be installed locally.&lt;/p&gt;&lt;p&gt;
                                Simply run &lt;code&gt;Adam.Core.DatabaseManager SetupLocalDemo -?&lt;/code&gt; to see a description
                                of all the arguments possible. You'll recognize many of the arguments as the ones
                                that the "normal" installation commands use.&lt;/p&gt;&lt;p&gt;
                                The simplest way to run this command is to use the -ask argument like this &lt;code&gt;Adam.Core.DatabaseManager
                                    SetupLocalDemo -ask&lt;/code&gt;. When it asks for sql accounts, specify the
                                necessary accounts or press enter to use Windows Authentication.&lt;/p&gt;&lt;/div&gt;</description></item><item><title>Create a preview player for Flash (SWF) files</title><link>http://blogs.adamsoftware.net/Web_Development/CreateapreviewplayerforFlashSWFfiles.aspx</link><description>&lt;div&gt;&lt;p&gt;
    Adobe Flash movies are a popular file format. The ADAM engine has no issues in 
    storing those file formats, but there is no out-of-the-box preview 
    player. However, creating such a preview player is pretty straight forward.&lt;/p&gt;&lt;h3&gt;The basics&lt;/h3&gt;&lt;p&gt;
                                To create a custom preview player, you should subclass the abstract class
                                &lt;span style="COLOR: #2b91af; font-family: Courier New, Courier"&gt;FileVersionView&lt;/span&gt;..This 
                                class is the base class for all preview players in ADAM.&lt;/p&gt;&lt;p&gt;
                                To create the HTML that provides a preview of the Flash file, you can add
                                &lt;span lang="IT" style="color:#2B91AF; font-family: Courier New, Courier"&gt;HtmlGenericControl&lt;/span&gt; controls 
                                as a child controls and set the necessary properties to it in order to output 
                                standard HTML for embedding a Flash file:&lt;/p&gt;&lt;p&gt;
                                To determine the URL of the Flash file, you need 
                                access to the &lt;span style="COLOR: #2b91af; font-family: Courier New, Courier"&gt;
                                FileVersion&lt;/span&gt; being previewed. This object is available in the
                                &lt;span style="font-family: Courier New, Courier"&gt;DataItem&lt;/span&gt; 
                                property of the
                                &lt;span style="COLOR: #2b91af; font-family: Courier New, Courier"&gt;FileVersionView&lt;/span&gt; 
                                control. The &lt;span style="COLOR: #2b91af; font-family: Courier New, Courier"&gt;
                                FileVersion&lt;/span&gt; object has a property
                                &lt;span style="font-family: Courier New, Courier"&gt;Path&lt;/span&gt; which contains the 
                                local (or network) path of the actual file. To convert this path into an URL, 
                                you can use a
                                &lt;span style="COLOR: #2b91af; font-family: Courier New, Courier"&gt;ServerFileUri&lt;/span&gt; 
                                object to create a secure URL from it.&lt;/p&gt;&lt;pre name="C#"&gt;protected override void CreateChildControls()
{
  FileVersion version = this.DataItem as FileVersion;
  if(version != null &amp;amp;&amp;amp; string.IsNullOrEmpty(version.Path) == false)
  {
    string path = version.Path;
    
    ServerFileUri uri = new ServerFileUri(path, "application/x-shockwave-flash");
    string url = uri.ToString();
  
    HtmlGenericControl control = new HtmlGenericControl("object");
  
    HtmlGenericControl param = new HtmlGenericControl("param");
    param.Attributes.Add("name", "movie");
    param.Attributes.Add("value", url);
    control.Controls.Add(param);
  
    HtmlGenericControl embed = new HtmlGenericControl("embed");
    embed.Attributes.Add("src", url);
    embed.Attributes.Add("type", "application/x-shockwave-flash");
    control.Controls.Add(embed);
  
    this.Controls.Add(control);
  }
  else
  {
    this.Controls.Add(new LiteralControl("No FileVersion available or the file could not be found."));
  }
}&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: the code above is a stripped down version and only contains the 
                                minimal required HTML properties to embeds a Flash file into an HTML page. When using the code in a production 
                                environment, you should complete the code to provide all properties. To get more 
                                information about which properties are available, there are dozens of articles on the web. We suggest following articles:&lt;br /&gt;&lt;br /&gt;&lt;a target='_blank' href="http://kb2.adobe.com/cps/415/tn_4150.html"&gt;Macromedia Flash OBJECT and EMBED tag syntax&lt;/a&gt;&lt;br /&gt;&lt;a target='_blank' href="http://kb2.adobe.com/cps/127/tn_12701.html"&gt;Flash OBJECT and EMBED tag attributes&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Using the preview player in ADAM&lt;/h3&gt;&lt;p&gt;A preview player is a provider. Therefore, once the code of the preview player is 
                                completed, you must register the containing assembly in ADAM and add the preview 
                                player in the '&lt;b&gt;Preview Render Web Control Providers&lt;/b&gt;' setting. More information on registering and configuring a provider in ADAM can be found 
                                in the topic '&lt;b&gt;Creating a custom provider&lt;/b&gt;' of the ADAM development guide, &lt;/p&gt;&lt;p&gt;Once this is done, open up the Config Studio, go to 'File Type Management', 
                                search for the SWF file type and add the Flash preview player to the list of 
                                preview players.&lt;/p&gt;&lt;h3&gt;Configuring the preview player&lt;/h3&gt;&lt;p&gt;
                                The abstract class
                                &lt;span style="COLOR: #2b91af; font-family: Courier New, Courier"&gt;FileVersionView&lt;/span&gt; 
                                has an additional virtual method:
                                &lt;span style="font-family: Courier New, Courier"&gt;ApplyProviderSettings&lt;/span&gt;. 
                                This method has one parameter (settings) which contains the additional XML attributes 
                                set on the &amp;lt;add /&amp;gt; tag of the corresponding preview player configured in the  
                                '&lt;b&gt;Preview Render Web Control Providers&lt;/b&gt;' setting. You can use this 
                                method to configure your preview player.&lt;/p&gt;&lt;p&gt;
                                By example, you could add configuration options to the preview player to control its width and height. 
                                To achieve this, add these properties in the setting. E.g.:&lt;/p&gt;&lt;pre name="xml"&gt;&amp;lt;add name="FlashPreviewPlayer" type="Sample.FlashPreviewPlayer, Sample" width="600px" height="400px" /&amp;gt;&lt;/pre&gt;&lt;p&gt;
                                You can now read these options in the
                                &lt;span style="font-family: Courier New, Courier"&gt;ApplyProviderSettings&lt;/span&gt; 
                                method:&lt;/p&gt;&lt;pre name="C#"&gt;private Unit _width = Unit.Empty;
private Unit _height = Unit.Empty;

public override void ApplyProviderSettings(IDictionary&amp;lt;string, string&amp;gt; settings)
{
  if (settings != null)
  {
    if (settings.ContainsKey("width") == true)
    {
      string width = settings["width"];
      if (string.IsNullOrEmpty(width) == false)
      {
        try
        {
          _width = Unit.Parse(width);
        }
        catch
        {
          _width = Unit.Empty;
        }
      }
    }

    if (settings.ContainsKey("height") == true)
    {
      string height = settings["height"];
      if (string.IsNullOrEmpty(height) == false)
      {
        try
        {
          _height = Unit.Parse(height);
        }
        catch
        {
          _height = Unit.Empty;
        }
      }
    }
  }
  base.ApplyProviderSettings(settings);
}&lt;/pre&gt;&lt;/div&gt;</description></item></channel></rss>