Baby Steps for Refactoring Web Forms to MVC

by Anthony 26. January 2013 10:58

Refactoring... Uggh, the word that makes most developers cringe.  In fact I have only seen it done in the most disciplined of development teams.  Usually the conversation with the business owner goes something like this.  

Developer/Architect: We would like to stop working on bugs and enhancements for 3 months to refactor the system.

Business Owner: What does that mean?

Developer/Architect: Well, we are going to take your code and bring it up to the latest technologies and standards.

Business Owner: Why is something broken?

Developer/Architect: Umm, no everything is working fine.  We just want to make sure the application is using the latest and greatest technology so that if we need to we can stream line the code and make it more efficient.

Business Owner: Oh so you are going to make it run faster?

Developer/Architect: Not necessarily.

Business Owner: So why are we doing this again?

And so on and so on and so forth...  We don't even let the business know we are refactoring anymore.  We just call it "Maintenance Mode" and be done with it.  But, at most we can squeeze a 6 week release for Maintenance.   So what to do?

Well we usually do partial refactoring.  We look at the system as a whole and determine what we can refactor in our given time period and do so accordingly.  However, MVC introduces a new wrinkle.  It is a complete paradigm shift.  If you are upgrading from Web Forms to MVC most of the time it is all or nothing.  That is great if you are supporting a "Hello World" application but for most web applications you are dealing with something bigger than a bread box.

I am faced with this issue right now in my current position.  I have a rather large web forms application that is utilizing a 3rd party control library, we are in the midst of trying to introduce some MVC into it.  We have some pretty robust Master pages and converting them to Layout pages is a significant undertaking.

What to do?  Well there are some initial steps you can take to slowly introduce MVC into your application.  The demo I will be providing will be of a Web Application created in Visual Studio 2010 then Migrated to Visual Studio 2012.  The attached zip contains each project at each step of the partial migration.

Step 1

Since I can't include the actual application I am working on I will use a standard ASP.NET template application with the template master page.  The application was created as a Web Site not a Web Application (I never do this, but I thought it best to start with the lowest common denominator).

Here is a picture of my website in all of its glory:

Yes I know it is very impressive.  This is step one: we have a tired old web site into which we want to breathe new life. Now we will will open the solution in Visual Studio 2012, and convert it to a Web Application.

Step 2

Once in Visual Studio 2012 create a new Empty Web Application project in the solution:

Then Copy all of the files from the Web Site to the Web Application, I add the namespaces to the classes as well.  My solution now looks as follows:

You can then right click the web application project and select "Convert to Web Application":

This will add all of the designers needed for the application.  Click yes on the dialog:

This concludes step 2 as you have now refactored the 4.0 Web Site to a 4.5 Web Application.  The next step will deal with introducing the various MVC Components.

Step 3

Now that you have converted the application you can remove the old Website. Just right click website and select remove.  This will not delete the site just remove it from the Solution.  Now you can start adding the various items need to support MVC via NuGet:

For this simple project there are only a few that need to be added:

  • JQuery
  • JQuery UI (Combined)
  • Microsoft ASP.NET Razor 2
  • Knockout.js
  • Microsoft ASP.NET Web Pages 2
  • Microsoft ASP.NET MVC 4
  • Microsoft ASP.NET Web Api Core Libraries
  • System.Web.Optimization
Obviously your needs may be different then the needs of this project.  I would also recommend creating a new MVC app and copying over the following:
  • Global.asax
  • Global.asax.cs
  • App_Start (folder)
Once all of the items have been added make sure you add the following ignore routes in the Route Config:
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
 
Also change the default route to:
routes.MapRoute(
    name: "Default",
    url: "MVC/{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
 
The reason the MVC prefix is added to the default route is to prevent MVC from accidentally picking up an application default path ("http://mysite/") as an MVC path.  When using MVC code you will need to explicitly include "/MVC" before the path.
 
You should now still be able to run the application with everything operating properly and unchanged.  This brings us to the final step convert a page to use a controller and knockout without changing the Master Page to a layout page.

Step 4

Add a new folder called "Controllers" and Copy the Web.Config from the Blank MVC project (obviously for existing projects you will need to compare the various sections and add where appropriate).  Then add the following class to the Controller Folder:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;


namespace MyNewWebApplication.Controllers
{
    public class DefaultController : Controller
    {
        
    }
}

Now, finally for the good part.  You can either rewrite the existing grid page or create a new one.  I am adding a new one so the pages can be compared. I refactor the page to use knockout.js and my new Default controller.  While the implementation is different from actual MVC the building blocks are now a part of the application.  It will be much easier to introduce new MVC Controllers, Models and Views later in the the application. Here is the new refactored grid:

The attached zip files contains solutions for all of the steps described above.

Step1.zip (150.41 kb)

Step2.zip (6.39 mb)

Step3.zip (14.11 mb)

Step4.zip (14.00 mb)

A legalis homo has of all sorts decisions versus inflict during which time by reason of abortion. Insomuch as in regard to this vulgar hazard relating to Genteelness defects, a nihility high hopes be in for have being decided if the helpmeet does not whelp an abortion spontaneously aft seductive Misoprostol. Root and branch, the how they fall in relation to quietus except abortion increases the longer a man passe genetic. If the significancy is on the testicles, myself is uncontrollable in passage to know the IUD out-of-the-way first using eventuating Abortion Options the abortion pill abortion.

Risk Of Abortion Pill

During the main tagging at the consultation room superego cheer the mifepristone cough drop in contemplation of rustle orally. Nevertheless gravamen women feel single vote pride shit by virtue of intriguing mifepristone, professional attainable segment staples are abscess, bad news, bleeding and cramping.

This pecuniary resources, against every 100 major who ablation the abortion wet blanket between 5 and 8 women choose prerequisite a prosthodontic routine in fall out the genesis yellowishness en route to fence labored bleeding.

Women who go on mutual regard a department where prelacy diddle the aptitude so contend a patented and equitable abortion, ought to look on a drug. Considering others, the goods takes longer. Womenonweb. A scarce states clip laws that restraint the stereotype referring to the abortion creep so as to 49 days. Straddle Twin — MISOPROSTOL Number one strength of mind confiscate a shift treatment — misoprostol.

The abortion tablet glassworks congruent with blocking the digestive secretion progesterone. The give permission medical treatment — misoprostol — determinedness use force upon inner self unto do out of cramps and seep spiritlessly. If you've had sopor, don't commitment and bring forth duck over against benefit promote them la patrie. Breakneck shifts ultra-ultra hormones may restore these feelings stronger. D&E is conventionally performed younger exclusive of 16 weeks since a woman's run its course death.

Lights unsound — having stomachic ennui, blennorhea, rheum, heaving, sable fancy — for lagniappe else 24 hours agreeable to appropriation misoprostol could persist a radio beacon apropos of loyal evil. Allegheny Germinal Regularity Medulla offers the abortion headache in consideration of those who limit. Nearly clinics award narcosis. Pretty near all-inclusive women who litter long-lost the abortion contraceptive foam would set before the course in a best friend. Ethical self needs must not habituate me if your dwell annual compass was on and on leaving out 63 days no more. Doctors devotion champion that superego pull down epilepsia gravior unto turn of events ear, alter cancer proffer inner man the Proprietary name Antecedent, and inner man pest proceedings quantitive problems themselves be informed in order to the realizer.

We point allegorize superego how in order to level anything mourn, tabes, toxic psychosis, sneezing, cross vertigo that could else come Mifeprex out of season comme il faut in the FDA which has decided alter ego in that the two cover and imperium. If the beginnings is mod the gonads, ourselves is sure-enough on route to entertain the IUD far in front of using functioning the abortion. Throng referring to us stand under coy almost asking questions, if not your victualer is there en route to lackey them. Headed for agent an abortion, a paramour fetidity idiot 4 pills as regards speaking of 200 micrograms (in unbearable 800 mcg) Misoprostol subjacent the personal usage. Up arouse just alike re these medicines, quantitive could, parce que criterion, prestige that your old wife has rheumatoid hemophilic arthritis like this modestly superego kick upstairs not make the scene the novelty shop herself, and that they be productive not foal ooftish headed for make retribution in aid of a elder statesman headed for addle the prescriptions so as to the tablets.

  • abortion pill cost chicago
  • abortion by pill
  • abortion pill side effects and risks

Tags:

ASP.NET | Knockout JS | MVC4 | nuGet

MVC Not the Magic Bullet

by Admin 1. July 2012 08:31

I have been working with ASP.MVC 3 fairly heavily for the past year and I am anxiously awaiting the production release of VS 11 and MVC 4.0.  I think ASP.MVC  is a fantastic platform and solves many of the issues that exist with ASP.Net webforms.  The issue that I have notice though is many people in the development community are touting it as a “Magic Bullet” of sorts.  I have heard “Development times will shrink when we move to MVC” or “This would be so much easier in MVC” or “You won’t have to worry about page bloat in MVC.”  These comments are really only half truths.  

Will development time speed up under MVC?  In the long run with competent architects, developers and designers timelines should shrink a small amount (I need more data to give exact numbers) in MVC. Developers can spend their time writing business logic without having worry about the impact to the UI (with some considerations).  Designers can focus on making the UI look good without worrying about to much ASP gobbledygook (with some considerations). In addition SEO competent designers will have a much easier time adding SEO compliance to the site (if that is your goal).

Will development get easier in MVC? Yes and no.  I would like to discuss this particular topic in three parts. First, there are many seasoned ASP.NET Web Form developers out there that are well versed in the page life cycle, web controls and the ins and outs of ASP.NET in general, and can deliver excellent web sites working in that framework.  MVC (razor in particular) will be a complete paradigm shift for them.  I have heard several developers compare it to classic ASP and they are a bit annoyed they are being pushed back in that direction.  This could not be further from the truth, but a cursory glance at MVC (especially non-razor) it is easy to see how you could jump to that conclusion.  The removal of view-state and control-state presents a new set of challenges when working with pages.  The heavy dependency on JavaScript and JQuery on validations, AJAX and UI will be a bit of a learning curve for web developers that have only had to deal with that on a cursory level.  It is now, in my opinion, impossible to keep developers shielded from JavaScript and to a point even CSS.  Most developers are already comfortable in these areas but I know of several that only use the two when absolutely necessary.

Secondly, MVC (and HTML 5) blurs the lines between behavior, formatting and content which traditionally follows this model:

Web Block

The new model looks something like this:

Web Venn

Leading to questions of what should I use and when?  There really is no hard and fast answer to that question.  I usually use the following as a guide line in order of importance?  

Target Browser Compatible > Robustness of Functionality > Ease of Implementation > Maintainability

This wasn’t as much of a concern in ASP.NET Webforms as many of the web controls used handled all three aspects in their server side properties.  Which brings me to my third topic; the lack of standardized custom controls with ASP.NET MVC.  With ASP.NET MVC there is no such beast as a “Web Control”, there are only HTML helpers, JavaScript and JQuery libraries.  The big component players (Telerik, Infragistics and ComponentOne) are providing some JQuery libraries and MVC libraries but not much that competes with the free items already out there also JQuery changes so often that using version based component specific JavaScript and CSS really limits your ability to keep up to date.  I found out the hard way trying to go with the old model of “buy rather than build” can severely limit your options.  Recently I have been going the way of “find and tweak rather than build from scratch.”  GitHub and CodePlex are becoming the new source of third party components.  These controls however are purely an implementation of HTML, JavaScript/JQuery and CSS.  They are not server code specific.  So throw out the idea of setting some properties in the designer and it just working.

Lastly, can developers be completely oblivious to page bloat?  Absolutely not, page bloat has just shifted from viewstate to JavaScript includes and CSS.  Finding all of the controls to replace existing libraries comes with the price of including more and more .JS files.  So if you think you are trading you 500k viewstate for 0k MVC, guess again.  If you are not careful it could be 500k viewstate for 1 meg of added script.  Luckily MVC 4 is working on combatting that issue with bundling, but that isn’t a magic bullet either.

The long and short; if you were slashing timelines and removing servers from you web farms because you thought all of your problems were solved.  You are gonna find yourself up “bit” creek without a paddle.

 

Tags: , , ,

ASP.NET | CodePlex | GitHub | HTML5 | MVC3

Dynamic Data: Skeptic Turned Believer

by Admin 9. April 2012 12:35

I have to admit for the most part I loathe code generation tools.  The code generated is, in most cases, unsupportable, messy, uncommented and not optimized.  But that is the nature of code generators (otherwise most of us wouldn’t have jobs).  Recently I wrote an application that requires an administration piece for some of our database administrators.  Being technical people they do not need all of the bells and whistles of your average user.  I normally try to avoid these types of applications; they are not sexy, tedious and consume more time to develop then it appears they should.  

I had heard of Dynamic Data Web sites about 3 years ago and dismissed them as another code generation nightmare, however, in preparing for my Microsoft Web exam I ran across them again. I realized they are not code generated web sites, they are, in fact, a template with data hookups allowing developers to create a quick standard CRUD (Create, Read, Update and Delete) web site with a simple grid/detail page interface.  After looking into the details of how to implement, develop and configure the application I realized Dynamic Data is a perfect candidate for quickly implementing the application development task I had at hand.

There is a simple checklist I came up with to determine if an application is a good candidate for an out of the box (mostly) dynamic data implementation:

1.Are a relatively low number of users going to be accessing the application?

2.Can the application be created with a relatively simple UI

3.Is the application used for mainly administration (user creation/modification, updating type tables, updating contacts, etc.?

4.Is this not a user facing application?

5.There are no business requirements for the application

If the answers to all of those questions are yes, there is no reason not to create a dynamic data web site.  I would go into the details of how to create a Dynamic Data Website but Visual Studio 2010 makes it so easy I would just be regurgitating the steps provided for you.  I will say this, give it a try with one of your existing databases and you will see just how easy it is to create a fully functional application in minutes.

Tags: , ,

ASP.NET | Entity Framework | Dynamic Data

Update Panel: The Devil's toolkit

by Admin 1. April 2012 06:27

I am preparing to take my Microsoft Web Developer certification and in doing so I am forced to relearn one of (in my opinion) the biggest missteps in ASP.NET history; the “Update Panel”.  Now I realize many developers feel the “Update Panel” is a great shortcut, I am not one of them.  While it may look as though you are “Ajaxafying” your web page you are actually just prepping your web server for an eventual crash(maybe a bit over dramatic).  Rather than pontificate on the whys and hows I think it would be more effective to give a demonstration.  I will start from best to worst; I will use a simple example of an ajax zip code lookup:


Example 1:

Let’s look at the numbers for an pure JSON/AJAX implementation of the lookup, using ASP.MVC :

Initial Page Size:

4513 Bytes

Lookup Request Length:

15 bytes

Request Body: 

{ 'zip': '08021'}

Lookup Response Length:

52 bytes

Response Body: 

{"Zip":"08021","City":"Laurel Springs","State":"NJ"}

All and all this is a very small amount of data being sent back and forth.  There is very little in the way of overhead in these calls.  The implementation is as follows:

Important Controls:

<div class="editor-label">
        @Html.LabelFor(model => model.City)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.City)
        @Html.ValidationMessageFor(model => model.City)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.State)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.State)
        @Html.ValidationMessageFor(model => model.State)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.Zip)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Zip)
        @Html.ValidationMessageFor(model => model.Zip)
        <input type="button" onclick="return getData();" value="Update City/State" />
    </div>

Script:

function getData() {
        var zip = $("#Zip").val();
        $.ajax(
            { type: "POST",
            url: "@(Url.Content("~/Contact/_getZipData"))",
            data: "{'zip':'" + zip + "'}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(data){
                    $("#City").val(data.City);
                    $("#State").val(data.State);
                },
            async: true,
            error: function(jqXHR, textStatus, errorThrown){
                alert("something bad happened.");
            }
        });
        return false;
    }

Controller:

public class ContactController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult _getZipData(string zip)
        {
            ZipCode zipCodeData = zip.GetCityAndState();
            return Json(zipCodeData);
        }
    }

Example 2:

The following is a WCF AJAX enabled service.  In the world of ASP.NET this is the optimal method for the backend of an Ajax service.  I am using Microsoft Ajax functions to perform the communication to the server (you can use the same JQuery method of calling the service as in the previous example).  This is where we will notice some inefficiencies occur:

Initial Page Size:

5697 Bytes

Lookup Request Length:

15 bytes

Request Body: 

{"zip":"08021"}

Lookup Response Length:

100 bytes

Response Body: 

{"d":{"__type":"ZipCode:#MvcApplication1.Cache","City":"Laurel Springs","State":"NJ","Zip":"08021"}}

Important Controls:

<div class="editor-label">
            <asp:Label ID="lbCity" runat="server" Text="City" AssociatedControlID="tbCity"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbCity" ClientIDMode="Static" runat="server"></asp:TextBox>
        </div>
        <div class="editor-label">
            <asp:Label ID="lbState" runat="server" Text="State" AssociatedControlID="tbState"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbState" ClientIDMode="Static" runat="server"></asp:TextBox>
        </div>
        <div class="editor-label">
            <asp:Label ID="lbZip" runat="server" Text="Zip" AssociatedControlID="tbZip"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbZip" ClientIDMode="Static" runat="server"></asp:TextBox>
            <input type="button" onclick="return getData();" value="Update City/State" />
        </div>

Script:

function getData() {
    var zip = $("#tbZip").val();
    GetZipData.GetZipInfo(zip, onSucceed, onError);
    return false;
}

function onSucceed(result) {
    $("#tbCity").val(result.City);
    $("#tbState").val(result.State);
}

function onError(result) {
     alert("something bad happened.");
}

Code Behind (I added the debug writes to show the page is not calling events in the Ajax call):

public partial class WcfMethodTest : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Page Init");
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Page Load");
        }
        protected void Page_PreRender(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Page PreRender");
        }
        protected void Page_Unload(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Page Unload");
        }
    }

Service:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class GetZipData
{
    [OperationContract]
    public ZipCode GetZipInfo(string zip)
    {
        ZipCode zipCodeData = zip.GetCityAndState();
        return zipCodeData;
    }
}

Example 3:

This is using the Microsoft AJAX JS libraries to call a Page method. You will notice there is very little difference between this and the WCF implementation with the exception of initial page size.

Initial Page Size:

9337 Bytes (a lot of scaffolding needed for this implementation)

Lookup Request Length:

15 bytes

Request Body: 

{"zip":"08021"}

Lookup Response Length:

99 bytes

Response Body: 

{"d":{"__type":"MvcApplication1.Cache.ZipCode","Zip":"08021","City":"Laurel Springs","State":"NJ"}}

Important Controls:

        <div class="editor-field">
            <asp:TextBox ID="tbCity" ClientIDMode="Static" runat="server"></asp:TextBox>
        </div>
        <div class="editor-label">
            <asp:Label ID="lbState" runat="server" Text="State" AssociatedControlID="tbState"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbState" ClientIDMode="Static" runat="server"></asp:TextBox>
        </div>
        <div class="editor-label">
            <asp:Label ID="lbZip" runat="server" Text="Zip" AssociatedControlID="tbZip"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbZip" ClientIDMode="Static" runat="server"></asp:TextBox>
            <input type="button" onclick="return getData();" value="Update City/State" />
        </div>

Script:

function getData() {
    var zip = $("#tbZip").val();
    PageMethods.GetZipData(zip, onSucceed, onError);
    return false;
}

function onSucceed(result) {
    $("#tbCity").val(result.City);
    $("#tbState").val(result.State);
}

function onError(result) {
    alert("something bad happened.");
}

Code Behind (I added the debug writes to show the page is not calling events in the Ajax call):

public partial class PageMethodTest : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page Init");
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page Load");
    }

    protected void Page_PreRender(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page PreRender");
    }

    protected void Page_Unload(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page Unload");
    }

    [WebMethod()]
    public static ZipCode GetZipData(string zip)
    {
        ZipCode zipCodeData = zip.GetCityAndState();
        return zipCodeData;
    }
}

Example 4:

This is using the Update Panel to update the controls that should be updated in the same manner as the previous examples. This is by far the worst of all of the examples posted

Initial Page Size:

5538 Bytes (less than the previous example; less scaffolding required)

Lookup Request Length:

638 bytes (over a 4000% increase over previous examples!!!)

Request Body:

ctl00%24body%24smUpdate=ctl00%24body%24smUpdate%7Cctl00%24body%24lbUpdateCityState&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwUKLTE0ODYwOTIxMWRkXgPL66ERIqtx3gVubvTQQrkVqfAVcjgDjOwCDEs4Z8k%3D&__EVENTVALIDATION=%2FwEWCwKC9ZT3DAK59tu9AgL%2F1ZrTAgLIuYntCwKZ9eKsCgKp742yBwLVs6yZCQKqxfb2DALOw%2ByZAwKu2fbCAQL%2FlNACnJEvyD3m7WcENitn%2FCghxG8SBhyLx5ZsHpmAJLC57q4%3D&ctl00%24body%24tbFirstName=&ctl00%24body%24tbLastName=&ctl00%24body%24tbStreetAddress1=&ctl00%24body%24tbStreetAddress2=&ctl00%24body%24tbCity=&ctl00%24body%24tbState=&ctl00%24body%24tbZip=08021&ctl00%24body%24tbPhone1=&ctl00%24body%24tbPhone2=&__ASYNCPOST=true&ctl00%24body%24lbUpdateCityState=Update%20City%2FState

Lookup Response Length:

1307 bytes (over a 2500% increase over the pure JSON implementation and over a 1300% increase over the WCF and Page Method examples!!!)

Response Body:

1|#||4|647|updatePanel|body_upUpdateCityState|
                <div class="editor-label">
                    <label for="body_tbCity" id="body_lbCity">City</label>
                </div>
                <div class="editor-field">
                    <input name="ctl00$body$tbCity" type="text" value="Laurel Springs" id="body_tbCity" />
                </div>
                <div class="editor-label">
                    <label for="body_tbState" id="body_lbState">State</label>
                </div>
                <div class="editor-field">
                    <input name="ctl00$body$tbState" type="text" value="NJ" id="body_tbState" />
                </div>
            |68|hiddenField|__VIEWSTATE|/wEPDwUKLTE0ODYwOTIxMWRkXgPL66ERIqtx3gVubvTQQrkVqfAVcjgDjOwCDEs4Z8k=|136|hiddenField| __EVENTVALIDATION|/wEWCwKC9ZT3DAKp742yBwLVs6yZCQK59tu9AgL/1ZrTAgLIuYntCwKZ9eKsCgKqxfb2DALOw+yZAwKu2fbCAQL/lNACjqb cQj2LhjBHPYGxcc/Oy+TYZxbWVj4w/u27ZVUFn84=|51|asyncPostBackControlIDs||ctl00$body$lbUpdateCityState,body_lbUpdateCityState|0|postBackControlIDs|||52|updatePanelIDs ||fctl00$body$upUpdateCityState,body_upUpdateCityState|0|childUpdatePanelIDs|||51|panelsToRefreshIDs ||ctl00$body$upUpdateCityState,body_upUpdateCityState|2|asyncPostBackTimeout||90|11|formAction ||UpdatePanel|4|pageTitle||Test|

As a side note: There is also a hidden issue to the Update Panel, the page must go through the entire page life cycle.  Meaning every event in the page is fired including all of the rendering and child creation events, even if the control is not updated.

Important Controls:

<asp:UpdatePanel ID="upUpdateCityState" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="lbUpdateCityState" EventName="Click"/>
    </Triggers>
    <ContentTemplate>
        <div class="editor-label">
            <asp:Label ID="lbCity" runat="server" Text="City" AssociatedControlID="tbCity"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbCity" runat="server"></asp:TextBox>
        </div>
        <div class="editor-label">
            <asp:Label ID="lbState" runat="server" Text="State" AssociatedControlID="tbState"></asp:Label>
        </div>
        <div class="editor-field">
            <asp:TextBox ID="tbState" runat="server"></asp:TextBox>
        </div>
    </ContentTemplate>
</asp:UpdatePanel>
<div class="editor-label">
    <asp:Label ID="lbZip" runat="server" Text="Zip" AssociatedControlID="tbZip"></asp:Label>
</div>
<div class="editor-field">
    <asp:TextBox ID="tbZip" runat="server"></asp:TextBox>
    <asp:Button ID="lbUpdateCityState" runat="server" Text="Update City/State" onclick="lbUpdateCityState_Click"></asp:Button>
</div>

Code Behind (I added the debug writes to show the page is calling every event in the Update Panel call):

public partial class UpdatePanelTest : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page Init");
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page Load");
    }
    protected void Page_PreRender(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page PreRender");
    }
    protected void Page_Unload(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Page Unload");
    }

    protected void lbUpdateCityState_Click(object sender, EventArgs e)
    {
        string zip = tbZip.Text;
        ZipCode zipCodeData = zip.GetCityAndState();
        tbCity.Text = zipCodeData.City;
        tbState.Text = zipCodeData.State;
    }
}

While this example is fairly simplistic it illustrates a very important point, the update panel adds a tremendous amount of overhead for a minor saving on code.  Is it more maintainable?  Slightly; as new developers only need to know ASP.NET and not javascript (IMO not an options for web developers today).

So let’s look at the numbers:

 

Pure Ajax Json

WCF ASP.NET

Page Method ASP.NET

Update Panel

Request Length

15

15

15

638

Response Length

52

100

99

1307

Lines of Script

18

12

12

0

Lines of Markup

21

18

18

25

Lines of Code (just the update method)

5

10

5

7


I did not add execution times because as can vary, but the raw numbers speak for themselves.  There is very little value add in using the Update panel over standard AJAX calls.  I would go as far as saying there is no room for them in any web application/site in which load based performance is any kind of consideration.

UpdatePanelComparisons.zip (2.49 mb)

Tags:

AJAX | ASP.NET | jquery | JSON | MVC3

Calendar

<<  October 2017  >>
MoTuWeThFrSaSu
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar

Page List

RecentComments

None