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

Peter's Gekko

public Blog MyNotepad : Imho { }

March 2005 - Posts

  • A blog (post) is never finished, just published

    Clicking the post button throws your blogpost into the outer world. Is it finished ? No, quite often it's content need a little update. I find myself updating posts all the time. Because I give a person a wrong name. It was Robert Stoppels who built the aquariumpc exhibited on the CeBit. (post is updated). An error glitched into the sample code needs an update. And when reading back the text has become to abstract adding a screenshot highly clarifies matters.

    The problem is that the original post has been collected by many a news agregator comming by. To see the update the reader has to revist your blog. I see no solution to that.

  • Custom bussiness objects for ASP.NET 2.0 object datasources

    In ASP.NET 2.0 the gridview control is quite nice. By just setting some properties you can create a web application whose grid data can be edited by the end-user without the need to write all the plumbing code by hand. Which is quite a big step forward from 1.x. For this to work the gridview communciates with the data through a datasource. Most of these datasources, like the sqlDatasource, communicate directly with the database. Having them on your webform leads to monolithic webapps.

    The way to layer an app is using an objectdatasource. In this article on the SDN site (you have to register to read the article. registration is free) I explored a way to use an ASP.NET dataset 2.0 style as bussinessobject. The story manages to separate the database access from the web-forms into two separate dll’s. Two layers, to turn these into tiers you need a RPC protocol for them to communicate over machine boundaries. For the SDN user group I’ll be doing a presentation on objectdatasources april 1st (no joke) to continue with this part of the story. Here some first shots at the subject.

    The properties of the 2.0 dataset suggest a role for webservices; all those diagrams in team system suggest that as well. But browsing and googling around leave the subject quite misty. The “generate webmethods” option in the dataset will not make it into the final version. I havn’t seen beta2 yet, for the time being it will take some custom work. As a demo a webservice to wrap up functionality of the dataset. This webservice will expose some of the methods needed by the datasource. (The dataset used is described in the article.)

    [WebServiceBinding(ConformanceClaims=WsiClaims.BP10,EmitConformanceClaims = true)]
    public class Service : System.Web.Services.WebService {

        [WebMethod]
        public DataSetInvoices InvoiceList()
        {
            DataSetInvoices ds = new DataSetInvoices();
            InvoicesTableAdapter ta = new InvoicesTableAdapter();
            ta.FillList(ds);
            return ds;
        }

        [WebMethod]
        public void UpdateInvoice(System.DateTime InvoiceDate, int InvoiceNumber, int idCustomer, string Description, int Original_idInvoice)
        {
            InvoicesTableAdapter ta = new InvoicesTableAdapter();
            ta.Update(InvoiceDate, InvoiceNumber, idCustomer, Description, Original_idInvoice);
        }

    }

    The objectdatasource does not really work with a full dataset but with it’s tableadapaters. A dataset is fully SOAP-serializable, a tableadapater is not. You can try to make the webservice return a tableadapter, the result will be that all the VS2005 auto-magic will wrap the adapter up in a dataset nevertheless.

    The original plan might have been to have the objectdatasource directly consume the webservice. For now we need a simple wrapper class which interacts with the webservice and exposes the functionality in the format the objectdatasource wants. The object datasource property builder lists classes available to provide the bussiness object.

    It will look for classes decorated with the System.ComponentModel.DataObject attribute. The datasource looks for methods on the dataobject to retreive, update, insert or delete data. The property builder will look for methods decorated with the System.ComponentModel.DataObjectMethod attribute. The constructor of this attribute takes a member of the System.ComponentModel.DataObjectMethodType enumeration as parameter. There is a Select, Fill, Update, Insert and Delete member.

    The objectdatasource looks for a matching method on the bussiness-object. Runtime it will look for a method whose parameter names match the parameters to be sent to the method. The names of the parameter have to match exactly, the casing of these names does not have to match. When Reflection finds no match an exception is thrown. The error message tell you what parameter names are expected. 

    The type of the parameters is not checked. When invoking the method the objectdatasource will try to convert the parameters to the desired type, when this is not possible an execption is thrown. The callstack of the exception clearly shows the attempt Reflection has made.

    In the gridview on the invoices the date, number, customer id and description columns can be edited. An object of this class can serve as a datasource:

    [System.ComponentModel.DataObject]
    public class BOwrapper
    {

        [System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
        public DataHost.DataSetInvoices.InvoicesDataTable InvoicesByName()
        {
            DataHost.Service ws = new DataHost.Service();
            DataHost.DataSetInvoices ds = ws.InvoiceList();
            return ds.Invoices;
        }

        [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;
        }

    }

    The BOwrapper class exposes methods which the objectdatasource (and the gridview using that) understands. In the implementation of the mehods it does invoke the webservice. In this example it is a straightforward synchronous invocation. It’s up to you to attach any bell or horn you wish. Or implement another RPC protocol, instead of getting to the bussiness object via a webservice you might want to use remoting.

    The result is that I have these layers

    • Webbrowser
    • Webform with objectdatasource
    • BOwrapper (can have its own dll)
    • Webservice
    • Database

    There are several ways to slice these layers into several physical tiers. And I still have fully updatable data in the browser without having to code my own plumbing. That’s something I really want to leave behind in 1.1.

     

  • Using the viewstate in a control whose viewstate is disabled (you need a page base class)

    The Datagrid is a lovely control when you need a web page whose layout has to adapt to a a huge variety of browsers. Just set the width of the grid to 100% and the grid's layout will scale quite well. When it comes to the page (response) size the datagrid is not that nice. The grid's viewstate will swallow a lot of bandwidth. In my case the size of a page with a grid went from 50k to 150k by just setting the grid's EnableviewSate property to true (which is the default). Most of the information in that viewstate is not needed at all. The data in the grid is dynamic, it is reread from a database on every roundtrip.

    By switching off the grid's viewstate you do lose a little more than intended. A lot of events no longer fire. OnBubbleEvent (which fires when a control in a template has posted back), OnItemCommand (which fires when a linkbutton in the grid has posted back) and the specific command events like SelectCommand, SortCommand and the events dependending on these, like SelectedIndexChanged, no longer fire (on my .net server, some people report different). Using a little hack you can alwyas find out what kind of event posted back.

    Some properties in the viewstate are hard to live without. To select an individual row you do need SelectedIndex. In ASP.NET 2.0 the essential properties have moved from the viewstate to the controlstate, in 1.x you have to do your own bookkeeping. The SelectedIndex cannot be preserved over roundtrips in the grids's viewstate but it can be stored in the viewstate of the page which owns the grid.

    Storing and retreiving something in the viewsate is pretty easy:

    const string myViewStateItemName = "_myViewStateItemName";
    protected int myViewStateItem
    {
       get
       {
          object o = this.ViewState[myViewStateItemName];
          if (o == null)
             return -1;
          else
             return (int) o;
       }
       set
       {
          this.ViewState[myViewStateItemName] = value;
       }
    }

    The viewstate is a name- value collection, the items are identified by a string. To make shure I use the same name when setting and getting the item that name is a constant. All values are stored as an object, it takes some casting to get the right type and some default value when the items wasn’t found (yet). Now the page has an integer property myViewStateItem.

    Page is a property of a web-control, the grid can reach the page from code. I have created a custom datagrid which inherits from the DataGrid. A first attempt to store the selectedindex might look like this:

    public class IndatoDataGrid : System.Web.UI.WebControls.DataGrid
    {
      const string myViewStateItemName = "_myViewStateItemName";
       public
    override int SelectedIndex
       {
       get
       {

          object o = this.Page.ViewState[myViewStateItemName];
          if (o == null)
             return -1;
          else
             return (int) o;

       }
       set
       {
          this.Page.ViewState[myViewStateItemName] = value;
       }
    }

    There are two things wrong with that

    • The ViewState property has a proptected visibility and is not available here
    • When two of these grids co-exist on one page they will both store their property in the same viewstate member

    This is where the page base class comes in. You do not need a visual page, just add a class to your project which inherits from System.Web.UI.Page.

    public class BasePage : System.Web.UI.Page
    {
       public int GetViewStateInt(string name)
       {
          object o = this.ViewState[name];
          if (o == null)
             return -1;
          else
             return (int) o;
       }

       public void SetViewStateInt(string name, int value)
       {
          this.ViewState[name] = value;
       }

    }

    The class exposes two methods which store and reterieve an integer value to and from the page’s viewstate. Any webform can inherit from this class.

    ///
    ///
    Summary description for StudieOnderdeel.
    ///
     
    // <Update> this code has been slightly updated since the original </update>

    public class StudieOnderdeel : BaseWebForm
    {
       protected System.Web.UI.WebControls.Panel Panel1;
       // Etcetera 

    Generating an unique name for the value is done in the code of the grid

    public class IndatoDataGrid : System.Web.UI.WebControls.DataGrid
    {
       private int GetInt(string name)
       {
          BasePage bp = this.Page as BasePage;
          if (bp != null)
              return bp.GetViewStateInt(VSname(name));
          else
             return -1;
       }

       private void SetInt(string name, int value)
       {
          BasePage bp = this.Page as BasePage;
          if (bp != null)
             bp.SetViewStateInt(VSname(name), value);
       }

       private string VSname(string varName)
       {
          return string.Format("{0}{1}", this.ID, varName);
       }

       const string myViewStateItemName = "_mySelectedIndexame";
       public override int SelectedIndex
       {
       get
       {
          return GetInt(VSname(myViewStateItemName));
       }
       set
       {
          SetInt(
    VSname(myViewStateItemName), value);
       }
    }

    The grid has two methods, GetInt and SetInt. These cast the grid’s Page to a BasePage and use the BasePage’s methods to get the value in and out of the viewstate. The name of the viewstate member is composed by the VSname method, which combines the ID of the grid itself with the name passed. The combination will be unique on the page. The overridden SelectedIndex property uses these to preserve the selectedindex over roundtrips.

    Now I have a datagrid which does preserve its SelectedIndex over roundtrips without a dramatic increase of viewstate size. 

  • Dogfood and taxes

    The 1st of april is near. In the Netherlands this is the last date to submit your tax-form. As I’m my own boss this does take quite a lot of bookkeeping. In contrary to most other self-employed people I know I am doing this all by myself.  An external guy could possible find some interesting tax-hole to save me some money (to be spend on him) but working through all paperwork and spreadsheets myself does give me a feeling of the kind of work some of my customers are doing day to day. I do my bookkepping with my own (Clipper !) application. So its premium dogfood.

  • web.config and dbconnectionstrings

    In an asp.net app the web.config has an ideal place to store app settings like email-response adresses or database connection-strings. In the appsettings section you can stash any string you want.

    <appSettings>
       <add key="dbConnectionString" value="workstation id=FARLOWELLA;user id=ThatsMe;data source=phelsuma;persist security info=False;initial catalog=Indato;pwd=MyOhSoSecretPassword"></add>
       <add key="StyleSheet" value="StyleSheetIndato.css"></add>
       <!-- Directory to create and delete temporary files. ASP.NET requires fieldcreate and filedelete rights ! -->
       <add key="TempDir" value="c:\temp\"></add>
    </appSettings>

    Clear language for a system administrator. When IIS loads the application the web.config file is parsed. Now all settings are available in your code.

    public static void openConnection(SqlConnection cn, string settingName)

    {
       cn.ConnectionString = System.Configuration.ConfigurationSettings.AppSettings[”dbConnectionString”];

    That’s cool. If the system administrator wants to change the database used he edits the web.config. But if the application is still running, the web.config has allready been parsed. When the timestamp of the web.config is updated IIS will restart your application. (In the code the application_start event of global.asx fires)

    Doing application maintenace by editing a configuration file is easy but exposing the settings as plain text in that file has a security risk. To view web.config you need network or local access to the server. IIS labels a “*.config” application mapping as forbidden. By default no web client can view it. But this setting can be changed in the IIS administrator. As a last hurdle you can encrypt the contents of web-config. Check here for an OnDotNet story on encrypting connectionstrings in 2.0.

    The dbconnectionstrings are an almost classical example of what to do with web.config. It is a pitty the content of most of the dbconnectionstrings is far less secure than possible. Allmost all contain a user name, password combination. An application is running under the asp.net account. This is a pretty restricted account, the many priviliges the connectionstring-user has are far to powerfull for the job. They migth even prove dangerous when the user (unintentionally) does something bad. Consider the effects of a sql injection attack. The application does not need the right to drop databases.

    Instead of using user based security you can use integerated security (Old dnj story on this). Then you assign the db rights straight to the asp.net account itself. This will result in a connectionstring like 

    data source=BROCHIS;initial catalog=DNJ;integrated security=SSPI;

    This is far less informative to evil eyes than the one with the password of the system adminstrator. 

  • CeBit : technology, entertainment and social networking

    Going to the Cebit ICT trade fair was a day well spent. Visited the show on a trip organized by Groniningen ICT  with ICT people from my part of the country. Hannover is a 4 hour bus ride which flies away with good company. The fair itself is an ocean. The amount Far Eastern producers of blue-tooth headsets is enough to mute every further sense of imagination. The Microsoft developers boot exhibited Visual Studio 2005, but don’t expect a lot of fancy tools on the rest of the show. After all it is a trade fair. When you’re looking for 10.000 custom set top boxes, available within 3 months, it’s the place to be. When you’re just a geek go for the hardware..

    Tablet PC

    Hosted by the Microsoft boot was the tablet store. They had a line up of a diversity of tablet PC from different brands. The place to compare. The big difference between the tablets is the screen. My Acer is a marvel but is absolutely not usable outside. Some others, especially the almost legendary Motion, literally shine out. At quite diverse places Tablets could be seen in action. Microsoft used them to serve potential MCE customers a game. The fair organization (or its secret service) used them to do something interesting as well. Regularly you would see someone carrying a tablet as if she was selling cigarettes or popcorn. Tapping all the time. I guess it was collecting data in the field but did not dare to ask.

    A complete hall was reserved for “displays, flat panels and CRTs”. Gigantic TV screens dominate the hall. Only flat-screens. The same for monitors, the only CRT’s I have seen on the whole fair were stashed on the bottom shelf of a 13 in an aisle easter Asian trade company. Those could even have been mockups, the screen was covered with a sticker. They will build anything over there. What was in the display hall were tablets PC’s. After all a tablet is a display with a PC inside. Some guys from mktec demonstrated tablets with (also) custom bussiness apps amidst the 96” butterflies.

    Other PC hardware

    There was a lot to see on computer parts and computer modding. Silent PC’s are hot. The variety in fans is overwhelming. Most amusing was a  “cooler-something” boot trying to demonstrate the quietness of their fans while the neighbor boot did home theater's with a sound level that would even mask a hairdryer. The best was the modding contest. Voting #10 is for Robert Stoppels, a Dutchman who built the aquarium PC

    The Coolest water cooled PC ever

    A personal draw of products seen :

    As a former entomologist I liked Ants. The boot had a game where you drive a cart with a steering wheel held in air. Tilting the wheel pushes the throttle, twisting steers. Worked. The wheel communicated with the computer using Ants. Ant, “the power of less”, is a system of very small transmitter, receiver or transceiver chips with a claimed power consumption in the order of micro-watt's. Some Ant devices only send, like the steering wheel. Others only read. With a transceiver you communicate bi-directional. Ants are very basic building blocks which communicate with your software over a serial interface. Haven't seen the API, but the specs are in messages per second. Sounds OK, all I have to do now is dream of a James Bond project.

    Walked into RetSoft, KISS document management software from Groningen. Serious stuff. They are looking for resellers.

    Quite hi-tech was Eleksen.Out of pressure sensitive conducting wire they weave cloths which make a fabric digitizer. The threads pick up where the cloth is tapped and how hard this is done. Ideal for a keyboard. At Fabrickeyboard you can find a diversity of rollable, washable but comfortable (I did try !) keyboards. As it is a woven digitizer and not a set of buttons you can print anything on the cloth and map the area’s on the fabric to specific keys. A prototype at the boot was a tablet bag. It was designed for young children, an age that doesn’t hold a pen yet, using a high variety of  keyboards. When they are young a few large keys will do, when they grow older more and smaller keys are needed. Switching keyboard is a matter of changing the digitizers cover. (And updating the driver (settings)) At the Elkensen web site are loads and loads of other ideas what you can do with this stuff. Like it, it literally feels good.

    Home

    Quite exhausted I returned to the bus. The ride home was great, all tired but content. It was a great day !

  • CeBit

    To finish a week of total chaos I'll be visiting the CeBit trade show. One of the largest ICT shows in the world, being held in Hannover, just around the corner from where I live. The ICT platform Groningen has organized a bus trip and I'll be a happy participant. We are going to meet our collegues at the other side of the border and have the opporunity to see what's new in general. I'll be specifically tracking for Tablet PC stuff. According to Gaston (Dutch), who skimmed  the catalogue, there was not that much. But let's find out what's really scribbling.

    Anybody got any specific recommendations for other things see there ?

  • Bad service redefined : here comes VIANETWORKS

    I thought it would be nice to have a small on-line asp.net site to demonstrate and try things. Saw an adverstisement in (Dutch) Microsoft .NET magazine of a  vianetworks offering and took the jump. Quite cheap so I didn't expect that much. Reallity was something fit to be sent straigh to WTF. I'll tell you some off my experiences so you'll be warned and can stay far away from them.
    Vianetworks offered a developers site for euro 1.99 (ex VAT) a month with 3 months for free. I ordered two sites. When it came to paying all my alarm bells should have gone off as my credit card number went over an unsecured connection. I must have been blinded by greed.
    One site went up and it did work. Pretty fast but the only thing it serves are asp(x) pages in your root folder. Subfolders are shielded off and serving a dll over http (to embed aWindows user control in IE) is blocked as well. The latter is no problem for the Unix box of my real provider. You have some mailboxes and a sql database. Not too good, not to bad.

    The other site didn't come up and I got in touch with Vianetworks support. Support comes in three flavors:
    • Not possible here (serve a dll)
    • Hilarious bullshit. (I complained about my domain not being published, as a response I got a WhoIs dump, the site did not exist)
    • No response at all, all attempts to follow up on 1 or 2 take this path
    They have an (expensive)  phone support line. You can leave a message and they will call you. They don't. A phone call to the main office brings you to someone who happens to be out for the moment but will call you. He doesn't. What else can you do ? Write a blogpost. As a final check I checked the URL. And to my surprise it is there now ! Well that saves me from calling them frauds but I will not do bussiness with these people ever again. What a lousy mess.

  • Quiet please

    A computer can be noisy, most of the average desktops are not that far from a vacuum cleaner sitting on your desk. The main reason for the noise are the fans to get away all the heat generated. As Trubadour demonstrated this heat is enough to fry an egg  (I found this first through Sahil). When you take a closer look the pictures you can see that machine is water cooled. At first thought this PC would be abolutely silent, having no fan. But the pump needed to pump the water around makes some noise as well, having had loads of aquaria I know that can be pretty bad, especially when the valves start leaking. Fritz Onion went back to (silent) fans having found suspicious green moist in his machine. I silenced my Hoover by replacing power supply, CPU fan and graphics fan. A hell of a difference.

    But still I am not content. Now the PC’s noise melts away in the background I start hearing new things. The electronics in a flat panel can emit quite a lot of irritating noises. Afaik they contain high frequency oscilators which vibrate. Very irritating. Classic CRT’s, especially TV’s, can be bad as well. The cathode ray tube emits a tone which the audio cannot mask. So what’s next in tweaking land ? Silent fans do work and are great fun to install, I’ll be the first one to try an HF silencer. Don’t know yet what they’ll look like.

    But it is an arms race lost in advance. Switch off your PC and you will hear squeeking lightbulbs and hissing heating pipes. I wish I could play some music while working. To me it’s one or the other. As its looking now I’ll end up in a monastry where the only disturbing sound will be my pen scratching the perkament. With integerated digitizer :)

  • Great (Lego) game (but not in Firefox)

    If you(r kids) like Lego and puzzles Junkbot, an on-line game, (and version 1) is a killer. My kids are absolutely addicted. The game is implemented as a Flash plugin and normally works without a glitch. Today Cas tried it in my ofiice, running Firefox. It took him just 8 levels to crash Firefox. Good thing : view in IE.
    Posted Mar 06 2005, 12:01 PM by pvanooijen with no comments
    Filed under:
  • Sorting in a datagrid without using the viewstate

    The datagrid has an option to sort the grid on a column. Every column in the grid has has SortExpression property. When you click the column header the SortCommand event is fired. In the parameters of that event you can get the SortExpression of the column whose header was clicked.

    That’s very nice but the moment you disable the grid’s viewstate the event no longer fires. The viewstate of a datagrid gets very big, it’s something you want to keep disabled. But the sorting option is nice. I found the folowing workaround.

    When the page posts back it is not a great problem to find out which control caused the postback. The names of the sortlinkbuttons all begin with the name of the datagrid. The second part of the name is the grid’s header and part of the third name is the column. So you can check (in page_prerender,or page_load) if and which column was clicked

    // In case of column header click
    // Request.Form["__EVENTTARGET"] will look like "DataGrid1:_ctl1:_ctl3"

    char[] splitters = {':'};
    string[] pbCtrl = Request.Form["__EVENTTARGET"].Split(splitters);

    if (pbCtrl[0] == DataGrid1.ID)
    {
        // Column ID's is 1-based !
        int columnClicked = int.Parse(pbCtrl[2].Substring(4)) + 1;
        sortOrder = DataGrid1.Columns[columnClicked].SortExpression;
    }

    The SortExpression is not in the viewstate and fully available.

    It is a hack. But works like a charm.

More Posts

Our Sponsors

Free Tech Publications

This Blog

Syndication

News