Blog

Metadata Exchange Using SvcUtil: A Cautionary Tale

March 21, 2008 by Dave Marini

One of the projects that I’ve been working on the past week is a conversion project that involves a web site that has a tightly coupled business logic layer. The goal of the project is to re-engineer the site so that the business logic and corresponding data access tiers are decoupled and distributed as services. For us the obvious choice for this is using the new Windows Communication Foundation framework to accomplish the task. After some heavy reading and a lot of trial and error, we’re very close to having this done and I’m proud of the outcome given the short span of the project (~ 5 weeks). We probably could have finished in 4 weeks if it weren’t for a seemingly innocuous problem with proxy generation that ended up costing me 3 day’s time to solve. If you’re using a tcp based Metadata Exchange binding and having trouble generating a service proxy with SvcUtil, read on!

The Error Rears It’s Ugly Head

This is the error that I was getting when trying to have SvcUtil generate my proxy class for a particular service of mine:

WS-Metadata Exchange Error URI: net.tcp://localhost:8888/MyServices/MyBigFatGreekService

Metadata contains a reference that cannot be resolved: ‘net.tcp://localhost:8888/MyServices/MyBigFatGreekService’.

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was ‘00:04:59.9843748’.

An existing connection was forcibly closed by the remote host

Oh how silly of me! As you can see, SvcUtil was built to tell you exactly what’s going on, NOT!! this error is terribly vague because it leads you to believe that you have a network issue going on, which hey, you might. But in my case, I had 15 services hosted on the SAME address and I was able to generate 14/15 with no problem. Now, let’s take a look at what kind of problems cause this error to appear:

Common Beginner Mistakes

I’m going to take a small digression here to talk about some common mistakes that take 30 seconds to fix that could cause this error to occur. Most people who get errors from SvcUtil are missing something in the configuration of their services that is causing the problem. The biggest two culprits I’ve seen:

1.) Make sure you enable Metadata Exchange. you need to do this explicitly for each service and it’s commonly missed. This is done with a Service Behavior Configuration Section, like below. The key piece here is the serviceMetadata element:

<behaviors>
  <serviceBehaviors>
    <behavior name="MetaDataBehavior">
      <serviceMetadata />
    </behavior>
  </serviceBehaviors>
</behaviors>

If you’re using a Tcp based binding, just making sure it’s there as above enables the exchange. For using an Http based binding, specify either HttpGetEnabled or HttpsGetEnabled, as in the below example:

<serviceMetadata httpGetEnabled="true" />

2.) Make sure that the security settings on your binding match what you want to achieve. If the discovery of your metadata is to be public, explicitly set your security to “None” so that you are sure not to encounter authentication issues. If not, make sure you configure the security correctly. In my example, we’re not securing the metadata endpoint.

<services>
   <service name="Service.MyService" behaviorConfiguration="MyServiceBehavior">
      <host>
        <baseAddresses>
          <add baseAddress = "net.tcp://localhost:8888/MyService" />
        </baseAddresses>
      </host>
      <endpoint address="" binding="netTcpBinding" contract="Service.IMyService"
           bindingConfiguration="myNetTcp" />
      <endpoint address="mex" binding="netTcpBinding" contract="IMetadataExchange"
           bindingConfiguration="mexTcp" />
   </service>
</services>
<bindings>
  <netTcpBinding>
     <binding name="myNetTcp" portSharingEnabled="true">
     </binding>
     <binding name="mexTcp" portSharingEnabled="true">
        <security mode="None" />
     </binding>
     </netTcpBinding>
</bindings>

In this case I’m using port sharing because we want all of our services to share the same Tcp port regardless of how many we have in the future. If you have port sharing enabled for one service, do yourself a favor and keep it consistent. For more detailed information about port sharing, read this blog post by Nicholas Allen to get a true understanding of why you need this.

Sleuthing About

None of my other services were having proxy generation problems, so I knew that I had the services set up correctly. I even double checked to make sure I didn’t have any syntax errors on that one service that could cause me problems. After this, I began seeing some strange things. Turns out, switching to an Http based binding like mexHttpBinding fixed the problem. But I didn’t want http, I wanted Tcp, so I pressed on. What could be the difference between the two bindings that could cause such a problem?

It turns out that the service I had trouble with was the largest of all the services I was trying to generate (~ 30 methods). I found that by commenting out a few of the methods in the service contract, the Tcp Metadata exchange WORKED! It also didn’t matter which methods were commented, which ruled out problems like an incorrectly serialized type or a duplicate operation name. Now, in Juval Lowy’s book on WCF, he states that service contracts should have no more than 5 – 7 methods if they are properly factored and this makes sense, but I didn’t have time to factor this class straight away due to time constraints. For now, the class has to stay big. There was no documentation stating that service contracts had a maximum size restriction, so again, WHY THIS ERROR?

I thought that maybe I needed to up the default throttling controls on the metadata exchange binding for the services, so I increased the maxReceivedMessageSize and all of the limits in the readerQuotas element, but received the same error. It should be noted here that the mexTcpBinding is a very specific type of netTcpBinding that doesn’t allow you to tweak these settings. So, just use netTcpBinding, there’s no rule against it.

Send In The Marines!

Hey everyone, SvcUtil has a limit on how much metadata it can receive! Did you know that? If you did, congratulations, because this is not well documented at all! Especially disconcerting is the apparent inconsistency with which this limit is imposed, which was the reason that my mexHttpBinding worked without a hitch. How do we tell SvcUtil to eat more fiber? It turns out I was on the right track with increasing the throttling controls on the binding, but not in the right place. It turns out that I needed to create an app.config for SvcUtil itself, place it in the directory with SvcUtil.exe and THEN run it. Here’s the config that finally made it work:

<configuration>
  <system.serviceModel>
     <client>
        <endpoint name="net.tcp" binding="netTcpBinding" bindingConfiguration="myTcp"
          contract="IMetadataExchange" />
     </client>
     <bindings>
        <netTcpBinding>
            <binding name="myTcp" maxBufferPoolSize="60000000" maxBufferSize="60000000"
                 maxReceivedMessageSize="60000000" >
              <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                 maxArrayLength="2147483647" maxBytesPerRead="2147483647"
                 maxNameTableCharCount="2147483647" />
            </binding>
        </netTcpBinding>
     </bindings>
  </system.serviceModel>
</configuration>

So there it is. Make sure that the binding configuration that you use in the svcutil app.config matches the one you’re using in the configuration file for your service host. If you don’t, you will be getting a different error when you run SvcUtil, explaining that you have mismatched service settings and therefore the action is invalid.

Roll Credits

I can’t say I figured this problem out on my own. In fact, when I was so frustrated that I ripped all my hair out, I finally posted the MSDN Forums to see if ANYONE had the same problem as me. Thanks to the moderators there, I was pointed in the right direction which solved my problem. You can see my post here.

In my next post, I’ll be discussing why Visual Studio’s Service Reference Proxy Generation Tool isn’t adequate for those who are producing and consuming their own services and want to share multiple collection data types between the service and client, and how to use SvcUtil to overcome that inadequacy.

Using Exchange Web Services 2007: The Basics

March 20, 2008 by Dave Marini

Exchange Web Services (EWS) for Microsoft Exchange 2007 provides a quick an easy way to interface with Exchange data from anywhere without having to interface with ugly COM interop objects if you’re living in a managed world like C#. Today I was curious at how to get calendar appointments from Exchange into a readable format that I can use in another application, perhaps one that synchronizes appointments from exchange with those from other calendaring applications like Google’s calendaring feature. Also, I found the documentation about EWS hard to find and not very helpful, so this post will serve as a single source of good documentation for those who are getting started with EWS. All of the examples I give will assume you have a basic familiarity with the available operations that the web service offers you. Here are some great links to get you up to speed:

MSDN Getting Started With EWS: A 3 part intro to Exchange 2007 Web Services. EWS Operations: A list of the operations that can be performed on the EWS. FindItem Example in C#: An example of querying calendar items from EWS. Glen Scales’ Blog: This guy knows Exchange inside and out.

The Exchange Web Services module works off the concept of creating a soap message to send to Exchange that will tell the server what you’re looking for and then give you back a soap response. The only thing I find to be problematic in the EWS architecture is that the type objects that were used to comprise the API that C# developers will use to create these requests is almost a literal translation of the corresponding XML elements and attributes, which has a tendency of making the code bloated and a bit unintuitive. Regardless, anything is better than using the old ways of communicating with Exchange, so let’s continue.

The first step in communicating with Exchange is to obtain a proxy. This is an instance of the ExchangeServicesBinding class. With Visual Studio 2005, you can generate this proxy object by adding a web reference pointed at http:///EWS/Services.wsdl. As a user of Visual Studio 2008, I thought that adding a service reference would accomplish the same thing, but it turned out I was wrong. If you attempt to use a service reference to generate these types, you won’t get the proxy object back to instantiate. So, the way to do this is as follows. Right click on your project and choose “Add Service Reference”. Then, when the Add Service Reference Dialog comes up, choose “Advanced”. This will present you with the Service Configuration Dialog screen. From here, there will be an option on the bottom left to “Add Web Reference” and this will bring you to the screen that will ensure that you generate the appropriate proxy objects from the WSDL. See Figure 1 for some screenshots of this.

Figure 1. Adding a web reference to the exchange services. Figure 1. Adding a web reference to the exchange services.

In the case you don’t want to go through using a web reference, you can use the wsdl.exe tool to generate the classes that you can then reference in your project. For more information about doing this, go here. Once you have the proxy, you will want to connect to it in order to post messages to it. The way to do this in C# is quite straightforward:

ExchangeServiceBinding esb = new ExchangeServiceBinding();
esb.Url = "http://<YourExchangeServer>/EWS/Exchange.asmx";
esb.Credentials = new NetworkCredential("username", "password", "domain");

Once authenticated, you will be connected to Exchange as the user in the credentials supplied. You can also use CredentialCache.DefaultCredentials if you are making a WinForms application and want to use the credentials of the logged in user when connecting to the exchange server. One thing to keep in mind when querying or creating items in exchange from this point is that all of these operations, with the exception of the free/busy time query, work off a single mailbox at a time, and this mailbox is initially that of the connected user. The solution if you need to see items from other users is to impersonate the target user(s) and perform the queries. There are 2 ways to accomplish this, one uses delegates and the other explicit impersonation.

Most operations in the Exchange Services proxy take objects that require you to specify which folders you will be working on. For example, if I wanted to look for messages that contain the subject “happy holidays”, I would probably want to look in the inbox, but also in the deleted items folder since I could have deleted the message I’m looking for. There is a property on the folder type object called Mailbox, and this allows you to specify another person’s mailbox when specifying the folder. So, assume I am connected to the Exchange Server as John Smith, but I need to find all appointments in Anne Dugger’s calendar folder. Here would be the code to use delegate access to accomplish this:

FindItemType fit = new FindItemType();
fit.ItemShape = new ItemResponseShapeType { BaseShape = DefaultShapeNamesType.Default };
fit.ParentFolderIds = new DistinguishedFolderIdType[]
{
    new DistinguishedFolderIdType
    {
        Mailbox = new EmailAddressType{ EmailAddress="adugger@contoso.com"},
        Id = DistinguishedFolderIdNameType.calendar
    }
};
fit.Traversal = ItemQueryTraversalType.Shallow;

FindItemResponseType firt = esb.FindItem(fit);

In the above example, the FindItemType is the class that we use to tell exchange to find items in a particular user’s folder. Here we’re specifying that we want to look in the Calendar folder of the user that has an email address of adugger@contoso.com. In order to use delegate impersonation to query Exchange, Anne Dugger would have to grant the connected user access to her calendar folder. This can be done in Outlook by going to tools->options and clicking on the Delegates tab. This tab is only visible if outlook is connected to an exchange server. This method is useful if the functionality you want to incorporate is opt-in as users can grant a particular system account delegate access to their mailbox so that automated tasks can be performed.

The second way to accomplish querying another user’s mailbox folders is explicit impersonation. This method is useful for scenarios where an Exchange Administrator wants to force one or more mailboxes to be maintainable by a system account. The setup for this scenario is a bit more complex and is covered in detail here. Once configured, we can programmatically invoke impersonation in C# through the following means. Using the same example as above, if John Smith’s account had been granted impersonation rights on Anne Dugger’s mailboxes, and I wanted to find all appointments in Anne Dugger’s Calendar folder, here is the C# code we would use:

ExchangeImpersonationType imp = new ExchangeImpersonationType();
imp.ConnectingSID = new ConnectingSIDType { PrimarySmtpAddress = "adugger@contoso.com" };
esb.ExchangeImpersonation = imp;

FindItemType fit = new FindItemType();
fit.ItemShape = new ItemResponseShapeType { BaseShape = DefaultShapeNamesType.Default };
fit.ParentFolderIds = new DistinguishedFolderIdType[]
{
     new DistinguishedFolderIdType{ Id = DistinguishedFolderIdNameType.calendar }
};
fit.Traversal = ItemQueryTraversalType.Shallow;

FindItemResponseType firt = esb.FindItem(fit);

As you can see from the code above, there is no longer a need to explicitly specify the mailbox when indicating which folders we will be searching. Instead, we tell the proxy instance that we are impersonating Anne Dugger’s account by specifying her email address in the ConnectingSID property of an ExchangeImpersonationType that we bind to the proxy instance. You can also use the principal name here if you desire, but note that this is may be different than the email address for the target user.

No matter which way you go about getting a user’s information, since you can only query one user at a time, you will probably want to employ your favorite threading techniques so that you can get multiple results back in a relatively short amount of time.

Let’s talk a bit about shapes. At least for the FindItem (and perhaps GetItem) service operations, there is a property called ItemShape. This property essentially defines what we expect to come back in the response message from Exchange. In the above example, We’re telling exchange to bring back the default properties for calendar items, but what if we wanted to include a couple of non standard properties in the result? Well, we can specify these in the AdditionalProperties Property of the ItemResponseShapeType class, as in the below example:

fit.ItemShape = new ItemResponseShapeType
{
   BaseShape = DefaultShapeNamesType.Default,
   AdditionalProperties = new PathToUnindexedFieldType[]
   {
      new PathToUnindexedFieldType{ FieldURI = UnindexedFieldURIType.calendarIsMeeting },
      new PathToExceptionFieldType{ FieldURI = UnindexedFieldURIType.calendarIsRecurring }
   }
};

The code above specifies that we want 2 custom properties to be returned, one indicating whether the appointment is a meeting and the other to indicate whether the appointment is recurring or not. We can then use these properties in the response should we have any logic for whether or not to process recurring meetings differently than other types of meeting.

Just as an aside, when searching for items in Exchange, you can specify grouping and paging options as well as restriction and sorting options. I won’t go into details about all of these, suffice it to say that the MSDN example in the link above shows all of these aspects of the FindItem operation. 

So that wraps up the basics of how to connect to and impersonate with Exchange 2007 web services. I’ve only really played around with it for an hour, and it’s pretty obvious that I only really used the FindItem operation since I only needed basic properties to be returned about the appointments I was searching for. For more details about the appointments (like the invitees, etc) I would have to call GetItem on each item that was returned from FindItem, passing the Item’s id in as the reference. The API has the ability to do much more than search, I can programmatically create appointments, messages and contacts as well, but the underlying infrastructure is the same as it is for finding an item, so getting an understanding of it for the FindItem operation will translate to other operations as well.

Extending the GridView to Work With the New DataPager Control

March 19, 2008 by Dave Marini

Recently I read an article by Scott Mitchell about the new ListView and DataPager controls that are included in the .NET Framework version 3.5. This got me curious as to how to adapt other well known databound controls like the GridView so that they can work together with the DataPager control. After some light reading and rather heavy reflecting over the guts of the GridView control, I had a gameplan and was ready to go. Extending a databound control to allow communication with the DataPager control isn’t too difficult to do, but it does assume that you have an understanding of how the data is bound to the control. But why bother to do this when the GridView has its own paging control built in? Well, for one thing, being able to decouple the pager from the grid allows us to do some pretty cool things. One thing I can think of is having the GridView in the left bar and the paging control someplace in the main window. Also, we can have a grid with two pagers. Each keeps track of the current page consistently, regardless of which one we use to page through our data. Finally, the templating controls of the pager are very powerful compared to those of the GridView by itself.

Let’s start with how a databound control can communicate with the DataPager. The DataPager control can be hooked up to any control that implements the IPageableItemContainer interface located in the System.Web.Extensions assembly. Here’s a quick shot of what the interface looks like courtesy of .NET Reflector:

public interface IPageableItemContainer
{
    //Events
    event EventHandler<PageEventArgs> TotalRowCountAvailable;

    // Methods
    void SetPageProperties(int startRowIndex, int maximumRows, bool databind);

    // Properties
    int MaximumRows { get; }
    int StartRowIndex { get; }
}

The MaximumRows and StartRowIndex properties of the interface are simply there to create a way for your databound control to determine the data window to display. This effectively defines the basis for what you will consider to be a “Page” of data. The SetPageProperties method is important in the interaction with the DataPager because this is the method in your control that the DataPager will call whenever you click on any of the DataPagerField controls (The Next or Previous Buttons, for example). Finally, the interface defines an event called TotalRowCountAvailable. This event tells the DataPager how many records are in the data being bound to your control. This is obviously important as the DataPager uses the total row count to determine how man page buttons to render or whether to disable the next or previous buttons so that you don’t go to a nonexistent page index.

So let’s begin extending the GridView with the hooks for the DataPager. Thinking about the IPageableItemContainer interface in terms of the GridView, we realize that MaximumRows is equivalent to the existing PageSize property, and StartRowIndex can be calculated from the existing PageSize and PageIndex properties. We also prepare the event by declaring it and creating a corresponding event invoker. Since I want my new Paging capability to be the default for this grid, I force the Pager to hide itself every page load. You can add a toggle to this behavior should you so desire. Finally, we stub out the SetPageProperties method, but we’ll leave it blank for now as we’ll revisit it shortly. So far our new GridView looks like this:

public class PageableGridView : GridView, IPageableItemContainer
{
     public PageableGridView() : base()
     {
          PagerSettings.Visible = false;
     }

     public event EventHandler<PageEventArgs> TotalRowCountAvailable;

     public int MaximumRows
     {
          get{ return this.PageSize; }
     }

     public int StartRowIndex
     {
          get{ return (this.PageSize * this.PageIndex); }
     }

     protected virtual void OnTotalRowCountAvailable(PageEventArgs e)
     {
          if (TotalRowCountAvailable != null)
                TotalRowCountAvailable(this, e);
     }

     protected virtual void SetPageProperties(int startRowIndex, int maximumRows, bool dataBind) { }
}

The good news is that we’re more than half way there. Now is where things get a bit more complex. We still need a way to set the control with the page size and starting row values based on what the DataPager says we need to display once the user clicks on one of its buttons. This is where the SetPageProperties method comes into play. Here is a basic implementation that gets the job done:

protected virtual void SetPageProperties(int startRowIndex, int maximumRows, bool dataBind)
{
    if (databind)
    {
        PageSize = maximumRows;

        int newPageIndex = (startRowIndex / PageSize);

        if (PageIndex != newPageIndex)
        {
           OnPageIndexChanging(new GridViewPageEventArgs(newPageIndex));

           PageIndex = newPageIndex;

           OnPageIndexChanged(EventArgs.Empty);
        }
    }

    RequiresDataBinding = databind;
}

When the DataPager sends the grid its paging information, the grid needs to set any appropriate params on itself to prepare to bind to the right window of data. The 2 properties that the grid is already equipped to do this with are the PageSize and PageIndex properties. These properties can be calculated from the information sent into the method, so we set them. Of course, if the Page is being changed, we should probably fire the OnPageIndexChanging event. This means if you aren’t binding to a datasource, you’ll still need to make sure to handle this event. Finally, we instruct the grid to rebind itself should the DataPager be in the process of binding to data. This is a basic implementation so you’ll want to do any data integrity checks here as well, for example checking to ensure that the new PageIndex and StartRowIndex values are in the valid range.

There’s only one thing left to do to complete our integration of the GridView to the DataPager. For the DataPager to render the appropriate number of page buttons, or for it to know when to disable the next or previous page buttons on the pager, it needs to know how many total rows there are. This, coupled with the Page Size, which is specified declaratively on the DataPager itself, help it determine the number of pages that the data source contains. The problem is, this information isn’t known to the pager. It is known to the GridView however, and we need to get it from there and pass it on to the DataPager. But when can we be sure that the GridView has this data? The GridView control inherits from CompositeDataboundControl. This type contains a special variant of the CreateChildControls method that also takes in a property indicating whether the control is being bound to data or simply re-rendered. A little reflecting shows that the GridView uses this method to bind to its data source. Knowing this, it appears this is the place we will want to inject our trigger for the TotalRowCountAvailable event to be raised. This gets a little complicated because we need to handle the case where we’re binding to a datasource manually or using a DataSource Control like ObjectDataSource or SqlDataSource, which have the total row count specified within them. A couple of helper methods are required to ensure we get the right value:

//Gets row count from SqlDataSource and the like...
private int _GetTotalRowsFromDataSourceObject(IEnumerable dataSource)
{
    DataSourceView view = this.GetData(); if (AllowPaging && view.CanPage && view.CanRetrieveTotalRowCount)
        return base.SelectArguments.TotalRowCount;
    else
        return (PageIndex * PageSize) + _GetSourceCount(dataSource);
}

//Gets the row count from a manually bound source or from a source in viewstate
private int _GetSourceCount(IEnumerable dataSource)
{
    ICollection source = dataSource as ICollection;

    return source != null ?
         source.Count :
         (from x in dataSource.OfType<object>() select 1).Sum();
}

The _GetTotalRowsFromDataSourceObject method retrieves the total number of records from the DataSource object, if it’s available. This depends on a couple of things, such as whether the EnablePaging property was set on the DataSource Control and whether the Object has completed the query operation. Worst case, we return a single page of data and be done with it. The _GetSourceCount method is used for two particular occasions. First, it’s how you get the row count in the event that you bind the grid’s DataSource property manually and then call DataBind(). Secondly, this method will also prove useful when the grid is rebinding after a postback to data that is stored in the viewstate. In both cases, we use a little LINQ to extract the total number of resulting data items (or rows in the case of viewstate) in the datasource. Now let’s see how we use these methods to tie it all together:

protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
   {
       int baseResult = base.CreateChildControls(dataSource, dataBinding);

       if (dataSource != null)
       {
           int dataSourceCount = (IsBoundUsingDataSourceID && dataBinding) ?
               _GetTotalRowsFromDataSource(dataSource) :
               _GetSourceCount(dataSource);

           OnTotalRowCountAvailable(new PageEventArgs(StartRowIndex, MaximumRows, dataSourceCount));
       }

       return baseResult;
   }

The base control’s CreateChildControls method is called first, since the grid uses it to actually do the databinding. if there isn’t any data to bind to, there will not be a reason to notify the pager, so we check to make sure we have data, then determine the number of rows in the source through the above mentioned process. Finally, we fire off the event with the derived data and then we return the original result so as not to affect any other operations that may rely on it. We now have a GridView that can be coupled with the new DataPager control. Here’s a sample of markup that we would use to use these controls together on a page:

<asp:DataPager ID="DataPager1" runat="server" PageSize="2" PagedControlID="grid2">
    <Fields>
        <asp:NextPreviousPagerField />
    </Fields>
</asp:DataPager>
<custom:pageablegridview id="grid2" runat="server" autogeneratecolumns="true" allowpaging="true"
        onpageindexchanging="grid2_PageIndexChanging" />

Notice that I don’t have to specify the PageSize property of the GridView because the PageSize property on the DataPager will be in control of this value. To ensure this, we could shadow the PageSize property on the grid, but this will suffice for now. So that’s really all there is to it. For newly created server controls that are bound to data, making these inroads to allow your control to work with the DataPager is pretty simple. For the existing controls, like the GridView, it’s just a matter of knowing how the binding takes place and then injecting the functionality someplace where you know the needed values will exist.

Modal UpdateProgress for UpdatePanel – Revisited

March 13, 2008 by Damien White

Back in September 2007, I posted an article which described a way to “disable” an UpdatePanel (or more specifically an entire page) by using a modal UpdateProgress control. This solution would allow developers to stop users from clicking on other items on the page while the UpdatePanel is processing. The premise behind this was taking a DIV and stretching it over the top of the page using CSS, and having a message (e.g. “Please Wait”) on top of that. This is achieved by using some simple CSS. If you want to read the original article, you can view it here.

Since that time, this continues to be one of the most popular posts and many people have wanted to use this solution with IE 6. Well, the original version showed the message, but not the “blanket” modal DIV in IE 6. There were also issues with scrollbars where the “blanket” would stay at the top and users could still see the bottom of the page if they scrolled. I’m happy to say that there is a solution to these issues… The following techniques were tested in IE 7 (7.0.6001.18000), Firefox 2.0.0.12, and IE 6 (6.0.2900.2180) in Standards Mode.

First, the code is the same, but instead of going back to the old post, here it is again:

<asp:updateprogress associatedupdatepanelid="UPDATEPANELID"
    id="updateProgress" runat="server">
    <progresstemplate>
        <div id="progressBackgroundFilter"></div>
        <div id="processMessage"> Loading...<br /><br />
             <img alt="Loading" src="images/ajax-loader.gif" />
        </div>
    </progresstemplate>
</asp:updateprogress>

Pretty simple code… basically the only “custom code” are the two DIVs. The first, progressBackgroundFilter is used to blank out the page. The second, progressMessage, is the message to display. In this case, it’s just text and an animated gif.

Solution for IE 7 and Firefox

Now for the styles, this is where we will fix the problems in the old solution. First, let’s start with IE 7 and Firefox. The old solution worked well, however it had a problem with scrollbars. To fix this in modern browsers, we will use the CSS property position: fixed.

#progressBackgroundFilter {
    position:fixed;
    top:0px;
    bottom:0px;
    left:0px;
    right:0px;
    overflow:hidden;
    padding:;
    margin:;
    background-color:#000;
    filter:alpha(opacity=50);
    opacity:0.5;
    z-index:1000;
}
#processMessage {
    position:fixed;
    top:30%;
    left:43%;
    padding:10px;
    width:14%;
    z-index:1001;
    background-color:#fff;
    border:solid 1px #000;
}

The only difference in this code is the position (which I have made bold and underlined in the snippets above). We are utilizing position: fixed, which means to pin the elements to the viewport regardless of the scroll position. Previously, we used position: absolute; which caused our “blanket” to position itself relative to the original viewport, but not the entire page, so the problem came about when there are scrollbars.

Fun (not) with IE 6

Now, for IE 6 (Note, it may work in other versions of IE, but I haven’t tested it). The problem with the initial solution was that IE 6 ignored the right and bottom CSS styles. All we could see was the processMessage DIV, but not the background filter. A first attempt at fixing this was to add a height and width to the progressBackgroundFilter for anything below IE 7. A width of 100% stretched it horizontally, but a height of 100% did nothing. Obviously a fixed height, e.g. 200px worked, but not much use when we don’t know the height. After a bit of research, I came across an article titled “Conflicting Absolute Positions” by Rob Swan, which greatly helped in coming up with a solution. IE 5 and 6 offer an alternative to just percents and fixed sizes, it allows us to dynamically set styles by using an expression. An expression is just a JavaScript snippet for a given value. Have a look at “Conflicting Absolute Positions” for more information on IE’s CSS expressions. Without further ado, here’s the complete CSS for IE 6:

body { height: 100%; }

#progressBackgroundFilter
{
    position:absolute;
    height: expression(document.body.clientHeight + "px");
    width: expression(document.body.clientWidth + "px");
}
#processMessage {
    position:absolute;
    top: expression((document.body.clientHeight * .30) + "px")
}

First, as mentioned, IE 6 doesn’t understand position: fixed; and reverts back to position: static, so the first step is to set position to absolute only for IE 6 and below in both the #processBackgroundFilter and #processMessage. The rest of the styles utilize expressions, with the exception of body style above, which I will discuss in a bit. The premise behind the expressions is to calculate the full page dimensions and position the background filter. For the message, I wanted to appear in the viewport 30% from the top of the screen like the IE 7 / Firefox counterpart, so that is why there is a calculation for the top. The thing that doesn’t happen with the message that does occur in IE7 and Firefox is that the message “follows” the user if they scroll. You could do capture the scroll event and move the message, but I feel this is overkill, plus it complicates the simplicity of the “Modal UpdateProgress” solution.

One thing to note here is that the expressions are using JavaScript, if a user has JavaScript disabled, the CSS expressions do not work. However, if they don’t have JavaScript enabled, the expressions are the least of your problems. Their overall AJAX experience will be non-existent. Just note this if you use expressions in other types of applications.

Anyway, in trying to getting this to work I encountered some issues with the JavaScript calculations and getting everything to work in sync. One thing to note here is that IE 6 is overly sensitive to DOCTYPE declarations making it difficult when dealing with box models (e.g. quirks vs. standards). On my pages, I use the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

For determining if IE 6 will be rendered in quirks mode vs. standards mode, I typically refer to the Wikipedia’s Quirks Mode page and the document type comparison that they have. I like to work in standards mode since that is what modern browsers use, but the DOCTYPE for XHTML 1.1 isn’t in the list, but XHTML 1.0 is, and further down the page it does list XHTML 1.1 as standards rendering. So, I went over to QuirksMode.com and referenced the article titled “document.body and doctype switching,” which was very helpful.

Originally, I simply had the expressions for just the two elements and this was the result when the browser was maximized:

Figure 1 IE6 Without Height

Figure 1 – IE 6 without body { height: 100%; }

Notice the issue with the bottom of the page in Figure 1? The progressBackgroundFilter doesn’t cover everything. I tried all sorts of stuff, then using the IE Developer Toolbar, I saw what was happening. since the page I was on was short, the body element only expanded just to the bottom of the content. I have no idea though why it’s still just a tad shorter than the body as shown in Figure 1 (see the bit of darker blue that is peeking out?). I believe it has to do with body padding and or margins, but my investigation on the topic ended there; I just chalked it up to IE 6 baffling me sometimes. Anyway, I thought to add the height: 100%; style to the BODY element. This turned out much better as shown in Figure 2 below.

Figure 2 IE6 With Height

Figure 2 – IE 6 with body { height: 100%; }

Much better, but your solution to the IE 6 woes may differ to mine. My basic styles on this site are as follows:

body { margin:0; padding:0;}
#container { margin:10px auto; }

You can see the body has no margin or padding (this would push out the body in IE 6 because it would be 100% + the margin and padding causing the page to scroll when it didn’t have to). I achieve the margin on the top and bottom by assigning these to my outer container which is just a DIV where all the content lies. Your design may not permit you to do the height: 100% trick, but in my case it was the solution.

IE 6 – Other attempts at a solution (more fun)

When playing around with IE 6, I attempted all sorts of things before using, the one solution that worked about 90% is as follows:

#progressBackgroundFilter
{
    position:absolute;
    height: expression(document.documentElement.scrollTop + document.documentElement.clientHeight + "px");
    width: expression(document.body.clientWidth + "px");
}
#processMessage {
    position:absolute;
    top: expression(document.documentElement.scrollTop + (document.documentElement.clientHeight * .30) + "px")
}

The thinking behind this was to take the window height (which document.documentElement.clientHeight gives us) and then add the scroll top position, which will give us the upper portion if the user scrolls up. The problem shows itself when the user scrolls down; that area is not covered. The good thing about this is that I didn’t need to mess with the body height, but the solution isn’t optimal in the long haul. Note this solution does work in the maximized state unlike other attempts (e.g. Figure 1 from earlier).

The purpose for me adding this “solution” is my hope that you, the reader, can come up with a solution that doesn’t involve body { height: 100%; }. Hopefully these attempts may help you come up with something a bit better. As stated earlier, the height thing can throw off some overall designs that you may have, for example if you have a margin or padding on your body element, your page will be that much longer.

Putting it all together

To get these styles to work with IE 7, Firefox, and IE 6, we need some technique to hide the IE 6 code from the other browsers. This is easily achieved without hacks and such by using a conditional comment. Conditional comments allow us to specify CSS code for a certain browser or range of browsers, hiding it from others.

The syntax for a condition comment follows a standard HTML comment (e.g.<!-- This is a comment -->) so that most browsers will simply ignore it. Internet Explorer however recognizes the <!--[if IE]> and processes it as part of the page. You can use specifics such as a straight browser version or a range using “lt” for “Less Than”, “gt” for “Greater Than”, and you can append an “e” (e.g. “lte” and “gte”) for “Or Equal To”.

In this case, we want to apply the IE 6 specific CSS to anything less than IE 7 (so the syntax is <!--[if lt IE 7]>). Here is snippet of what my HEAD section looks like, complete with conditional comment:

<head>
    <title>Visoft Inc.</title>
    <link href="styles.css" rel="stylesheet" type="text/css" />
    <!--[if lt IE 7]> <style type="text/css">@import "ie6.css";</style><![endif]-->
</head>

The IE 6 specific logic resides in the file ie6.css while everything else is in styles.css. Since the IE 6 specific stuff comes after the generic stuff, the styles will be overridden only for IE 6.

The end results

You’ve already seen a snapshot of IE 6, so here is what IE 7 and Firefox look like:

Figure 3 - IE7 with Modal UpdateProgress

Figure 3 – IE 7 with the Modal UpdateProgress

Figure 4 - Firefox with the Modal UpdateProgress

Figure 4 – Firefox with the Modal UpdateProgress

With this revised solution you should be able to use this approach in more designs where you need to disable the rest of the controls from the user. I feel that this is a nicer option that hiding content on the page or whatnot to achieve the same thing. The user’s experience is very important to the success of an application in the user’s eyes, so the nicer the UI, the better your application is perceived.

Updated Blog – Migration from Subtext to BlogEngine.NET

March 12, 2008 by Damien White

What better thing to do on a Tuesday night (well ok, Wednesday morning) when you can’t sleep than update your blogging engine.  Subtext is a great blogging engine, however; we outgrew some of its features.  In its place, we decided to go with BlogEngine.NET.  The transition was pretty easy thanks to BlogML, however, like all things, we needed to do some manipulation ourselves.  Along with the new blog engine, we also put in a new Visoft-branded blog theme, which was long overdue.  Instead of delaying the release of the new blog, we hope to launch a new Visoft, Inc. website in the next few weeks, which will be based on the blog theme we have here.  

Some of the new things to look for:

  • The old Subtext links should still work – BlogEngine.NET has different paths for posts, but with a bit of custom changes, these should be seamless.
  • The old RSS feed URL should work – (again thanks to some custom work), but you should switch to the new feed URL of http://blogs.visoftinc.com/syndication.axd just to make everything easier in the future
  • New authors! – It was lonely being the only one adding posts, look forward to other Visoft developers adding new posts in the future. BlogEngine.NET has a nice feature of being able to filter based on the author as shown here: http://blogs.visoftinc.com/author/Damien%20White.aspx
  • New content! – We have been holding off on publishing content until the new blog engine was in-place, so look for some new content coming real soon.
  • New theme – We would love your feedback on the new layout. 

There are too many new things to list, so feel free to browse the site and discover BlogEngine.NET and the new Visoft, Inc. Blogs!

Ping Services for BlogEngine.NET

March 12, 2008 by Damien White

I was looking for a list of Ping Services for BlogEngine.NET and came across Roman Clarkson’s post on the topic. As you may or may not know, BlogEngine.NET supports either XML or SQL for storage of posts, settings, etc. Roman has a pingservices.xml file available on his site, which can be downloaded and used with BlogEngine.NET’s XML provider.

When migrating to BlogEngine.NET, we decided to use SQL Server instead of XML, so I decided I would create a SQL script which does the same thing as Roman’s XML but for those of you that use SQL storage for BlogEngine.NET.

You can download the file here: BlogEnginePingServiceList.zip, the zip file contains the SQL script that you can run against your DB.

Dynamic AJAX Control Toolkit – Calendar Extender

February 06, 2008 by Damien White

Often times, I have encounter questions regarding dynamically creating controls, specifically ones related to the ASP.NET AJAX Control Toolkit. Today, I was working with an application where I needed to create a dynamic  CalendarExtender and thought I would post the results.

Here is a simple example of how to create a dynamic CalendarExtender from code-behind:

// Create a textbox to hold the date
TextBox dateValue = new TextBox();
dateValue.ID = "dateValue";

// Create the calendar extender
AjaxControlToolkit.CalendarExtender ajaxCalendar =
    new AjaxControlToolkit.CalendarExtender();
ajaxCalendar.ID = "ajaxCalendar";
ajaxCalendar.Format = "MM/dd/yyyy";
ajaxCalendar.TargetControlID = dateValue.ID;

placeHolder1.Controls.Add(dateValue);
placeHolder1.Controls.Add(ajaxCalendar);

In the ASPX, I have just a simple PlaceHolder where I append the dynamically created controls:

<asp:placeholder id="placeHolder1" runat="server">
</asp:placeholder>

Finally, here’s the end result:

Calendar

Wrox Blox – Hands On ASP.NET AJAX Control Toolkit

January 11, 2008 by Damien White

Hands On ASP.NET AJAX Control Toolkit I hope everyone had a good holiday, I apologize for not posting anything new in the past couple of months. Things have been very busy with everything going on lately. I happy to say that I can check one thing off the to-do list! For those of you that may not know, Wrox has created a new development to help programmers get up to speed quickly on new topics called a Wrox Blox. A Wrox Blox is a shortened down “Programmer to Programmer” eBook that focuses on specific tasks. For example, instead of finding the time to work through a 300 or so page book on a topic, the Wrox Blox talks specifically about a focused point. It also contains complete source code of the examples just like the “Programmer to Programmer” series.

In my case, I have written a Wrox Blox that focuses on the AJAX Control Toolkit titled “Hands-on ASP.NET AJAX Control Toolkit”. The book focuses on the controls: CollapsiblePanel, Accordion, Tabs, ModalPopup, TextboxWatermark, AutoComplete, and CascadingDropDown. Many of the topics and examples come from common questions that I have encountered on the ASP.NET forums. While the book focuses on specific controls, I feel it does a good job of discussing various topics related to all the controls, such as dynamic creation, digging into the source, understanding how controls are rendered, and theming to name a few. One specific topic found in the book that I’m sure most of you will be interested in is a much more in-depth look at theming the Tab Control. Creating themes for the Tab Control is one of the most popular posts on this blog and is frequently asked about in the ASP.NET forums.

The direct link to the book is: http://www.wrox.com/WileyCDA/WroxTitle/productCd-0470286644.html. I’d like to thank Jim Minatel at Wrox for getting me involved in the project and all of the wonderful editors at Wrox for polishing up my rambling thoughts.

ASP.NET AJAX ScriptManager JavaScript Files

October 05, 2007 by Damien White

I have been doing a bit of experimentation with ASP.NET AJAX (in this particular case .NET 3.5) and came across a nice feature of the ScriptManager and what it renders for the Microsoft AJAX JavaScript files. I just thought this sheds a bit more light on the operations of the ScriptManager and ASP.NET AJAX, and since you can never have enough knowledge, here it goes…

As you may or may not know, when you add a ScriptManager to the page, two JavaScript resources are pushed down to browser (via ScriptResource.axd): MicrosoftAjax.js and MicrosoftAjaxWebForms.js. These two files make it possible for you to use the JavaScript Microsoft AJAX Library extensions. Now for the cool part, if you look at MicrosoftAjax.js and MicrosoftAjaxWebForms.js you’ll see it’s very hard to read since there are no line breaks or formatting, and because of this, almost impossible to debug. See Figure 1 below for what MicrosoftAjax.js looks like to the browser.

Figure 1 - MicrosoftAjax.js

Figure 1 - MicrosotAjax.js

Now, you may not be seeing this particular view if you fire up Firebug and look for yourself. You may see something more like Figure 2:

Figure 2 - MicrosoftAjax.debug.js

Figure 2 – MicrosotAjax.debug.js

That’s MUCH better for debugging, isn’t it? What controls this rendering you ask? Simple, it’s the compilation debug setting your web.config:

<system.web>
<compilation debug="true">
...
</compilation>
...
</system.web>

As I’m sure you aware, compilation debug should be set to false when you deploy your application, but is typically set to true when developing.

While you can see I’m using AJAX in .NET 3.5 in this example, this feature of the ScriptManager holds true for the ASP.NET AJAX Extensions for ASP.NET 2.0.

Hopefully this gives you a little more insight into the operations of the ScriptManager and ASP.NET AJAX. Not sure if you’ve noticed this feature, but it sure is a nice one!

AJAX Control Toolkit – Tab Control – Themes

September 26, 2007 by Damien White

There seems to be a lot of issues on the ASP.NET Forums with “Theming” the AJAX Control Toolkit’s Tab Control. There are lots of requests for samples (one example), but there are limited resources out there. Looking at the Tabs sample page, you will find information on Theming, but it’s pretty basic. You will find the various styles that affect the tabs on the bottom of the sample page. Even with this, it leaves something out and people have problems. I believe the thing that throws people off is how the sample states “If your CssClass does not provide values for any of those then it falls back to the default value.”; the default value for the tabs are extremely basic. The style you most frequently see is the XP tab style (more on this later).

I feel you should begin by looking at the structure of the tab HTML to truly understand how it works. If you are curious about the other HTML structure, check out Firebug. The power of Firebug is truly amazing; this is a sample screenshot but doesn’t even come close to paying Firebug justice:

_[If anyone from the Microsoft IE team is listening; PLEASE give us this power in IE7 or IE8, the Internet Explorer Developer Toolbar is ok, but it just feels crippled next to Firebug and “Firebug Lite” doesn’t fill any of the real gap.]

Let’s take a closer look at the tab structure:

<span id="..." class="ajax__tab_active">
  <span class="ajax__tab_outer">
    <span class="ajax__tab_inner">
      <span id="..." class="ajax__tab_tab">Tab 1</span>
    </span>
  </span>
</span>

As you can see, a tab is constructed of nested <span> tags. The class ajax__tab_outer defines the right side of the tab, the class ajax__tab_inner defines the left side of the tab, and finally ajax__tab_tab defines the middle of the tab as this image shows:

Tab Layout

Now that we understand the tab structure, let’s work on some styles. In this example, we’ll clone the tab styles of Internet Explorer 7 (IE7) under Windows XP. The easiest way to create new styles is to copy that of the ajax__tab_xp which is the default style that you typically see. Browsing the source of the Tab control (which you can download from Codeplex), navigate to the AjaxControlToolkit\Tabs folder and open up Tabs.css. You will find a section called xp theme; this is what we are copying. Looking at the CSS you’ll see that the effects for the tab are created using images and for the IE7 style, we will do the same. So in copying the XP style, we create the following images:

  • tab-line.gif – Used to underline the header
  • tab-right – The right side of the inactive tab
  • tab-left – The left side (outer) of the inactive tab
  • tab – The inner portion (tab) of the inactive tab
  • tab-right-hover – The right side of the hover tab
  • tab-left-hover – The left side (outer) of the hover tab
  • tab-hover – The inner portion (tab) of the hover tab
  • tab-right-active – The right side of the active tab
  • tab-left-active – The left side (outer) of the active tab
  • tab-active– The inner portion (tab) of the active tab

…and finally create the styles (I have separated the background declarations from the other styles just for simplicity of listing and discussions)

First the backgrounds; this is a carbon copy of the ajax__tab_xp with just our new images replacing the embedded ones.

/* IE theme -- Backgrounds */

.visoft__tab_xpie7 .ajax__tab_header {
background:url(tab-line.gif) repeat-x bottom;
}

.visoft__tab_xpie7 .ajax__tab_outer {
background:url(tab-right.gif) no-repeat right;
}

.visoft__tab_xpie7 .ajax__tab_inner {
background:url(tab-left.gif) no-repeat;
}

.visoft__tab_xpie7 .ajax__tab_tab {
background:url(tab.gif) repeat-x;
}

.visoft__tab_xpie7 .ajax__tab_hover .ajax__tab_outer {
background:url(tab-hover-right.gif) no-repeat right;
}

.visoft__tab_xpie7 .ajax__tab_hover .ajax__tab_inner {
background:url(tab-hover-left.gif) no-repeat;
}

.visoft__tab_xpie7 .ajax__tab_hover .ajax__tab_tab {
background:url(tab-hover.gif) repeat-x;
}

.visoft__tab_xpie7 .ajax__tab_active .ajax__tab_outer {
background:url(tab-active-right.gif) no-repeat right;
}

.visoft__tab_xpie7 .ajax__tab_active .ajax__tab_inner {
background:url(tab-active-left.gif) no-repeat;
}

.visoft__tab_xpie7 .ajax__tab_active .ajax__tab_tab {
background:url(tab-active.gif) repeat-x;
}

Finally, the rest of the styles which we’ll change a bit from the ajax__tab_xp styles:

.visoft__tab_xpie7 .ajax__tab_header {
  font-family:verdana,tahoma,helvetica;
  font-size:11px;
}

.visoft__tab_xpie7 .ajax__tab_outer {
  **height:29px**;
}

.visoft__tab_xpie7 .ajax__tab_inner {
  padding-left:3px;
}

.visoft__tab_xpie7 .ajax__tab_tab {
  **padding:8px 40px;
  ** margin:0;
}

.visoft__tab_xpie7 .ajax__tab_body {
  font-family:verdana,tahoma,helvetica;
  font-size:10pt;
  border:1px solid #999999;
  border-top:0;
  padding:8px;
  background-color:#ffffff;
}

Most of the styles are arbitrary (and most are copies from the ajax__tab_xp styles), but the two import styles that effect the tab are the height and padding, underlined in the sample above. The height matches that of the tab images while the padding increases the width and centers the text vertically and horizontally. You could set different left and right paddings to change the text alignment, but in this example we have it centered.

The last thing we need to do is to add the custom CssClass to the Tab Container:

<ajaxcontroltoolkit:tabcontainer id="tabContainer" runat="server" height="300" cssclass="visoft__tab_xpie7">

Finally, everything in place; we get the following tab style:

IE Styled Tabs

The three styles are represented in the image: tab, active, and hover. Not a bad reproduction from the original. Obviously, we don’t have an image in the header in this example, but this can always be added using the <headertemplate> of the Tab Panel. You can also go a bit farther with the replication and add the thin bar that is below the tabs.

IE Styled Tabs 2