CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Peter's Gekko

public Blog MyNotepad : Imho { }

April 2006 - Posts

  • Of mice and old men

    Working all day with screen, keyboard and mouse is quite a stress to some parts of your body. Over the years, getting old, you have to pay the toll. Sore wrists and tired eyes can become side-effects of your hard work. So far I'm surviving quite well but I do pay a lot of attention to anything which helps.

    I'm addicted to Microsoft hardware. Their gull-wing keyboard is awesome and their mice are quite comfortable as well. I don't believe there is one mouse model which is the solution to RSI prevention; what really helps is switching continuously from one model to the other. So I have a couple hooked up together with the keyboard in a little goodie bag USB (1.1 is good enough) hub.

    A "normal" mouse a monster trackball and just recently a wireless notebook laser mouse joined the club.

    The latter has one, thumb operated, magnify button on the side. Which fires up the Intellipoint (MS mouse software) magnifying glass. Which is another big help. It can be just the tool to find that little pesky typo in a query.

    The magnifier can be fired up with another mouse as well. In the configuration dialog you assign the function to a button. It took me my new mouse to find that out. In Vista the magnifier is part of the OS itself.

    There is one thing which can be improved in this scenario. The mouse configuration lets you select one type of mouse and its button configuration is used for all mice attached. Enabling the magnify button on the laser-mouse turns the forward button of the other mice attached into a magnify button as well. I just wish I could configure the three mice independently. Beside the buttons it would make a lot of sense to set precision and acceleration different for each model. Something to check in Vista.

  • RADical ASP.NET in VS 2005 without messing it up right from the start

    The term RAD is more or less a hot topic on Codebetter. It started with a "RAD kills" post by Jeffrey which lead many people to chime in. As I almost glorified RAD it's time to write something more elaborate on how I think you can work with RAD without making a mess out of it. This will dance around the objectdatasource and the dataset. Two components who are surrounded by a lot of RAD-wizardery. I will not treat those themselves, most of it can speak for itself, but will try to place them in a broader application wide context.

    What RAD exactly is is a sliding definition. What everybody seems to agree on is that it's drag and drop. You drag something from a toolbox in your IDE and drop on something else. Dropping visual things designing (web-)forms is natural. Remember editing resource-files in the earlier days of Windows to create a form ? The Delphi and VB form designers were a great step forward. But you can also drop non visuals on your form (or component, web-service designer, etc). These "things" can be anything: an operation on a database; an interaction with the service manager; a message queue. This can be very dangerous. Someone not hindered by any knowledge of the matter will drop something which he does not understand what it actually is, let alone what it does. Like coding with a chainsaw. Cuts through the problem quickly but the damage is astonishing and impossible to repair

    In the following I will demonstrate this in a small asp.net 2.0 web site. Visual Studio is a good tool to build an UI. I haven't bumped into the common troubles yet so I prefer 2005 over VS 2003. I had built a lot with asp.net 1.1. Applications which handled a lot of user input and I had to write loads of plumbing code. Many, many screens, with even more fields. Coding patterns emerged, but in the end it was still a hell of a lot of typing. The one thing which makes ASP.NET 2.0 stand out is 2 way databinding which finally relieves me of writing the plumbing code. When I study the code generated by VS and its execution flow it's not unlike the patterns I followed myself in 2003. But this code is generated a lot faster and with less errors than I can type myself.

    So designing webforms with VS 2005 with a lot of drag and drop (which also works in the markup view) saves me lots of time and effort. So it's quite tempting to do the database handling the same way. In the toolbox is a sqldatasource. Dropping one on my webform is just as easy as dropping a textbox. But look what happens to the markup:

    The markup should be about the way you webpage looks. But now is does contain a plain (MS) sql (server) query. When it comes to maintenance it's not a very comforting idea to store the sql strings in the markup of  the aspx. Everything from the appearance to the low level database access is now in one assembly, even in one code file bringing the application down to a monolithical piece of concrete. No need to explain this is just bad, bad, bad. Here I completely agree, this kills.

    It's a pity that the majority VS 2005 demos is done with this sqldatasource. In the talks by Scott Gutthrie on Asp.net 2.0 I've seen he very quickly skims over datasources, uses a sqldatasource and briefly mentions the object datasource. I don't thinks it's his favorite subject. Setting up a sqldatasource is lightning fast. That's a flashy demo and it automagically demonstrates the database connectionstring  wizard, including a small "secure by default" show. A sqlExpress datasource can be quite OK for a site for some small business sites. But when the business gets big, involving DB updates, the site is toast. My advice is to stay as far away from the sqlDataSource as possible. But instead of giving up on all of VS RAD use the objectdatasource. 

    Setting up an objectdatasource in a demo does take a little more time. The wizard is not as flashy and has its idiosyncrasies. And it takes a lot of explaining to give the audience a clue of what is going on.

    But before diving a little into them I have to mention business logic in the UI; another hobby horse in RAD. Suppose your webform wants to validate a customers name. It would be tempting to do something like this:

    public partial class _Default : System.Web.UI.Page

    {

        protected void LinkButton1_Click(object sender, EventArgs e)

        {

            string myCustName = TextBoxCustName.Text;

            if (myCustName.IndexOf("73") > 0)

            {

                // Your stuff here

                TextBoxCustName.Text = myCustName;

            }

     

        }

    }

    Now what if this fancy 73 rule changes to 84 ? You have to check all screens where it is used. Which is a (maintenance) nightmare.

    An application has to be built in layers. A layer containing UI, a layer containing BL, and a layer containing DB interactions. When the layers get distributed over several processes or even machines they become tiers. For the latter to be possible every layer has to be in a separate assembly. The communication protocols between the assemblies may vary. That's a subject on itself, for the moment its sufficient to say that the things to be passed from one layer to the other should be serializable (over http) and that the communication should not be too "chatty". What I always do, in every project however small it may be, is draw the first border and add a class library to separate the non UI code from the UI.

    This library is an independent assembly, it can also be used in a webservice or a winform application.

    This library has a customer class to do the validation

    namespace DataLibrary

    {

        public class MyCustomer

        {

            public static string ValidName(string myCustName)

            {

                if (myCustName.IndexOf("73") > 0)

                {

                    // Your stuff here

                }

                return myCustName;

            }

        }

    }

    The website adds a reference to this class library (that's in the property pages of the site) and the codebehind of the web page delegates the validation to the lib.

    protected void LinkButton1_Click(object sender, EventArgs e)

    {

       TextBoxCustName.Text = DataLibrary.MyCustomer.ValidName(TextBoxCustName.Text);

    }

    The library is also going to contain customer classes for the objectdatasource to bind to. An objectdatasource completely abstracts the data away into any object and is not picky about the  class to instantiate objetcs from, by default the wizard just lists all classes which are decorated with the DataObject attribute. The runtime will accept any class. When reading or updating data the objectdatasource will fire specific methods on the object with specific parameter lists (or one object which holds all parameters). For a good designer interaction you should decorate the implementation with the DataObjectMethodType Attribute. The names of the methods invoked to read or write data, as well as the parameter lists sent are all configurable in the properties of the objectdatasource. Which requires quite some explanation when demoing the component. The bottom line is that everything is highly configurable but takes a lot of run-time checked trial and error to get right. Having automated tests for this makes a lot of sense.

    The DataSet 2.0 style is a quite handy class which can serve objects to feed to an objectdatasource, has all DataObject's attributes set, and does provide all the DataMethodType members. A dataset describes tabular data in an XSD schema and contains a tableadapter which wraps up the sql to interact with the actual database. An objectdatasource will list the datasets's tableadapters from the project and the projects referenced.

    You might object that these are several layers crammed together. Later on I'll come back on that, for the moment I want to demonstrate that these dataset do have a lot of power to get your data access and logic together.

    A dataset can contain more than one table. For each table there is a tableAdapter to bundle SQL queries to read and write from/to the database.

    The dataset has loads and loads of wizards which will guide you through the creation of the sql statements (including scalar queries) as well as the methods published. There is an enormous code file generated. Quite interesting to walk through but not the kind of stuff you would like to write by hand.

    The good thing is that a dataset can also include some business logic. Say you want something to happen every time a row is updated. In VB you can add this logic declarative to the dataset. (see this on MSDN for a deeper story)

    Partial Class CustomersDataTable

        Protected Sub UpdateTimeStamp(ByVal sender As Object, ByVal e As System.Data.DataTableNewRowEventArgs) Handles Me.CustomersRowChanged

            ' Your BL here, example below

        End Sub

    End Class

    Now every time something uses this dataset to update data your business rule is hit..

    This functionality cannot be added declarative in C#. It takes overriding the initialization code of the dataset. The eventhandler subscribing updates a comment field.

    partial class PakketenDataTable

    {

     

        public override void EndInit()

        {

            base.EndInit();

            this.RowChanged += new DataRowChangeEventHandler(PakketRowChanged);

        }

     

        private void PakketRowChanged(object sender, DataRowChangeEventArgs e)

        {

            PakketenRow dr = (PakketenRow)e.Row;

            if (e.Action == DataRowAction.Commit)

                if (!dr.IsOpmerkingenNull())

                    dr.Opmerkingen += string.Format("{0} :Row has changed", DateTime.Now);

        }

     

    }

    The nice thing in the C# version is that you can add multiple handlers to the event. A second handler for instance to send a message to someone or something. The VB handles keyword sets only one handler. (Read here for more background on handles vs +=)  To add multiple handlers in VB you have to take the C# route and override the init method as well. (Is this code available in VB ?)

    So a dataset can be directly used by an objectdatasource and has the possibilities to add a little business logic to your data. But, as I already mentioned, everything below the presentation layer is still one monolithical block. When your not happy with that there are several ways to continue:

    • Get something to get organized. The XSD schema editor may be nice but it is not a datamodeler.
    • Think SOA. Your layer should be able to exchange (xml) messages. A dataset has some very useful members available. Don't expose database stuff.
    • Slice up the whole thing into any number of custom layers/tiers you desire. As long as you implement the methods required by the objectdatasource in one of the layers you're fine.
    • An 3d party external OR-mapper. No need for objectdatasource support per se, as long as the tool supports 2 way data binding. That was all we were after.

    Which leads to the old dataset vs OR mappers rants. Another "yeah, but" discussion. When it comes to RAD tools I would just like to say: know what the tools do and know how to use them. Wizards are great but don't become the sorcerers apprentice.

  • That's security

    This popped up when signing on

    Good ! Just wish the previous versions of MS-anti-spyware had already checked for this. (Scan scheduled 2 at night. As I do have a life I am asleep. And so is my machine. Missed scan)

  • Including classic htm pages in an asp.net site (Look mom, no frames)

    At the moment I'm migrating my website. The old version is a bunch of static htm pages scribbled with FrontPage, the new version is an asp.net 2.0 site. As the old site is well read I don't want to break any links, a link to http://www.gekko-software.nl/DotNet/Art01.htm should keep serving the same "Delphi vs. C# article"  The easiest way would be to just copy the files and use IIS as a dumb "htm-file-server". But I want to have control over the pages; display them in a nice .net (master) page and add functionality as desired. An option could be to use frames, one frame for the aspx, one frame for the htm. But for many reasons I don't find frames very nice to work with. So here I'll present a pure .net solution.

    In the first step the handler of an htm request to the site (like http://www.gekko-software.nl/DotNet/Art01.htm) has to be set to asp.net. You do this in the configuration of the virtual directory in IIS. Add the htm extension in the application configuration list and set the executable to aspnet_isapi.dll.

    Now every incoming htm request for the virtual directory will be handled by asp.net.

    To intercept the request and redirect it to my viewer I install a so called HttpModule. An httpmodule is a way to be the first or the last in the handling of any request coming to the site. Installing a HttpModule is done in the web.config

    <system.web>

    <httpModules>
       <add name="UrlRewriter" type="Gekko.WebSite.URLrewriter"/>
    </httpModules>

    The module has a name and a type. This type is a class which implements the IHttpModule interface. It is in the app_code folder of the site.

    namespace Gekko.WebSite

    {

        public class URLrewriter : IHttpModule

        {

     

            #region IHttpModule Members

            public void Dispose()

            {

     

            }

     

            public void Init(HttpApplication context)

            {

                context.BeginRequest += new EventHandler(context_BeginRequest);

            }

            #endregion

     

            void context_BeginRequest(object sender, EventArgs e)

            {

                HttpApplication httpApp = sender as HttpApplication;

                string pageName = httpApp.Request.AppRelativeCurrentExecutionFilePath;

                if (pageName.EndsWith(".htm"))

                {

                    httpApp.Context.RewritePath(string.Format(@"~/ArticleViewer.aspx?article={0}", pageName.Substring(2)), false);

                }

            }

        }

    }

    IHttpModule is a nice lean interface. The init method is passed the full context of you web application. I add a handler to the beginrequest event. Which gives my code a first look at every request coming in and even the possibility to change the request. The method filters out any request for an htm and, using the Context.RewritePath method, rewrites the request url to that of my aspx page with the viewer. It passes the desired htm file in the querystring. Now all request for an htm will be served by my asp.net 2.0 code.

    (You can do a lot more with HttpModules. There are many events to hook into. The module is the first and the last one to handle, bend, modify or analyze all requests served by your app. There are loads and loads of good samples to be found all over the web)

    Now the viewer has to display the htm. How will it do that ? The easy part is that you can assign any html to the text property of a label. The result will be that the page rendered displays the htm in its full glory. But I want to be a neat citizen on the web and not render any garbage. The original htm of my pages has a lot of bla-bla Frontpage headers. What my code will do is extract the real content from the htm file and assign that to the label.

    An html response  (should) look(s) like this

    <html>
       <head>
          <title>This page is about software</title>
          .......
       </head>
       <body>
          .................
       </body>
    </html>

    The content is between the body tags.

    The code takes this appoach

    • Read the htm filename form the querystring
    • Read in the htm file into the rawHtml string.
    • Extract the page title using a regular expression
    • Assign the title to the viewerpage's title
    • Extract the page body by searching for the body tags
    • Assign the body to the text of a label

    private void displayArticle()

    {

        object o = Request.Params["article"];

        if (o != null)

        {

            string pageName = o.ToString();

            // read in the htm file

            string fullFileName = HttpContext.Current.Server.MapPath(o.ToString());

            StreamReader sr = null;

     

            try

            {

                sr = new StreamReader(fullFileName);

                string rawHtml = sr.ReadToEnd();

                // Use regex to extract title

                Regex reTitle = new Regex(@"<title\b[^>]*>(.*?)</title", RegexOptions.IgnoreCase & RegexOptions.Multiline);

                if (reTitle.Matches(rawHtml).Count > 0)

                    this.Title = reTitle.Matches(rawHtml)[0].Groups[1].Value;

                // Plain search to extract body

                int bodyStart = rawHtml.IndexOf("<body");

                if (bodyStart >= 0)

                {

                    // Find end of body tag

                    bodyStart = rawHtml.IndexOf(">", bodyStart);

                    int bodyEnd = rawHtml.IndexOf("</body", bodyStart);

                    if (bodyEnd < 0)

                        bodyEnd = rawHtml.Length;

                    LabelArticle.Text = rawHtml.Substring(bodyStart + 1, bodyEnd - bodyStart - 1);

                }

            }

            catch (Exception ex)

            {

                LabelArticle.Text = "Article not available";

            }

            finally

            {

                if (sr != null)

                    sr.Close();

            }

        }

    }

    For the code to build you need to include System.Text.RegularExpressions in the using list. A regular expression is a nice way to get the title, also when the tags are spelled poorly, like <tiTle  >. The Groups[1].Value member returns the title enclosed by the tags. It would be tempting to use a regular expression as well to get the body. But due to the many nested <'s and >'s inside the body that would be a pretty complicated one. And when you manage to figure out a working one there's quite a chance it literally will take ages to evaluate. Here I know there is (maximum) one pair of body tags, a linear search will be fast and good enough.

    <Update>
     In a comment James Curran writes down one regular expression which yields both results in one go. Which works like a charm and makes the code even simpler.

    private void displayArticle()

    {

        object o = Request.Params["article"];

        if (o != null)

        {

            string pageName = o.ToString();

            // read in the htm file

            string fullFileName = HttpContext.Current.Server.MapPath(o.ToString());

            StreamReader sr = null;

     

            try

            {

                sr = new StreamReader(fullFileName);

                string rawHtml = sr.ReadToEnd();

     

                // Use regex to extract title and body 

                Regex reHtml = new Regex(@"<title\b[^>]*>(?<Title>.*)</title\b[^>]*>.*<body>(?<Body>.*)</body>", RegexOptions.IgnoreCase | RegexOptions.Singleline);

                MatchCollection mc = reHtml.Matches(rawHtml);

                this.Title = mc[0].Groups["Title"].Value;

                LabelArticle.Text = mc[0].Groups["Body"].Value;

     

            }

            catch (Exception ex)

            {

                LabelArticle.Text = "Article not unavailable";

            }

            finally

            {

                if (sr != null)

                    sr.Close();

            }

        }

    }

    This was to good not to be included in the full story.
    </Update>

    The result is that all my classic pages are a full part of the asp.net 2.0 site and are still accessible by the classic url. The reader won't even notice

  • Developers vs. (?) ITpro's. SMTP and a website

    In a recent post I described how easy it was to turn your website into a spamming tool provided you know how to change some IIS settings. In a comment Dennis wrote "Some things are so simple, you'd expect everyone to know these things and use them wisely. Unfortunatly,."  Yes both coding and setup on itself are easy but the two parts are usually handled by different people. The developer is writing the code and the ITpro guy does the configuration. And these people have different cultures. Most of us developers are used to working with database connection strings like ".. user=sa;pwd=" and we are unpleasantly surprised by some service being refused. These days with  more and more systems being "secure by default" it's time we grow up and start displaying some real interest in configuration matters.

    The big hurdle to take is communication. Developers and IT pro's speak different languages. On the developers side the framework docs don't help, there are loads of samples, there is the SmtpPermission class but not a word on server configuration. No bridge to the world of ITpro. All you get is the exception which talks about relaying. And when you look up relay in the docs you'll end up in SOAPheaders documentation. That doesn't help either.

    The actual configuration work itself is becoming easier and easier. When it comes to sending mail I found this post by Scott Guthrie on the system.net part of the web.config file. An example

    </connectionStrings>

    <system.net>
        <mailSettings>
            <smtp from="me@spammer.net">
            <network host="localhost"/>
            </smtp>
        </mailSettings>
    </system.net>

    <system.web>

    These settings are used by all smtpclients in your app. Including things like the password-recovery control which send a user a lost password. My code example can now even be simpler

    private static void SendMailWithIIS(string subject, string body, string to)

    {

        MailMessage message = new MailMessage();

        message.To.Add(to);

        message.Subject = subject;

        message.Body = body;

        message.BodyEncoding = System.Text.Encoding.ASCII;

        message.IsBodyHtml = true;

        message.Priority = MailPriority.Normal;

     

        SmtpClient smtp = new SmtpClient();

        smtp.Send(message);

    }

    The app will be easier to maintain as well. The ITpro guy can jump straight to the system.net settings in the web.config. No need to ask which appsetting holds the name of the mailserver. One reason less to talk ? Which would be a pity. We developers have to learn to live and write software in a restricted world and have to learn how to setup a real world development machine. ITpro's can learn a lot from developers as well, but that's a different subject.

  • A new version of the Red-Gate SQL tools

    Red Gate has a lovely suite of tools to work with SQL databases. Their bundle has a SQL compare tools to compare the structure of a database as well as the content. The tools not only show the differences but also generate sql scripts to update structure or content. Previously I blogged on my experiences with SQL compare. A search for Red-Gate on CB will show that many of us have good experiences. The tools have really saved us loads and loads of work. The previous version works pretty well with SQL 2005. And now there is a whole new version out: SQL bundle 5.

    The first thing which meets the eye is the completely revised UI. The former was the only point which could use some polishing. Their new one is great:

    It still does have its idiosyncrasies. FI the way to close the interactive help is different but intuitive. But the amount and overview of the information is overwhelming and really pleases my widescreen.

    Download the trial at your own risk, it's addicting software :)

    Posted Apr 05 2006, 11:53 AM by pvanooijen with 4 comment(s)
    Filed under:
  • Using localhost as mailserver (5.7.1 Unable to relay for xxx)

    With .NET 2.0 writing code which uses the IIS webserver to send mail has become even more powerful. The System.Net.Mail namespace has some rich classes.

    private static void SendMailWithIIS(string subject, string body, string to)

    {

        MailMessage message = new MailMessage();

        message.From =  new MailAddress("Me@Spammer.net");

        message.To.Add(to);

        message.Subject = subject;

        message.Body = body;

        message.BodyEncoding = System.Text.Encoding.ASCII;

        message.IsBodyHtml = true;

        message.Priority = MailPriority.Normal;

     

        SmtpClient smtp = new SmtpClient("Localhost");

        smtp.Send(message);

    }

    The .NET docs even contain a sample to send mail asynchronous. The hard part lies not in the code but in the configuration of localhost. It considers itself being used as a mail relay and by default it does not allow anyone to do that. In your code you'll get the error message : Mailbox unavailable. The server response was: 5.7.1 Unable to relay for

    To fix it you have to configure relay restrictions in the IIS admin.

    Here I've set localhost, aka 127.0.0.1, as the only one allowed to relay mail. And now my .NET code can spam everybody. Use with care !

  • Project WSYP : how MS handles error feedback

    This really good video on how Microsoft handles user feedback on XP failures (the "Send / don't send error" dialog) was recently on a  Dutch Technet/MSDN briefing. And now SDN's top MS-basher Dick van Kooten has found a link. Thanks !!

    Enjoy. Clicking send will never be the same again.....

    Posted Apr 03 2006, 12:13 PM by pvanooijen with no comments
    Filed under:
More Posts

Our Sponsors

Free Tech Publications

This Blog

Syndication

News