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

Peter's Gekko

public Blog MyNotepad : Imho { }

January 2008 - Posts

  • How to set the UI culture of an ASP.NET page from code

    The globalization of an asp.net web site is not that difficult. When rendering a page the language preferences of the visiting browser are used. When the resources are set up correctly the translations are read from the corresponding resource. The browsers language preference is also used by the code behind. Also the result of this snippet

    Label10.Text = DateTime.Now.ToLongDateString();

    depends on the browser settings.

    But you can also set the language in which to render the page from code. How to do this can be found on MSDN but (as usual..) that example is not clear because it (again..) tries to demonstrate several things at the same time and doing that it skips a major point.

    To set the culture from code you have to override the InitializeCulture method of the (base) Page. In my snippet the language is set by an (optional) parameter in the url.

    protected override void InitializeCulture()

    {

        const string nlCulture = "nl-NL";

        const string enCulture = "en-GB";

        string rqCulture = Request.Params["nl"];

     

        if (!string.IsNullOrEmpty(rqCulture))

        {

            switch (rqCulture)

            {

                case "0":

                    UICulture = enCulture;

                    Culture = enCulture;

                    break;

                case "1":

                    UICulture = nlCulture;

                    Culture = nlCulture;

                    break;

            }

        }

        base.InitializeCulture();

    }

     

    When a "1" is passed the page is rendered in Dutch, using the Dutch resource files. When a "0" is passed the page is rendered in British.

    You have to set two properties of the page: UICulture and Culture. To what kind of a value is a mystery in the MSDN example. Over there it is set to the selected value in a listbox. What kind of value that it is beyond the scope of the example. It was even harder to guess because reading the property in the debugger (it is hard to write a test on a live HTTP Context) displays long descriptions, not the short en-GB kind of thing. For an overview of all cultures available check the documentation on the CultureInfo class. In case you use any other value than the ones listed there your code will hit an exception.

    Another small puzzle is why you have to set two properties. The UICulture is used to select the right resource file. The running thread, which runs the code behind also has a culture, this is the other Culture property. In case you would not set this property the snippet with the ToLongDateTimeString would still lead to a string in the culture of the browsers preferences.

    That's all there is to it.

  • Upgrading an ASP.NET 1.1 app to 2.0

    We have this big application known as the app with the sprocs, it has been a source for quite a lot of blog fodder already. The app has a long history; it originally started as a classical 2-tier Client Server application. A Delphi frontend running against a sql server backend. A lot of the business logic was (and still is) in stored procedures. My first shot was converting it to a web application. Armed with Visual Studio 2003 and sql reporting services we got it up and running. Originally intended to bridge a couple of years till the "big centralized app to cover all needs" was going to take over. As usual such an information system never gets further than the meeting table our app will live for many more years and will require quite a lot more updates.

    The main emerging problem was that's it's still based on ASP.NET 1.1. The newer versions of the .net framework have a lot of nice new things to offer; especially asp.net is so much better than 1.1. But my main problem with 1.1. is the tooling. As you might remember the web page editor in VS 2003 is a nightmare. There is Resharper and nunit for VS 2003 but Resharper completely pales compared to the 2005 version. So it would be great to convert the app to ASP.NET 2.0 before doing the next update. When VS 2005 came out I had done a test conversion. Which just didn't work. We decided to give it another shot. The goal was to move to asp.net 2.0 (moving from 2.0 to later version is no big deal) and do a full Resharper code review.

    In the end it all worked out, now everything reads green. In the process I met several small glitches worth mentioning

    Components and Datasets

    The database is wrapped up in an assembly. Database access is done using loads and loads of TableAdapters grouped on Components and data is published in typed datasets. All very much 1.1 style, in the days I built it that was a quite logical sequel to the Delphi datamodules. With a far better implementation. Converting this assembly to 2.0 went without any problems. Resharper helped me to tidy up the code and fixing some obsolete methods.

    But now new functionality will be based on plain domain objects and I am going to leave the actual access to the database to nHibernate. The nice things is that this approach can co-exist with the old-school dataset style. The app doesn't care whether it's data is in a dataset object or in a plain domain object. The database doesn't care whether the sql is issued by a tableadapter or by hibernate. But the application developer, me, does care how I can organize the logic of my application.

    Convert to web app

    My first attempts to convert the app had been in the days prior to VS 2005 sp1. In an 1.1 app all web pages were in one assembly; in the first version of asp.net 2.0 every page had it's own assembly. Converting an app meant ripping it apart. My app died in that process. Since 1.1. the single assembly app is back. Now VS will convert your 1.1. app into a single assembly app.

    But it doesn't always convert your web pages right. In 2005 the class behind a web page is split in 2 partial classes, one with the generated code and one with your code. This split is not (always ?) done on the converted pages. You have to convert each page by hand. To do this right click the page in the solution explorer and choose convert to web application. David has a very nice post with good screenshots demonstrating this.

    SmartNavigation

    There are several ideas what smart navigation actually stands for. One has to do with focus and scroll position of a page over postbacks. The other with the history of pages in the browser. Without smartnavigation set every roundtrip of a single page is added to the browser history. With smartnavigation set every discrete page visit enters the history only once. Our app, being used for a lot of data entry, does a lot of roundtrips; so it's pretty important for smart navigaton to work right.

    In 1.1 SmartNavigation was a property of the Page class. Which had it's flaws. In 2.0 the property is considered obsolete; the members MaintainScrollPosition and the SetFocus are suggested. These do what their name suggest. But the thing we needed smartnavigation for seemed to be forgotten. To keep the history of the pages visited clean now requires a setting in the web.config

      <system.web>

        <pages smartNavigation="true"></pages>

     

    Control ID

    Every webcontrol on a page has an Id. You set the Id property but there is also the generated Id which is used when the webpage lives in the browser and in the form variables when the page posts back. To guarantee an unique id it is generated from the id of the control and the grid, user control or panel the control is in. You need this Id on several occasions. One is to find out which control was responsible for the postback. The good thing is that you calculate the id by hand, the bad thing is that the separator for the parts of the name has changed. In 1.1 it was a :, in 2.0 it is a $. In 1.1 a control id was something like DataGrid1:_ctl1:_ctl3, in 2.0 DataGrid1$_ctl1$_ctl3.

    Client side script

    Injecting client side script from the server requires the RegisterClientScript method. The 1.1 signature is considered obsolete, the new version expects a type in an extra parameter. It is hard to find any solid background information on this. What works well is passing the type of the usercontrol or page class which is injecting the script.

    Our client side script wrote some content in textboxes. When the page was posted back the server side code could use these values. In 2.0 these values are no longer passed into the textbox controls. To get to any updates done by script you have to read these yourself from the form variables in the request. Here you can use the ClientId property of the control containing the textbox to get the textbox Id.

    So instead of

    TextBox txb = (TextBox)Panel1.FindControl("TextBox" + i);

    if (txb.Text == "X")

        result += match;

     

    You now have to code

    if (Request.Form[string.Format("{0}:TextBox{1}", ClientID, i)] == "X")

        result += match;

     

    Loading CSS and images

    The app uses forms authentication to control access. Which forces an user to successfully log on before (s)he can access a page. In 1.1 this perfectly shields off all aspx pages. In 2.0 this also shields of other content like images and stylesheets. The unauthenticated user is redirected to the login screen. After conversion that no longer showed the app's logo (an image) nor applied any style. Fixing required an extra entry in the web.config.

      </appSettings>

      <location path="images">

        <system.web>

          <authorization>

            <allow users="*"/>

          </authorization>

        </system.web>

      </location>

      <system.web>

     

    The images directory contains the logo and the stylesheet. Everybody may see that.

    Winding down

    Having fixed these things I'm quite happy with the conversion. Now I can release the full potential of Resharper to do some big and needed refactorings. And the HTML editor in VS >= 2005 is so much nicer. So far the working of the pages in the app are based on the webforms API. As the Id fiddling showed this is not the easiest API. But it does work well; when you understand it. But I just can't wait to move on to .NET 3.51 and use asp.mvc for the new stuff.

  • Specialize ! In how, not in what

    At the start of a new year, whose name is in many a new product, it's a good moment for some small reflections before rushing on. My job over the years has been "with computers". To most people in my surroundings, including my wife, there is no big difference in setting up a network drive for sharing the family photos and web enabling a legacy planning app. Way back, when I started my job, you needed a broad knowledge to play your part. Over the years I have always tried to keep up with the many aspects of IT, which accumulated in running my own website and mail traffic. Which also helped me in better understanding the kind of environment my applications have to live in.

    But some problems at the end of last year made me change my mind. It had been a very rich experience to set up a fully functional site but to keep it running day after day is a different ballgame. The worlds of IT management and Software development differ on a very crucial point. In the last year(s) we have learned how to develop software following the scientific method. Isolate the problem to a single statement and try to falsify that by a repeatable experiment. In TDD words: mock up the environment, write a test which (initially) fails and automate running the test. Having to do "some" IT management made me realize how incredibly important and satisfying it is to work in such a way.

    My problem was that I started missing incoming mail. Something in the long chain between the sender and Outlook went wrong. But what ? I have been delving through firewall monitors, event logs, configuration files, registry settings and a lot more. Awful, the Visual Studio debugger is a paradise compared to what I've seen. My main problem was that all of this was passive, I can only observe the output of some tools. To understand which and how all parts work together I have to be an Exchange system architect. Which I'm not. Again and again I wished for a way to do some real experiments on the parts of the system. An experiment to test the firewall, an experiment to test mail acceptance or routing. I wished for all that the most when I found the real problem. My tests would have read green. The real problem were the master MX dns records which had gone stale; which slowly propagated over the web.

    I dare to state that we as software developers have a fundamental better way of building systems and keeping them alive. While ranting, I even dare to say that the situation is worse because (in my experience) a major part of the IT staff is just bad, not really fit for their job. Over the years I've met many a guy who would rather be a "real" developer but had failed the opening exams and now spent his days typing setup scripts. I'm the more mad at them because XS4all, an internet provider which used to have a good name and advertises with "we're not cheap but we are good", employs these kind of trained monkeys as well. On my email problems I made a phone call to their support line as they are my provider and do my DNS registration. The question was loud and clear "Hey, I see a significant drop of incoming SMTP traffic". After 40 minutes he still did could not say anything more "You run your own mail server and we do not support that". Idiot ! End of rant. Yes I do know some good IT staff. To them I can only say, be proud of yourself, you are a rare breed. Make sure your boss understands your qualities.

    The main lesson I've learned is that I am going to narrow my focus. With IT management I've had my fill, this is really the end of my private hosting. When it comes to software development I'm going to focus as well. Not on what's inside all these new api's. But on how to use them. On a testable reproducible way.

    Happy new year !

More Posts

Our Sponsors

Free Tech Publications

This Blog

Syndication

News