Sunday, June 26, 2011

fighting with ASP.NET web forms

Three golden web forms hacks:
  1. Struggling with imposed HTML...

    Let’s say you had the following information...


    First Name: null

    Middle Name: Woodrow

    Last Name: Wilson

    Nation: US

    Role: Head of State

    Quote: God loves me.


    First Name: David

    Middle Name: Lloyd

    Last Name: George

    Nation: UK

    Role: Head of State

    Quote: Whatever.


    First Name: Georges

    Middle Name: null

    Last Name: Clemenceau

    Nation: France

    Role: Head of State

    Quote: I'm the new Napoleon.


    First Name: Vittorio

    Middle Name: null

    Last Name: Orlando

    Nation: Italy

    Role: Head of State

    Quote: TAKE ME SERIOUSLY. I'M IMPORTANT! I MATTER! PAY ATTENTION TO ME!


     
    ...and you wished to arrange it like so...


    Which nation has the coolest leader?

    Georges Clemenceau David Lloyd George Vittorio Orlando Woodrow Wilson
    "I'm the new Napoleon." "Whatever." "TAKE ME SERIOUSLY. I'M IMPORTANT! I MATTER! PAY ATTENTION TO ME!" "God loves me."
    France UK Italy US




     
    ...however, the closest you can get with a DataList web forms control is like so...



    Which nation has the coolest leader?


    Georges Clemenceau
    "I'm the new Napoleon."
    France

    David Lloyd George
    "Whatever."
    UK

    Vittorio Orlando
    "TAKE ME SERIOUSLY. I'M IMPORTANT! I MATTER! PAY ATTENTION TO ME!"
    Italy

    Woodrow Wilson
    "God loves me."
    US




     
    ...also let's assume that you didn’t build the DataList. It just sits in an .aspx page that you are tasked with cleaning up HTML for that has significant functionality written around the PostBack of its asp:RadioButton controls. What will you do?



    Bryan Bilbrey of New Iron has suggested that I read Martin Fowler's "Refactoring." The bulk of this book is a long list of different types of Refactorings detailing both why/when to Refactor and the steps for doing so. I have generally found myself skimming the notes for steps for refactorings as once I know where I am going I feel confident in getting myself there. Refinement doesn’t seem challenging... at least, not on the page. In practice however, I find there is a need to be careful and to slowly, incrementally walk towards an objective in incremental steps. For the problem mentioned above, I recommend:



    1. creating a Repeater next to the DataList (The Repeater will not wrap it's data in table HTML unless you write the HTML yourself.)
    2. making <ItemTemplate> contain asp:RadioButton controls (like those of the DataList) wrapped inside <td></td> (Write other HTML markup for the table around the Repeater but not in it.)
    3. making a copy of all methods that manage logic for the DataList's asp:RadioButton controls and getting the new methods working with the Repeater
    4. getting rid of the DataList and make sure everything works
    5. adding the other horizontal rows to your HTML table (This could be done with separate Repeaters for each row. For this less form-functional data you could also spool up HTML in C# which is a really dirty hack, but then web forms is an environment that requires dirty hacking.)

    What if there are one hundred data points instead of four? The user will have to scroll horizontally and that will be ghetto. Well, the content likely wasn't designed in such a space-consuming manner to begin with if there are to be numerous records. That said, if the number of records does grow unwieldy, you will need to consider how to craft second and third tables to hold new "rows" of data. This could be done by adding new Repeaters which are only shown conditionally when applicable and by breaking the data that gets passed to the Repeaters up before bindings.




  2. Struggling with column-based sorting...

    OK... moving from DataLists and Repeaters to GridViews... Let's say you have something like the information above in a GridView like so...


    Which nation is most influential?
    Which nation has the coolest leader?

    First Name Middle Name Last Name Nation
    Georges   Clemenceau France
    David Lloyd George UK
    Vittorio   Orlando Italy
      Woodrow Wilson US




     
    Here I envision a web form that allows a user to select one of two survey questions to answer. The asp:RadioButton controls that govern which survey is asked will conditionally either show or filter away records where "Role" is not "Head of State" such as:


    First Name: Gavrilo

    Middle Name: null

    Last Name: Princip

    Nation: Serbia

    Role: Assassin

    Quote: Come together, right now. Over me.


     
    OK, let's also assume that we don't want to make a trip to the database every time the page reposts to get records to populate the GridView. Instead, we get all five records upfront if (!IsPostBack) and otherwise we just rely on data kept in ViewState. On top of this, we want to make the last two columns sortable. Now some conditionals have to stack. Oh boy. We cannot use the default means of GridView column sorting as it turns out because that approach does what it does without reposting the page (JavaScript), not allowing us access to ViewState and not playing nicely with the IsPostBack logic that is in place.* What is the fix?



    <asp:TemplateField HeaderText="
    <input type='submit' name='sort' value='Nation' />">



    Dirty hacking! It works! Use this approach to make a column header repost the page. Then fish for the submission in C# like so:


    if (!IsPostBack)

    {


       go get data...

    } else {

       string sortBy = Request.Form["sort"];

       if (sortBy == "Nation") {


          more code...


    *If we use links-driving-JavaScript to facilitate column sorting, Serbia will inappropriately appear as an option in the "Which nation has the coolest leader?" survey upon the clicking of a sortable column heading. This is because we pull data from the database in full when the page isn't reposted and we only filter that data when the asp:RadioButton next to "Which nation has the coolest leader?" is clicked. Web forms allow asp:RadioButton controls to repost the page.


  3. Struggling with jQuery form validations...



    Alright, there is only one form on every page, controlled by a MasterPage, and I sometimes, but not most of the time, I want it to have an onsubmit parameter that could return false so that I may raise a flag to a user to let him/her know there is a problem with leaving a field blank or something comparable. (Perhaps for the forms above you would wish to shout: "You must make a selection to vote.") Note: The conditional presence of onsubmit should only occur for a few individual .aspx pages nested within a larger existing application of numerous .aspx pages. Also: On the target page, I would have the jQuery function called err on the side of returning true unless very specific conditions are met, as not doing so could, for example, sabotage a search field in a common header which unfortunately uses the same form as the main content of the page due to the nature of web forms. If formMaster was the designation of the form in the MasterPage, some logic in the MasterPage is going to have to look like this:


    string url = Request.ServerVariables["script_name"];

    if (url.Contains("targetpage.aspx")) {

       formMaster.Attributes.Add("onsubmit", "return foo();");

    } else {

       if (url.Contains("otherpage.aspx")) {

          formMaster.Attributes.Add("onsubmit", "return bar();");

       }

    }



No comments:

Post a Comment