Josh Heyse

Thoughts Defragmented

Archive for September, 2008

Dynamic Data Filtering 1.10 on CodePlex

Posted by jheyse on 30th September 2008

After almost a month of sporadic work on Dynamic Data Filtering I am happy to announce that I am releasing the next version.  This version includes several new features and a bug fix. It is downloadable from CodePlex

New Features

Dynamic Filter Repeater

Based on suggestions I have added a Dynamic Filter Repeater.  This control uses the FilterAttributes annontated in your MetaModel to automatically populate the list of filters for a given page.  This is most useful if you modify your PageTemplates/List.aspx & PageTemplates/ListDetails.aspx pages.  Filtering is OPT-IN!

Visual Studio Integration

Dynamic Data Filtering now has a design time experience.  I have added design time rendering to the DynamicFilterForm and new DynamicFilterRepeater.  The first time you drag either control on to the form the designer will automatically create the DynamicData/Filters folder and populate the folder with the default templates provided.  You will also see a designer action, "Upgrade DataSource", which will convert a LinqDataSource to a DynamicLinqDataSource.

I have also added item templates to the Add New Item… window which will add a filter to the DynamicData/Filters folder for you.  Currently I have templates for the standard equals operator and range.  I believe these are the two most common filters used, let me know if you’d like the others and I will add them in the next release.

Thank you David and Joe from the ASP.NET team for their help with the designer support.
Thank you Steve for the icon work.

Installer

Dynamic Data is now distributable via an MSI installer.  This installer will install to %Program Files%Dynamic Data Filtering by default.  Included in this folder are the binaries, samples and the default templates.  The installer also automatically adds the VS integrations mentioned above.  This was my first experience with WIX and I must say I am impressed and have found my new installer development technology.

Thank you James who helped convert the C# examples and templates to VB.

Bug Fixes

It was identified that multiple queries were being performed against the database on pages that had a DynamicFilterForm on them.  It was found that this was caused by the BaseDataSource.PerformSelect() method.  This method has been overridden to prevent this behavior in both the DynamicFilterForm and DynamicFilterRepeater.

Posted in ASP.NET, Dynamic Data, LINQ | No Comments »

Microsoft ASP.NET and jQuery

Posted by jheyse on 28th September 2008

The recent buzz on my blog roll has been that Microsoft has announced that jQuery will be being distributed with the next version of ASP.NET.  I think that this is a HUGE move for Microsoft’s relationship with the open source community.  Not only are they going to be bundling the most popular javascript library, but they will also be contributing to the project as an equal to the rest of the project’s developers.

This is also going to help me as a consultant who often deals with companies who stay away from open source projects and non-Microsoft tools.

Posted in ASP.NET, Visual Studio, jQuery | No Comments »

View State Logger

Posted by jheyse on 19th September 2008

For the last several weeks I have been engaged at a client on a project originally written by another consulting firm.  The project is an ASP.NET 2.0 application and the design isn’t the best.  My role is to help get them through this last round of stabilization and out the door.  The web application is AJAXified with the use of UpdatePanels everywhere.  There is also heavy use of ViewState to persist objects (such as DataSets and DataTables!) between post backs. We are now doing some performance testing and it has become obvious that ViewState size is going to be an issue for users oversees.  Some pages had as much as 75k in ViewState. ViewState was over twice as big as RenderSize!  To make things worse a lot of this was hidden by the fact that the ViewState grew during UpdatePanel async postbacks.

The project is in triage mode and there isn’t time to be rearchitecting or refractoring anything.  To help figure out which pages needed work the most, I implemented a simple HttpModule that calculates the size of the ViewState on each page.  I implemented log4net to log the messages which will allow for configuration after the site goes live.

public class ViewStateSizeLoggerModule : IHttpModule
{
    private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
    public ViewStateSizeLoggerModule() { }
 
    public void Dispose()
    {
 
    }
 
    public void Init(HttpApplication context)
    {
        if (_log.IsInfoEnabled)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }
    }
 
    void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication app = sender as HttpApplication;
        if (app.Request.Url.OriginalString.Contains(".aspx"))
        {
            bool isAsyncPostback = !string.IsNullOrEmpty(app.Request.Headers["x-microsoftajax"]);
            app.Response.Filter = new ViewStateSizeLogger(app.Request.Url.PathAndQuery, isAsyncPostback, app.Response.Filter);
        }
    }
 
    private class ViewStateSizeLogger : Stream
    {
        private Stream _response;
        private string _pageName;
        private bool _isAsyncPostback;
 
        public ViewStateSizeLogger(string pageName, bool isAsyncPostback, Stream response)
        {
            _pageName = pageName;
            _isAsyncPostback = isAsyncPostback;
            _response = response;
        }
 
        public override bool CanRead
        {
            get { return _response.CanRead; }
        }
 
        public override bool CanSeek
        {
            get { return _response.CanSeek; }
        }
 
        public override bool CanWrite
        {
            get { return _response.CanWrite; }
        }
 
        public override void Flush()
        {
            _response.Flush();
        }
 
        public override long Length
        {
            get { return _response.Length; }
        }
 
        public override long Position
        {
            get { return _response.Position; }
            set { _response.Position = value; }
        }
 
        public override int Read(byte[] buffer, int offset, int count)
        {
            return _response.Read(buffer, offset, count);
        }
 
        public override long Seek(long offset, SeekOrigin origin)
        {
            return _response.Seek(offset, origin);
        }
 
        public override void SetLength(long value)
        {
            _response.SetLength(value);
        }
 
        public override void Close()
        {
            _response.Close();
        }
 
        int _length = 0;
 
        public override void Write(byte[] buffer, int offset, int count)
        {
            string viewStateHeader;
            string viewStateFooter;
 
            if (_isAsyncPostback)
            {
                viewStateHeader = "hiddenField|__VIEWSTATE|";
                viewStateFooter = "|1|";
            }
            else
            {
                viewStateHeader = "<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="";
                viewStateFooter = "/>";
            }
 
            string html = System.Text.Encoding.Default.GetString(buffer);
 
            int startingIndex = 0;
            if (_length == 0)
            {
                startingIndex = html.IndexOf(viewStateHeader);
                if (startingIndex >= 0)
                    startingIndex += viewStateHeader.Length;
            }
 
            if (_length != 0 || startingIndex >= 0)
            {
                int endingIndex = html.IndexOf(viewStateFooter, startingIndex);
                if (endingIndex == -1)
                {
                    _length = html.Length - startingIndex + _length;
                }
                else
                {
                    _length += (endingIndex - startingIndex);
                    _log.InfoFormat("ViewState Size for page {0}: {1:###,###,###} bytes", _pageName, _length);
                    _length = 0;
                }
            }
 
            _response.Write(buffer, offset, count);
        }
 
    }
}

Posted in ASP.NET | No Comments »

Presentation: ASP.NET Dynamic Data @ LCNUG on 9/25

Posted by jheyse on 16th September 2008

I’m giving my first presentation at the Lake County .NET Users Group (LCNUG) on Thursday, September 25th.  The topic is on ASP.NET Dynamic Data, a new feature released with the .NET Framework 3.5 SP 1.  I plan to make this presentation extremely code based and create a simple, but functional, automobile classified web site. The abstract for the presentation is located below, along with details on the event.  I will be posting the power point slides and code samples here, after the presentation.

Presentation Abstract

ASP.NET Dynamic Data is a new framework released with the .NET Framework 3.5 SP1 that lets you create data-driven ASP.NET Web applications easily. It does this by automatically discovering data-model metadata at run time and deriving UI behavior from it.  A scaffolding framework provides a functional Web site for viewing and editing data. You can easily customize the scaffolding framework by changing elements or creating new ones to override the default behavior.  Come see how ASP.NET Dynamic Data can drastically reduce development time, while still giving you the flexibility necessary to create rich data driven web applications.

Meeting Time & Location

Subs and will be provided at 6:30. Talk starts at 7:00.

College of Lake County
Technology Building Room T326-328
19351 West Washington Street
Grayslake, Illinois, 60030

Click on here for directions.

Map image

Posted in ASP.NET, Dynamic Data, Speaking | No Comments »

My Biggest Complaint about Visual Studio

Posted by jheyse on 2nd September 2008

Overall, I love Visual Studio. Every version gets better than the last.  I believe that is the single most productive tool a developer can use.  Eclipse comes in a close second, but this may only be because I live in Visual Studio a lot more then Eclipse and I know Visual Studio’s feature set much better. 

But the ONE thing that annoys me more than anything is accidentally hitting the F1 Key and brining up help. I recently installed a 3rd party component and it merged with my Visual Studio help files, so I am stuck with a help update in progress window:

HelpUpdateInProgress

Normally I am fine with this functionality, yes F1 should go to help and I do use the MSDN Library quite frequently.  But the true issue is that this locks the Visual Studio process from continuing to do work, if you attempt to click on VS or interact with it you receive the following Delay Notification:

DelayNotification

Why does opening, and possibly re-indexing, need to be an synchronous operation?!??! Seriously? I managed to type this blog post out and I am still waiting to get back to coding.

</rant>

Posted in Visual Studio | No Comments »