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

Peter's Gekko

public Blog MyNotepad : Imho { }

April 2005 - Posts

  • Maxtor, network storage for the masses

    For quite some time I am a very content user of an external Maxtor USB drive. This week it was joined a Maxtor "shared storage drive". With a price of an euro a gigabyte I couldn't leave it on the shelf. The maxtor site, the documentation and the utilities were pretty vague. It's very easy to set up by the average nitwit, but when you're a geek you're on your own.

    The drive comes in a case which is somewhat longer than a regular USB drive. It has a 100 Mbs ethernet port and two USB connectors. The ethernet plugs directly in a switch (or accesspoint). Inside is a full windows network client, which will find a dhcp server and publish the drive on your LAN where it will appear if it was a complete PC.

    Management is done with a web interface. In name the pages are asp pages; I cannot look inside the box to see if there is a real IIS running. Web -based management includes

    • Assign the drive to a workgroup (in the figure it's part of my Gekko workgroup)
    • Manage users. The storage can only be accessed by users known to the device. The password of the user cannot be blank. This is the point where the client-utilities fall short; trying to add a user will fail quite often. What you have to do is add all users under their windows username with their windows password. Having done that the user will have access without the need to set up anything on the client.
    • Manage shared folders. Every user has his own storage invisible to the others. Besides that you can set up shared folders. The right to see, read or change these folders is set up on a per user base.
    • Add a printer. You can attach a printer to the USB port. After plugging in the device displays a network printer. Using it the first time requires installing the (Windows) printer driver.
    • Add external storage. You can also add another storage device to an USB port. Like another USB drive or a pen drive. The drive will be visible to all users as a shared folder.

    And that's it. Now I have a file and print server in my network and look: no PC...

     

  • Use a regular expression to lock up the webserver

    I am a rookie when it comes to regular expressions but learned one thing which I want to share with you. With a regular expression you can do very sophisticated matching of string patterns. The content of a regullar expression is a science on itself. The .net framework makes evaluating the expression quite simple.

    string Pat = MyRegularExpression;

    RegexOptions options = new RegexOptions();
    options |= RegexOptions.Singleline;

    Regex r = new Regex(Pat, options);
    Match m = r.Match(MyStringToSearch);

    if (m.Success)

    The Match method of the RegEx class will do the actual matching. What the documentation does not tell you is that it can take virtually forever to execute this statement. We had a beautifull expression which worked very well on a test string. Skimming the contents of a 396 KB text file went different. Starting the match drove the aspnet worker process (w3wp on server 2003) to 100 % processor utilization (51% on a (hypertreaded) dual) which locked up the server. We killed the process after half an hour. Nobody can wait that long.

    Browsing the net I found this post on MSDN which explained what was going on. Finally found a need for supercomputing@home.

  • Meet the experts

    The coming meeting of the Dutch user group DotNed is monday may 2nd. It will be a special one. Held in the new Microsoft Technology Center in Barneveld (You're not supposed to know that untill you have registered). Speakers will be Ronald Laeremans, Nikola Dudar, Ray Stephenson and Scott Currie from the MS C++ team and the topic will be VS 2005.

    To me, with my Delphi  background, C++ was allways that over complicated language which you couldn't avoid. Delphi could do all pointer manipulation and other dirty tricks without the need of *-es and the like. But all WinApi samples were in C++, a passive knowledge of C++ was a must. Now in the days of managed code I am curious how they will position C++. A refreshing topic.

    Barneveld is in the mid-eastern part if the Netherlands. It's also well reachable from many a part of Germany and Belgium. Free registration is here. See you there ?

  • How I got my VS 2005 beta 2 running

    Just as curious as everybody else I went for for the VS 2005 beta. Had to take some bumps to get it up and running, these are some things I learned:

    • You're not the only one trying to download it. Download speed varies dramatically. Starts at 400/500 K, soon drops to a fraction of that and eventually the stream will stop. In the MSDN downloader you can set the number of retries. By default this is 3 which is not enough to complete the download. You can change the number of retries while running, but this number won't be active untill you restart.
    • Virtual PC will not accept the downloaded ISO image.
    • Nero imagedrive can load the image but the setup fails on that virtual drive.
    • You can burn the image to a physical disk. Setup fails again
    • And again the Daemon tools virtual DVD drive (freeware !) works like a snap. The drive is recognized by Virtual PC as DVD drive. After this the install is flawless.

    And now I can start with the serious work. Provided the VS 2003 produduction project has some time to spare. I have to write tons of plumbing code which VS 2005 would generate for me on the fly. The future is bright...

  • Where to get your grid's data on the next roundtrip

     In a recent post I wrote some things on a datagrid and what to do over roundtrips. In a comment  John asked me what I did with the data over the roundtrips. He mentions 4 ways to store it. I always use the first one: a full reread from the DB on every roundtrip.

    This is my situation:

    • The data might be changed on the next roundtrip. Actions on the form itself may have caused the changes.
    • The bottleneck is the bandwidth. The page's viewstate has to remain as small as possible.

    The first point makes a database reread over roundtrips neccesary. In case only the second point applies it would be an alternative to store the data in the cache or session. Still I favor the database. My main reason is that a database server is designed / optimized for caching data and I don't have to reinvent the wheel. To be honest I never measured the difference with using the session or cache object. Given the updates in the DB I need a reread anyway. The apps behave well. The user load is not gigantic but a tiny box can serve all. At this moment I'm working on an application which will be under a greater stress. I hope (trust) the architecture will stand.

    My main point is that bandwidth is far more important than server load. It's not a big problem to scale up to a bigger database server or to plug in some Mb's to store the sessions. That's all under your control. Widening the user's bandwith is not.

    Having said this, I'm in for any other view. In 2005 it's a delight to see how you can configure caching right on the datasource itself.

  • Events in a datagrid, the page lifecycle and the viewstate

    When it comes to building web applications ASP.NET 2.0 will make life a lot easier. The key to success in building good web apps with ASP 1.x lies in understanding the page lifecycle. Which still has a lot of secrets and surprises. In this post I will investigate it once again and cover some of my new findings.

    The page life-cycle

    On each roundtrip a webform is loaded in IIS and the events on the page are fired. The sequence in which the events are fired is fixed. The handling of the page request has three stages, each of the stages has its own events. You can find most of them in the property window of the forms designer.

    These events are found not only on the webform itself but also on all the controls of the form.

    • In the first part the page is initialized. First the init event is fired. You can perform some initialization but its context (which contains things like the request parameters) is not avaliable yet. After this the page is loaded in IIS and the page-load event is fired. Now the context and all the controls are available. VS generates an empty event handler and advises you to write your initialization code here.

    private void Page_Load(object sender, System.EventArgs e)
    {
       // Put user code to initialize the page here
       // For the sake of simplicity the database code is put here :< In real life this should be somewhere else !!

       sqlConnection1.Open();
       sqlDataAdapter1.Fill(dataSet11);
       sqlConnection1.Close();
      this.DataBind();
    }

    • In the second part of the cycle events like button clicks and grid-link button clicks are handled. An eventhandler, like the click of an update button, could change underlying data allready being read in in the pageload. Now you have a problem.
    • In the third part of the cycle the page will render the HTML to the result which will be returned to the client. As a last resort you can hook into the pre-render event. In case your buttons update the data the prerender event is a better place to load the data

    private void WebForm1_PreRender(object sender, System.EventArgs e)
    {
       // For the sake of simplicity the database code is put here. In real life this should be somewhere else.
       sqlConnection1.Open();
       sqlDataAdapter1.Fill(dataSet11);
       sqlConnection1.Close();
       this.DataBind();
    }

    Any updates caused by your buttonclicks are now visible on the page.

    • After the prerender event the unload and dispose event are fired. As you page no longer has a context you cannot do anything with the pages content.

    A control which is not visible is not rendered. As a consequence the prerender event will not be fired on an invisible control. The page_load event is allways fired. If you put your dataloading code in the prerender event of the control consuming the data, your data will not be  read when it is not used. That’s another plus of the prerender event.

    The viewstate

    This scenario works as described when the viewstate is enabled, as it is by default. When you use a datagrid the viewstate can be quite huge. In case the grid’s data are read in again on every roundtrip it makes a lot of sense to disable the grid’s viewstate. This will higly reduce the amount of data travelling over the wire.
    Typical events in a datagrid are things like ItemCommand which fires whenever a linkbutton (with a commandname) in the grid is clicked. Like the select or Sort button. The SelecetedIndexChanged event will fire whenever a select button was clicked. Also when the SelectedIndex has not changed in value. These events fire in the middle part of the page, together with all the other button-clicks and the like.

    When you disable the viewstate the behaviour of the grid can change dramatically. In case the data is bound to the grid in the page_load, which happens before the grid’s events, the grid will behave the same. The events fire and even selectedindex has a usable value. But when you bind the data to the grid in the prerender event no events will fire at all and the SelectedIndexwill allways reads -1. Drilling down you will find that even OnBubbleEvent, which triggers the item events, does not fire. And there is nothing you can do about that.

    Roundup

    In an ideal situation I want the following

    • Disable the viewstate of the datagrid
    • Bind the data in the concluding part of the life cycle
    • Use the selectedindex property

    The last two points are in conflict. That’s why I started working on a custom datagrid with a custom implementation of the Selectedindex. Which works for the time being. ASP.NET 2.0 will bring relief: it generates all the plumbing code needed to get my data in and out of the page and introduces the controlstate which saves the essential state of the grid without the hog.

     

  • How to execute a SQL storedproc from an SqlCommand

    A database has a storedproc with some parameters. I don't know exactly what it does, I don't want to know, I don't have to know, it's not under my management. But my app does have a connection to it and has to call to stored proc. This is how it does that :

    SqlCommand berekenUrenverdeling = new SqlCommand("EXEC dbo.SP_STUDOND_URVRD_BEREKEN @AIDGEBRUIKER, @AIDURENVRD", sqlConnection1);

    berekenUrenverdeling.Parameters.Add("@AIDGEBRUIKER", idGebruiker);
    berekenUrenverdeling.Parameters.Add("@AIDURENVRD", idUrenvrd);

    berekenUrenverdeling.ExecuteNonQuery();

    I create a new sql command. The command text contains the name of the stored proc, dbo.SP_STUDOND_URVRD_BEREKEN, and the name of the two parameters, @AIDGEBRUIKER and @AIDURENVRD. Both parameters are added to the SqlCommands parameter collection as name value pairs. (In ADO.NET 2.0 the Add method has 3 parameters). ExecuteNonQuery fires off the proc. In case I'm interested it will return the number of rows affected.

    Nothing special at all, works like a charm and thanks to the parameters it's pretty safe against a sqlinjection attack.

    Posted Apr 15 2005, 08:19 AM by pvanooijen with 4 comment(s)
    Filed under:
  • VS Team System and the way to design applications

    Last thursday we had our Northern “MSDN-Technet” briefings. A day of sessions for developers and IT-pros, organized by MS and a good place to meet fellow developers. Some things had changed. The event used to be decorated with political hyper-correct banners bearing portraits of afro-asian-caucasian people in conversation. The new banners just bear the letters TechNet. In blue. In the the corner is MSDN. Also in blue and small. Mmmm. Also new was the raffle. The good thing about that was that is keeps people at the spot to see what they won and induces social interaction. Prizes included a ticket for TechEd and a smartphone. I won a workgroup edition of Operations Manager. Don’t know yet what I’m going to do with it, it’s in MSDN and so far I never felt like installing it. But winning something feels good.

    The highlight in the presentations was one on Team System by Arie Leeuwesteijn. Walking in I thought: “not again” but the talk very quickly evolved into a good discussion. Arie quickly gave an overview of the many parts of the product. Team System will come in three versions: Architect, Developer and Test. Most of the tools are found in several versions, the developer edition has the most. One of these is the class designer.

    This was (imho) the most interesting partof the discussion. An idea is to have the architect design the classes and their public interfaces after which the developer will write the implementation. The model of a class is the source-code itself. The only thing added by the editor is some graphical information how the diagram is drawn. So when a developer is coding (s)he is actullay working in the design itself. To me this is good. In one of my recent nightmares a huge pile of paper is thrown over the fence and I am supposed to turn that into a working system. Usually the paperwork needs improvement and after a short span of time the work done by the architect and the actual implementation are far out of sync. With team system coding can change the model. To lock the model in team system you have to use source-safe. Any project with more than one person working on it which does not use sourcesafe will lead to (at least) frustration. Rules should prevent checking in code (=design) you’re not allowed to change. I like this approach very much, usualy I am in the luck of being both architect and developer. Now I can work on both aspects of the app at the same moment. And when it comes to working with another person TS can really help. But it does require mutual trust.

    Designing an application requires more than drawing class diagrams. This is where the 3d party jumps in. For instance, Borland is working on Caliber a tool to manage system requirments. Borland and Delphi was another part of the discussion. Please, please give me a Object pascal add-in for Visual Studio. I should try Delphi 2005, but the IDE frightens me; the only thing I’m really interested in is the language.

  • sqlInjection attack on a LIKE query

    If SQL had known attributes I should have decorated my Like query with [AirCode]. Several comments questioned wheter and how it was vulnerable to a sql-injection attack. Well, the aircode version is. The original is harder to break.

    The vulnerable one :

    orgSql = "SELECT id, Info FROM Table1";
    sqlDataAdapterBuildSql.SelectCommand.CommandText = orgSql + (" WHERE Info LIKE '" + textBoxInput.Text + "%'");

    Guess what happens when the user types this in the textbox

    e'  drop table table2 --

    Yes, table2 is gone. Provided your app has adminstrator rights on the database. A lot off apps do.

    The other one, as seen in "Writing Secure Code":

    sqlDataAdapterUseParameter.SelectCommand = "SELECT id, Info FROM Table1 WHERE (Info LIKE @param1)"
    sqlDataAdapterUseParameter.SelectCommand.Parameters["@Param1"].Value = string.Format("{0}%", textBoxInput.Text);

    When the malicious user now tries to inject sql via the textbox the only result will be that the database is queried for e'  drop table table2 -- A large resultset is not that likely .

  • SELECT LIKE %

    Trying to be smart I ran into this. In an app the user is looking for some person, the query has some parameters to help her.

    SELECT Naam, Afkorting FROM  dbo.Persoon WHERE (Naam LIKE @Param1) AND (Functie LIKE @Param2)

    To the parameter values is appended the % character The query will return all rows which start with the value supplied.

    PersoneelZoeken.SelectCommand.Parameters["@Param2"].Value = string.Format("{0}%", paramvalue);

    The catch is what happens when an empty parameter is passed in. Which will result in a query which looks like

    SELECT Naam, Afkorting FROM  dbo.Persoon WHERE (Naam LIKE '%') AND (Functie LIKE '%')

    At first sight the query will return all rows. It does not. It will return al rows which do contain a value for the Naam and the Functie column. % matches any text but does not match a dbNull value. Makes sense. But was a catch.

     

    Posted Apr 08 2005, 02:19 AM by pvanooijen with 7 comment(s)
    Filed under:
  • Objects to feed an objectdatasource

    I had to miss the codeworse april fools joke. Spent the day doing my presentation on objectdatasources with VS 2005. On beforehand my main concern was setting up the hardware. Had to run VS 2005 from an external hard disk in 300Mb of memory. The sql server was running on another notebook. All was tied together with my old, but o so reliable Zyxel hub-accesspoint. Within 10 minutes I had to connect all cables, wake up the machines and get the network connected. Which went without a glitch. At the end of the session we had a VS 2005 solution containing a classlibrary, a web service and a web site up and running with debugging. All with the 300 megs of virtual PC RAM. Good job VS 2005 !

    In a previous post I had introduced custom objects for an object datasource. To recapitulate: an object datasource expects an object which has methods to read, update, insert or delete data. The consumer of the datasource will invoke these methods. A typical consumer would be a gridview, by setting some properties on the grid you can browse and update (database) data without the need to write plumbing code. A TableAdapter in a dataset (2.0 style) fullfills this by default. In my example the object  fed to the datasource invoked a webservice to interchange data. The webserservice wrapped up the tableadapter and gives the opportunity to split my app’s layers into tiers.

    [System.ComponentModel.DataObject]
    public class BOwrapper
    {

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Update)]
        public virtual int UpdateInvoice(DateTime InvoiceDate, int InvoiceNumber, int idCustomer, string Description, int Original_idInvoice)
        {
            DataHost.Service ws = new DataHost.Service();
            ws.UpdateInvoice(InvoiceDate, InvoiceNumber, idCustomer, Description, Original_idInvoice);
            return 1;
        }

    // And so on…

    During last friday’s presentation we had great fun feeding the datasource all kinds of objects. In the previous post I mentioned the  System.ComponentModel.DataObject attribute. This is used by VS but is not required at all, uncheking the checkbox will display all (referenced) classes found in the project. For instance you can feed the proxy of a webservice directly to an objectdatasource.

    When a method on the datasource’s object is invoked it is sent a load of parameters. Reflection will query the object for a method with the specific name and a list of parameters with the specific names. When no method whose parameter names match is found an exception is thrown. Both method name and parameterlist can be set in the property window of the objectdatasource

    Which parameters have to be sent to the object will vary. In a grid you will normally only edit a few columns. From a detailsview, which can also work with an objectdatsource, the number of updated fields and thus the number of parameters to the method will be larger. Both object-datasources can use the same class for their objects as long as the object has an overload for every number of parameters required. The webservice will do the actual update but you cannot overload the webmethods. A more flexible alternative is to give the webservice one update method which takes a datatable as parameter. For the table to be serializable VS will wrap it up in a dataset.

        [WebMethod]
        public int UpdateInvoice(DataSetInvoices.InvoicesDataTable invoice)
        {
            InvoicesTableAdapter ta = new InvoicesTableAdapter();
            return ta.Update(invoice);
        }

        [WebMethod]
        public DataSetInvoices.InvoicesDataTable Invoice(int id)
        {
            InvoicesTableAdapter ta = new InvoicesTableAdapter();
            return ta.GetDataById(id);
        }
     

    The overloaded update methods of the bussinessobject all use this webmethod. As they have to return a full row of data they first have to read in the original row, update the columns passed in and return the full row.

       [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Update)]
        public virtual int UpdateInvoice(DateTime invoiceDate, int invoiceNumber, int idCustomer, string description, int original_idInvoice)
        {
            Service ws = new Service();
            DataSetInvoices.InvoicesDataTable it = ws.Invoice(original_idInvoice);
            it[0].InvoiceDate = invoiceDate;
            it[0].InvoiceNumber = invoiceNumber;
            it[0].idCustomer = idCustomer;
            it[0].Description = description;
            return ws.UpdateInvoice(it);

        }

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Update)]
        public virtual int UpdateInvoice(int InvoiceNumber, int Original_idInvoice)
        {
            Service ws = new Service();
            DataSetInvoices.InvoicesDataTable it = ws.Invoice(Original_idInvoice);
            it[0].InvoiceNumber = InvoiceNumber;
            return ws.UpdateInvoice(it);
        }

    This does increase overhead. Instead of one invocation of a webmethod passing just a couple of values we now have two invocations which send a complete dataset to and from the consumer. .NET 2.0 has two options to reduce the traffic. The beta-1 includes the option for a dataset to serialize itselef in a binary format, which is not that usefull on a webservice but quite usefull when you use remoting as RPC protocol. For the next beta it is announced that there is the option to leave out the dataset’s schema from the dataset when serializing it. Another optimization would be to delete the return type from the update web-methods. With WSE or Indigo the method invocation can than be one way, the update is sent to the service, response not needed.

    This took me a lot of guessing, trial and error. The goal was to to build a webapp without having to write the plumbing code and without getting stuck with an app without layers or whose layers could not be split into tiers. All the online documentation mainly tlaks about SOA and team system but does not come with that much examples of real code. Beta 2 will have a lot of new things, I’m ready to give that a new look.

     

  • Code worst

    You think codebetter was good last friday ? Julia Lerman is just hilarious .
    Posted Apr 05 2005, 08:02 AM by pvanooijen with no comments
    Filed under:
More Posts