Friday, September 23, 2005

How I got FreeTextBox 3.0 working without aspnet_client

[11/22/05 Update: FreeTextBox 3.1.1 requires fewer fixes, and an updated blog on the process is here].

FreeTextBox is a (free) rich text editor control for ASP.NET 1.1 and 2.0. It is pure JavaScript, supports Mozilla, IE, and other popular browsers, and works great (almost). You can add it to your web designer toolbox and just drop it onto a web page and you have rich text editing for free. It's incredibly easy, and the other has done a great job. With the release of FreeTextBox 3.0, the requirement for a very hefty aspnet_client subdirectory was replaced with an http handler that can fetch all of the control's dependencies (gifs, jpgs, js, etc.) straight out of the control's assembly. That means deployment is as easy as copying a single FreeTextBox.dll file into the Bin directory of your ASP.NET web application and you are ready to launch. Swell... except it doesn't work. Not quite.

To get the FreeTextBox control to pull its dependencies out of the assembly rather than external files, its installation instructions claim that with ASP.NET 1.1 you have to add an HTTP handler to your web app's Web.config file, and that with ASP.NET 2.0, you don't. You actually have to modify Web.config for both versions of ASP.NET. Just follow the instructions that they give for ASP.NET 1.1 for modifying Web.config, and your ASP.NET 2.0 app will be on its way to using just the .dll. In my next blog post, I'll talk about enhancing their instructions so your FreeTextBox.dll assembly doesn't even have to be in your Bin directory.

The way FreeTextBox 3.0 comes from their download page, it has a few bugs that get in the way of completely eliminating dependencies on aspnet_client (at least up to version 3.0.6, the current version as of the time of this writing). I'll enumerate them here, and how to get around them. But first, let me prescribe the code you use to try to get it working for yourself, and then I'll list the gotchas that you'll likely run into, and how to solve them.

For the purpose of this blog, I will be assuming that you are following along using ASP.NET 2.0. However, very nearly all (if not all) of the steps would be the same for ASP.NET 1.1.

  1. Modify your Web.config file so that it includes this snippet between the <system.web> tags:
    <httpHandlers>
     <add verb="GET" path="FtbWebResource.axd" type="FreeTextBoxControls.AssemblyResourceHandler, FreeTextBox"/>
    </httpHandlers>
  2. Now open up an empty .aspx page. Add this line just below the <%@ Page ... %>line:
    <%@ Register Assembly="FreeTextBox" Namespace="FreeTextBoxControls" TagPrefix="FTB" %>
    Now add this tag where you want the rich text box to appear:
    <ftb:freetextbox id="FreeTextBox1" supportfolder="~/FtbWebResource.axd" focus="true" runat="Server"/>
    Notice that you must explicitly set these attributes as given. A few hiccups may/will happen, and are listed below, if you don't. For now, just do it. :)
  3. Copy the FreeTextBox.dll assembly that you downloaded into your web application's Bin directory. If you are using ASP.NET 2.0, grab the copy of the .dll that resides in the "bin\Framework 2.0 Beta 2" subdirectory of the downloaded zip.
  4. Start your web application and browse to the .aspx you just created.

At this point, you will either see a working FreeTextBox, or (and much more likely) you will run into one or more of the issues below. Next to each issue is its fix.

  • FreeTextBox improperly caches certain HTML attributes for the life of the web application. If you change attributes in a tag (like SupportFolder or any of the ...Location= attributes), you will typically need to restart your web site/server in order for the changes to actually get noticed. The easiest way to do this is to re-save your Web.config file. You don't need to make any changes to Web.config. Just save it to get ASP.NET to dump the web app and reload it, effectively dumping FTB's cache.
  • Failed to map the path '/aspnet_client/FreeTextBox/Languages/en-US.xml'.
    This comes up when you haven't set the SupportFolder attribute to point to your .axd handler. Be sure to work from the snippet I include above, with emphasis on the SupportFolder="~/FtbWebResource.axd" attribute. And remember to re-save Web.config so that the new attribute will be noticed.
  • FreeTextBox has not been correctly installed. To install FreeTextBox either:
    1. add a reference to FtbWebResource.axd in web.config:
      <system.web>
       <httphandlers>
        <add verb="GET" path="FtbWebResource.axd" type="FreeTextBoxControls.AssemblyResourceHandler, FreeTextBox"/>
       </httphandlers>
      </system.web>
    2. Save the FreeTextBox image and javascript files to a location on your website and set up FreeTextBox as follows
      <ftb:freetextbox id="FreeTextBox1" supportfolder="ftbfileslocation" javascriptlocation="ExternalFile" toolbarimageslocation="ExternalFile" buttonimageslocation="ExternalFile" runat="server"/>

    This is the most fatal flaw in FreeTextBox, and it's the one that ultimately trips most people into giving up. The error lies in FreeTextBoxControls.Resources.JavaScript.FTB-Utility.js, one of the javascript files that are embedded in FreeTextBox.dll. This file exists in the aspnet_client directory (that we're not using), and oddly it's not the same file. And the embedded file has two typos in it that keep the browsers from parsing it, resulting in this error. The fix is not too difficult, honestly, but it's the pits that it has to be done. Keep in mind to, that this fix probably can't be redistributed because of copyright laws. So fix it for yourself, and anyone else who wants this fix should download the control themselves, and then come here to patch it themselves. Here's the fix:

    1. Copy your FreeTextBox.dll from your web app's Bin directory to some temporary and clean directory. For this example, I'll assume c:\temp\ftb. When you download FreeTextBox, 3 versions of the FreeTextBox.dll are included (for some reason). One is for .NET 1.0, another for 2.0, and another one that isn't labeled. Work with the one in the 2.0 directory. At least that is what I did, so I know it works.
    2. You'll need the .NET Framework SDK for this step, but that comes with Visual Studio, to access it from the command prompt, navigate through your Start menu to your Visual Studio 200x group, and then deeper into the "Visual Studio Tools" group. Launch "Visual Studio 200x Command Prompt". This opens a command prompt with the PATH variable set so you can use the SDK commands easily.
    3. Change to the temporary directory you created with FreeTextBox.dll in it.
      cd \temp\ftp
    4. Decompile the FreeTextBox.dll assembly. We need to fix the embedded .js file within it. This is how you do it:
      ildasm /out=FreeTextBox.il FreeTextBox.dll
      You should now have hundreds of files in your little temporary directory. These files all make up what you will eventually recompile into your patched version of FreeTextBox.dll.
    5. Keep your command window open. You'll use it later.
    6. Using your favorite JavaScript editor (Notepad does just fine), fix two lines in FreeTextBoxControls.Resources.JavaScript.FTB-Utility.js:
      old line 14: for(var i = 0; i < arguments.length; i++){
      new line 14: for(var i = 0; i < arguments.length; i++){
      old line 35: for(i = listEvents.length - 1; i < = 0; i = i - 1){
      new line 35: for(i = listEvents.length - 1; i <= 0; i = i - 1){
      These changes are to change an HTML representation for the less-than sign to the sign itself, and to remove the space between <= that shouldn't be there.
    7. It's a really good idea to increment the version number of the assembly you're building. Otherwise, .NET thinks that your assembly is identical to the old one, and won't trash the old one in its cache with your new one, and the bug won't go away. Modify 1 line in FreeTextBox.il to increment the version number:
      old line 2251: .ver 3:0:6600:6
      new line 2251: .ver 3:0:6601:6
    8. One optional change can be made in FreeTextBox.il while you're there. It's a shame that the SupportFolder="~/FtbWebResource.axd" attribute has to be manually added to every FreeTextBox tag you drop into a web page. Change these few lines in your .il file to fix the default value so you don't have to: 35305, 18049, 17992. Don't mess with the IL hex code--just the string. Below is an example of the change.
      old line 35305: IL_001d: ldstr "/aspnet_client/FreeTextBox/"
      new line 35305: IL_001d: ldstr "~/FtbWebResource.axd"
    9. In the command window you used to decompile, recompile the FreeTextBox.dll like this:
      ilasm /dll FreeTextBox.il /output=FreeTextBox.dll /quiet /key=yourkey.snk
      You'll need to have your own strong name key. You can generate one with sn.exe -k yourkey.snk
    10. Copy your new FreeTextBox.dll assembly to your web app's Bin directory. This change to Bin should automatically cause ASP.NET to restart the web app, so just refreshing your browser should now eliminate the error that was displayed initially. Yay!
    11. One note: if you've already been using the GAC to store FreeTextBox, you'll need to add your new assembly to the GAC and adjust your Web.config and .aspx files to point to your own version of FreeTextBox before you'll see the fix. If you didn't follow that, don't worry about it. Read my next blog when it is published.

    So that's it. That should get it working for you. Please post a comment below either way. Let me know if this has helped, or if there are other bugs/issues you've run into, including their fix, if you have it. I'm not an expert on FreeTextBox, but seeing as the author of it doesn't seem to be responding to any forum messages and isn't updating his installation wiki to be correct, let's make this blog useful for everyone!

2 comments:

  1. iwant freetextbox within scriptmanage and updatepanel

    ReplyDelete
  2. hey Andrew... i want to use FreetextBox in C# windows application.. is it possible ... if not what are other options to Freetextbox...?

    regards
    kK

    ReplyDelete