Mike Nichols - Son of Nun Technology

June 2007 Entries

Update Panel Request Handler Control

I am sure there is something already builtin to the UpdatePanel for this (?) but I couldn't find it and wanted to get it done.

I have a number of controls on page that need to be refreshed after callbacks from UpdatePanel. Namely, I am using Peter Blum's validators and wanted to validate a group of controls after a callback. Rather than writing client script over and over, I create a UpdatePanelRequestHandler control that you can drop on your page and it'll create the add_endRequest or add_beginRequest client scripts for you can register them as Startup scripts.

Just tell the control the script to run on either begin or end callback and it'll render it to your page. I am just pasting the control here...

[UPDATE] I have created a much more flexible control exposing these client side events as a server control to easily be able to hook client side scripts before/after callbacks . You can get the code and tests at code.google.com/p/son-of-nun/


 

    [NonVisualControl, Designer(typeof(UpdatePanelRequestHandlerControlDesigner))]
[ParseChildren(true)]
[PersistChildren(false)]
[DefaultProperty("ScriptToRunOnEndRequest")]
public class UpdatePanelRequestHandler : Control
{
private string _beginRequestFunctionName = "begin_{0}";
private string _endRequestFunctionName = "end_{0}";
private string _scriptToRunOnEndRequest = string.Empty;
private string _scriptToRunOnBeginRequest = string.Empty;
public const string end_Request = "add_endRequest";
public const string begin_Request = "add_beginRequest";
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
_endRequestFunctionName = string.Format(_beginRequestFunctionName, this.ClientID);
_beginRequestFunctionName = string.Format(_endRequestFunctionName, this.ClientID);
}

public string BeginRequestFunctionName
{
get { return _beginRequestFunctionName; }
set { _beginRequestFunctionName = value; }
}

public string EndRequestFunctionName
{
get { return _endRequestFunctionName; }
set { _endRequestFunctionName = value; }
}

public string ScriptToRunOnBeginRequest
{
get { return _scriptToRunOnBeginRequest; }
set { _scriptToRunOnBeginRequest = value; }
}

public string ScriptToRunOnEndRequest
{
get { return _scriptToRunOnEndRequest; }
set { _scriptToRunOnEndRequest = value; }
}
private string CreateRequestScript(bool isBeginRequest,string requestFnName,string scriptToRun)
{
string handlerScriptName = isBeginRequest ? begin_Request : end_Request;

StringBuilder script = new StringBuilder();
script.AppendFormat("Sys.WebForms.PageRequestManager.getInstance().{0}({1});function {1}",handlerScriptName,requestFnName);
script.Append("(sender,e){if (e.get_error() == null){");
script.Append(scriptToRun).Append(";}}");
return script.ToString();
}
public string EndRequestScript
{
get
{
if (string.IsNullOrEmpty(ScriptToRunOnEndRequest))
return string.Empty;
return CreateRequestScript(false, EndRequestFunctionName, ScriptToRunOnEndRequest);
}
}
public string BeginRequestScript
{
get
{
if (string.IsNullOrEmpty(ScriptToRunOnBeginRequest))
return string.Empty;
return CreateRequestScript(true, BeginRequestFunctionName, ScriptToRunOnBeginRequest);
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
StringBuilder scripts = new StringBuilder();
scripts.Append(BeginRequestScript).Append(EndRequestScript);

if (scripts.Length > 0)
{
StringBuilder script = new StringBuilder();
script.Append("<script type='text/javascript'>");
script.Append(scripts.ToString());
script.Append("</script>");
Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_requestHandler",
script.ToString());
}
}

}
internal class UpdatePanelRequestHandlerControlDesigner : ControlDesigner
{
public override string GetDesignTimeHtml()
{
return base.CreatePlaceHolderDesignTimeHtml("");
}
}

Reloading Firefox CSS without full load

I'm doing alot of page design right now and this little function that lets you reload all your css files without having to load the whole page.

Found this neat snippet here but his code is broken because the brower substitutes the 'idea' ligh bulb for [i] in the loop. So I am reposting the code.

 Just create a bookmark and in 'location' plug this javascript. I have this in my toolbar so I can quickly view my changes in css realtime.

 Copy and paste...this formats funny in the blog but I didn't want to introduce any /r/n's so you can just paste into the Firefox dialog box.

javascript:void(function(){var i,a,s;a=document.getElementsByTagName('link');for(i=0;i<a.length;i++){s=a[i];if(s.rel.toLowerCase().indexOf('stylesheet')>=0&&s.href) {var h=s.href.replace(/(&|%5C?)forceReload=d+/,'');s.href=h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+(new _fcksavedurl="h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+(new" Date().valueOf())}}})();

Templating User Controls in ASP.NET And Inner Visibility

One of my favorite ways of simply templating logical tasks in my current project is using templated User Controls. It's a great way to reduce duplicated HTML maintenance.

I read about this here and followed the links and really dug how it gave me more freedom since there was less duplication. But one problem came up when trying to access the controls placed within the template regions. I had placed the ParseChildren(true) attribute on the usercontrol class so could only get to my inner controls using FindControl. Lame.

So next I tried to make it easier using ParseChildren(false). This lets the controls be visible to me, but it also rendered the template tags, totally screwing my html.

Finally, I came across Nikhil's post on SingleInstanceTemplate. I set my ParseChildren attribute back to true and then on each ITemplate within the UserControl I am using as a template I added the attribute

TemplateInstance(TemplateInstance.Single)

DING! I got my html back and still have access to my inner controls.

Using Interfaces Against NHibernate

A question came up on the NHibernate forum that I think is very common. I am sure there is a better way of dealing with this, but I haven't figured it out yet.

I have the following abstraction for a class hierarchy: 

public interface IFoo
{
string MyProperty{get;set;}
string MyPropertyWithNoSetter{get;}
}
public interface IFooBar : IFoo{}
public interface IFoosBall : IFoo{}

An abstract class might emerge through refactoring and the concrete implementations of my contracts might end up looking like this:

public abstract class FooBase : IFoo
{
string MyProperty{get;set;}
string MyPropertyWithNoSetter{get;}
}
public class FooBar : FooBase, IFooBar{}
public class FoosBall : FooBase, IFoosBall{}

Now I really want to use IRepository<IFoo> or IRepository<IFooBar> or IRepository<IFoosBall> to interact with all my Foos. But how do I map this in NHibernate so that it will know what I want to do? 

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyCore" >

  <class name="IFoo" table="Foo" >

    <id name="Id" access="property" unsaved-value="0" >

      <column name="Id"/>

      <generator class="native" />

    </id>

    <discriminator>

      <column name="TypeCode" not-null="true" sql-type="nvarchar(25)" />

    </discriminator>

 

    <property name="MyProperty" />

 

    <subclass name="IFooBar" discriminator-value="IFooBar">

      <subclass name="FooBar" discriminator-value="FooBar">

        <!--note this is repeated from FooBase class-->

        <property name="MyPropertyWithNoSetter" access="nosetter.camelcase-underscore"/>

      </subclass>

    </subclass>

    <subclass name="IFoosBall" discriminator-value="IFoosBall">

      <subclass name="FoosBall" discriminator-value="FoosBall">

        <!--note this is repeated from FooBase class-->

        <property name="MyPropertyWithNoSetter" access="nosetter.camelcase-underscore"/>

      </subclass>

    </subclass>

  </class>

</hibernate-mapping>

There are a couple of points of interest here:

  • Since interfaces do not have fields, prefer the default 'property' access strategy for NHibernate and provide the getter/setter on properties.
  • If you have a property that you must enforce without a setter (see MyPropertyWithNoSetter) and that is represented in a base class (FooBase), then you will need to duplicate the mappings on those properties for the implementations of that base class and set the  appropriate access strategy for those properties.
  • You MUST provide discriminator values for even those <subclass> elements that will not be persisted (IFooBar and IFoosBall in this case). Otherwise, you'll get an exception telling you that NHibby couldn't instantiate an abstract class or interface. When Nhibernate does a query using your mapping it will use the IN sql operator in the WHERE clause.So an ICriteria using typeof(IFooBar) will have 'WHERE TypeCode IN ('IFooBar','FooBar')' in its query.

Now I will be able to do things like IRepository<IFooBar>().Get(myID) or IRepository<IFoosBall>().FindAll(DetachedCriteria.For(typeof(IFoosBall))...).

Hope this helps...

Boo Generic Syntax

I wanted to write a quick note to highlight Boo generics syntax since I had some difficulty finding clear docs on this. As I am digging into brail and using Binsor this'll be handy since the latest drop of Boo supports generics.

This states that generic type definitions in Boo are handled thus:

 MyType of MyGenericParam

or for multiple generic parameters

MyType[of X,Y,Z]

Also found a discussion here.

So in Binsor to register a component, it could be something like:

Component(name,IMyService[of IThing1,IThing2],MyImplementation,LifestyleType.Eternal)

 

Tasty!

Visual Studio Tabbed Document Navigation

Being lazy, I never would just look into the Tool/Options menu of VS.NET to see how to flip between tabbed documents with the keyboard. The option is Window.PreviousDocumentWindow .  I set these to Alt+PgUp and Alt+PgDown to  toggle between my documents. The only thing I couldn't see was how to 'Close alll but this' with the keyboard. Anyone know how to do that?

Protecting the developer from himself and his profession

There are lots of discussions going on in the blogosphere about Mort's and wizards and designers and so on. I won't bother with a link list since it probably isn't necessary and really I am not probably qualified to comment authoritatively on them anyway.

I can,however, give my own impressions of tools that seem to be developed to help coding or make promises of '80% less code' as a developer who wrangled with these tools for a long time.

I remember the first time I opened up Visual Studio for the first time and read the walkthrough that told me to drag a sql adapter onto a webform (or something like that) and the feeling I got. I had come to development from VBA and Excel tricks and was excited to finally be a 'bonafide' developer. The feeling took me all the way back to middle school when I first started to learn drums. Everyone was encouraging me to sit down on the drumset and imitate the grooves laid down in the popular music of the day as a way of learning to make music. I saw value in this but I wanted to learn how to play drums. Show me how to hold the sticks correctly, show me how to listen to the music and point out what makes certain sounds 'paint' different emotions in me. Yeah I want to play as quick as I can, but please don't leave me there and have me believe that I am a drummer simply because I can play a White Snake song. I fely like they were protecting me from being a drummer who knew what he was doing.

When I was led to software development I started out approaching it like I have always approached new things - I want to be an artist with the tools I have. I want to be a sculptor not a manufacturer of pink flamingos. So when I was drowned in a sea of drag-and-drop-just-let's-get-started-so-you-look-like-you-have-something-on-the-web tools, wizards, datasets, etc., I seemed to have lost my original desire to be expressive in technology. Even though we are creating business applications that have business value I still never stopped believing that within that scope you can do something elegant, creative, and even geekily beautiful. Kind of like listening to Kenwood Dennard with Maceo Parker or Vinnie Colaiuta with Sting...it's popular but within there is great ingenuity and beauty!

Last year I finally was led to discover TDD, DDD, and other Agile methodologies and principles that finally seemed to affirm the icky feeling I was getting producing web pages without really understanding HTTP and completely confused about what 'layered' applications were supposed to look like. Even basic stuff like file structures and so on bewildered me and the slightest change to my software would send a bowel movement thru my entire project that would break code everywhere...yecch. This is art?

Ironically, the catalyst for this was Ruby On Rails and the 'Agile Web Development With Rails' book. All of a sudden I realized that I had been getting protected from software development. There was no intellisense, no installer or wizard. Just SciTe. I even had to deploy to a Unix server and got bit by the differences from deploying to a Windows environment. IT WAS FUN. All of a sudden I felt like I had control of my environment and the more I learned the more creative I got. For people who think that wizards, drag-and-drop data controls, and so on reduce friction I would encourage them to dive into a framework that has none of those and see if that is true. I discovered the opposite was true and frankly I was GLAD there wasn't a good IDE around for RoR...it forced me to learn what was happening under the hood and forced me into the simplest solution possible each time. Now I'm learning MonoRail and while Castle gets bad press about 'bad documentation',when I have difficulty with it I usually discover that it is due to some hole in my knowledge about web development, not with the framework. I LIKE that it challenges me to know what I am doing.

We are fortunate today to have such breadth of information at our fingertips. However, I am afraid that our fastfood mentality to learning has hijacked the ancient apprenticeship/craftsmanship approach we all crave when we first begin. I've got so much more to learn but I am thankful that there are those who at least question the emphasis on shortcuts to producing applications and encourage developers to grow in their skillsets.

Mike

Early MonoRail Lessons #1- RailsFacility usage

I am using a new project I just started to learn MonoRail. I have completed a previous project using Ruby On Rails so was excited to dig into Monorail and have not been disappointed.

A very helpful sample application that has some great guidance is the Timok.Rbr sample. Inside this sample, they are utilizing the RailsFacility to wire up the controllers with underlying services automagically using Windsor (referencing the Castle.MonoRail.WindsorExtension package).

Since I can be like the Tasmanian Devil learning new technology, I kept overlooking a very simple configuration element that prevented me from enjoying the autowiring goodness. Inside the web.config for the monorail config section :

 

  <monorail smtpHost="yoursmtphost" useWindsorIntegration="true">   

Failure to set the useWindsorIntegration attribute to 'true' will result in :

No parameterless constructor defined for this object.

exception messages since the application doesn't know it should be using Windsor to inject your services. I knew what the problem was and knew this was a rookie mistake but wanted to post the exception message to point to the solution anyways. Of course, this would be wrongly set if you started out without intending to do the Windsor hookups.

Hope this helps.

Mike

AutoSuggestBox ASP.NET Control With Scriptaculous Autocompleter

A while back I posted some findings while searching for a suggest box that was easy to use and bore the weight of javascripting for me. I extended a decent control I found on CodeProject but the problem was that it subclassed Anthem.NEt's TextBox control. What I wanted was to rather have an extender-type of control that would decorate the behavior of any ITextControl derivative so that I could freely use third-party control and such.

Going through all this made me really want to get familiar with prototype and Script.aculo.us libraries. They are widely used and the Ajax Control Toolkit has been buggy for me to use so I thought it would be a good opportunity to really get under the hood of what AJAX is and how to deal with out-of-band requests.

Here were my requirements:

1. Plays nice with the UpdatePanel in ASP.NET Ajax Web Extensions...no kooky parser errors

2. Templatable for Header, Item, and EmptyItem situations

3. Easy to style

4. Pluggable script options so I can have other client-side actions respond to selections

5. SelectedValue property and SelectedValueChanged event on client-side and server-side

6. Options for Animated gifs for progress indicators and I can put those ANYWHERE on the page

7. Can have the suggestions set at a width different from the referenced TextBox (which is the default behavior for the Scriptaculous control)

Before building the server control needed to wrap my head around the prototype.js library while digging into the excellent Scriptaculous autocompleter control. These libraries make all kinds of things a snap and are a blast to play around with. I am learning monorail at the same time so I needed to understand prototype anyways.

Along the way I came across Simone Busoli's BusyBox implementation of the Scriptaculous control and while it had many features I needed, I wanted to extend it further. 

Here's a look at what I can do now: 

        <asp:TextBox runat="Server" ID="TextBox1" Width="400px"/><asp:PlaceHolder runat="server" ID="ImagePlaceHolder1" /><br />

        <SON:AutoSuggester runat="server" ID="AutoSuggester1" TargetControlID="TextBox1"

                ProgressAnimatedImage="AzureFlower" Width="650px"

                AnimatedImageContainerID="AnimatedImageContainer1" OnSelectedValueChangedClientFunction="refreshUpdatePanel">

            <HeaderTemplate>

                Header Stuff Here

            </HeaderTemplate>

            <ItemTemplate>

                <%# Container.DataItem %>

                <span>Man we should make this complicated</span><br />

                <asp:TextBox ID="TextBox2" runat="Server" >For Instance here is a textbox</asp:TextBox>

            </ItemTemplate>

            <EmptyItemTemplate>No Items Found!</EmptyItemTemplate>

        </SON:AutoSuggester>

  • TargetControlID - The ID (in the same Naming Container) of the TextBox to attach behavior to
  • ProgressAnimatedImage - A enumeration of stock images to show while the callback is happening
  • AnimatedImageContainerID - The control that will hold the image...monkeying around with Response.Filters to render the image html right after the TextBox caused too many parser headaches in UpdatePanels
  • OnSelectedValueChangedClientFunction - A client side function that will receive one parameter (the new value of the hidden _value field). You can use this to refresh update panels too or whatever
  • HeaderTemplate - A non-selectable item that is, um , the header
  • ItemTemplate - The template just like in a Repeater that you can use to show other bits of info, but perhaps just populating the textbox with a specific field (see DataTextField)
  • EmptyItemTemplate - The template that will show (along with the Header if specified) when no items are returned on the callback
  • DataTextField (not shown) - The property name in the DataItem to reflect upon for the TEXT WHICH WILL POPULATE THE TEXT BOX
  • DataValueField(not shown) - The property name in the DataItem to reflect upon for the value that will be saved as the SelectedValue (hidden field)

 

The html for the items rendered by the Items are as follows:

<ul>

    <li id='1' class='autosuggester-item' >

        <span style='display:none;'>One</span>

        <div class='informal' >One<input type='hidden' id='AutoSuggest1_Results_1' value='One'/></div>

    </li>

    <li id='2' class='autosuggester-item' >

        <span style='display:none;'>Two</span>

        <div class='informal' >Two<input type='hidden' id='AutoSuggest1_Results_2' value='Two'/></div>

    </li>

    <li id='3' class='autosuggester-item' >

        <span style='display:none;'>Three</span>

        <div class='informal' >Three<input type='hidden' id='AutoSuggest1_Results_3' value='Three'/></div>

    </li>

</ul>

The 'informal' class is used by the Scriptaculous script to identify items that should not populate the TextBox. The first hidden span is the actual value that will be placed in the TextBox.

While there are a few more features I want to implement I think this is pretty rich and I have it working inside UpdatePanels and multiple controls and so on. It's fairly lightweight, too, as are the Scriptaculous and prototype libraries that are embedded.

I don't have a binary dist yet so you can hop over to my new google hosted source-code repository at http://son-of-nun.googlecode.com/svn/ .

On a side note, it was somewhat frustrating not being able to manipulate the rendered HTML from another control (the TargetControl here) without making ASP.NET go awry. It seems like it would be simple to have an event that fires pre- and post- Render() method that passes the html so it could be played with. But this is probably another case of protecting the developer from the framework.

Apparently this is a known issue when you use Response.Write directly in your code during callbacks. I implemented a custom Response.Filter to intercept the html during the Write() call and injected the image html there, but while this worked great on partials where no callback was taking place, the UpdatePanel simply couldn't figure out what was going on and would complain.

Enjoy...

Resources

Persisting DateTime values and Unit Testing

This is a note for me to recall when doing testing between my app and the database.

Typically, I initialize DateTime variables to a specification in my application using a Specification like this:

 

    public class DateTimeSpecification

    {

        public static DateTime UNSPECIFIED_MIN = new DateTime(1800,1,1).Date;

        public static DateTime UNSPECIFIED_MAX = new DateTime(2999,12,31).Date;

    }

This works great but of course I forget sometimes. There was a good discussion on Oren's blog about this issue a while back but I didn't ahve time to keep up with it. My solution to get around the dreaded SqlDateTimeOverflowException is to use this Specification in my apps.

I am thinking about writing a patch for NHibernate that would have a floor and ceiling for DateTime values according to the DB provider...eventually.

Anyways, I was using SqlCE to do some testing and the message is a bit cryptic:

System.Data.SqlServerCe.SqlCeException: An overflow occurred while converting to datetime.

It's the same issue, just a less meaningful message...

Scriptaculous controls playing nice with UpdatePanel (ASP.NET Ajax)

I've been playing around with the scriptaculous controls but came across difficulty with the script not firing after a partial update when embedded within an UpdatePanel.

It's worth noting that prototype.js and ASP.NET Ajax script work okay together. I understand there used to be a conflict.

Anyways, I found an obscure thread that helped me fix my problem here.

Basically you just need to hook into the Sys.WebForms.PageRequestManager's endRequest event and fire your scriptaculous script when the UpdatePanel has completed it's stuff:

      <script type="text/javascript">
        // <![CDATA[
                Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandle);

                function endRequestHandle(sender, args)
                {
                        if (args.get_error() == null)
                        {
                                if ($("photoframe"))
                                {
                                        Sortable.create("photoframe",  {
                                                        tag:'div',only:'photoimage',overlap:'horizontal',constraint:false,
                                                        onUpdate:function()
                                                        {
                                                                $("<%= SortOrderHiddenFieldID %>").value = Sortable.serialize("photoframe");
                                                        }
                                                });
                                }
                        }
                }
        // ]]>
        </script>

My custom control required having the scriptaculous script outside this script block and also within to behave all the time.

 

Hope this helps...

 

Mike

Selenium IDE

I'm trying to get in the unit testing for web pages game and  came across Selenium IDE.

It's got a nifty recorder so you can just navigate the web form and right-click assertions along the way. WHen you are done you can export the test to C# code (among others).

Great way to learn Selenium I think.

Resources