Hugoware

The product of a web developer with a little too much caffeine

Archive for August 2009

Sony VAIO – Now With Less Bloatware!

leave a comment »

You may have seen my previous post where I was deciding on the laptop I was going to purchase. I ended up going with the Sony VAIO VGN-FW463J/B (I can actually type it from memory after all the work I did this weekend). I got an awesome deal from NewEgg.com at a mere $899 – no tax!

To recap – here are the specs…

  • Operating System Windows Vista Home Premium 64-bit
  • CPU Type Intel Core 2 Duo P8700 2.53 GHz
  • Screen 16.4″
  • Memory Size 4GB DDR2
  • Hard Disk 320GB
  • Optical Drive Dual Layer DVD Burner
  • Graphics Card ATI Mobility Radeon HD 4650 (1GB)
  • Dimensions 15.1″ x 10.3″ x 1.14-1.46″
  • Weight 6.9 lbs.

Overall I’m quite satisfied with my purchase but it was a tough road to get here. This last weekend was rough to say the least. Here are a few of the problems I had when I got started.

Heat! Yowza!

I was quite shocked when I felt how hot this laptop is. It isn’t unbearable but is certainly isn’t ideal either. The odd thing is that the bottom of the laptop actually seems to be cooler than the top!. For the most part it seems that the harddrive and the graphics cards are the culprits – but since I plan to switch to a SSD drive later on then that source of heat should go away – and since I use the n52te when I play any games then the graphics card should be irrelevant (even though the vent exits where my arm would be — but whatever, close enough :))

Wireless

The wireless works until it comes out of sleep mode – then it works for one or two requests and dies. You have to fiddle around with the connection before it finally restores itself. It isn’t terrible since the wireless “on/off” switch is on the front of the laptop and you can use it to “reboot” the connection. Just a slight annoyance that you can easily overcome.

BLOATWARE

I remember when I was a teenager my parents bought me a VAIO and if I remember correctly they had a bunch of custom software for everything. In fact, instead of using the typical Windows 98 Start menu, they had some custom screen for managing your applications. You could get out of it but it was also a pain since it was in your way at the start.

This VAIO is no different – they have a bunch of silly programs to do things that are already built into Vista (like one to manage your wireless connection – why?). Along with that you have some other apps pre-installed applications like a trial version of Office or Norton Anti-Virus.

The problem comes in since you can’t do a clean install because the restore disks automatically reinstall all the bloatware you didn’t want — well that is unless you intervene. 🙂

The solution is really quite simple – just end task out of the installer!

At one point you’ll see that the VAIO restore disks are trying to install the software and drivers – just press CTRL-SHIFT+ESC to pull up the task manager and then end the process! The program fails, the Vista install completes and all the drivers you need, minus the wireless driver, can all be found on the restore disks.

Everything was installed correctly after the Vista install finished so I doubt you need the restore disks for the drivers – but they are there if you need them (again – the wireless driver has to be downloaded from the Sony website though).

Summary

I’m happy with my new laptop even though it took some effort to get to this point. Now my desk looks even more nerdy!

In my defense the teddy bear is a father’s day gift and cannot be removed… ever…

sweet

Written by hugoware

August 31, 2009 at 2:36 am

WebForms : FrontPage For Programmers

with 9 comments

Yeah – I said it. I called WebForms FrontPage for programmers – whadaya goin’ to do?

Now before people start throwing hate mail at me its worth pointing out that up until MVC I used WebForms for all of my web development. In fact, I really do like WebForms. I think that they are especially great for whipping out quick internal projects that normally draw away from the time you could use developing something useful.

But, as much as I like WebForms, I think that too often they spew out more crap than value. If FrontPage was the way for a non-technical person to make a website then WebForms is the way for a non-web developer to make a website.

A Simple Example

(It’s worth noting my measurements are based on uncompressed HTML – I’m mostly pointing out the differences between output created by the developers – not the content that is compressed down the wire.)

Well here is a page that really rubs me wrong…

windows-example-1

[Microsoft.com/Windows]

Why? Nothing bad about it – the page looks pretty good… until you look under the hood at the source code. Once you start digging into it you find that the page is a whopping 123K and of that 28K is in the ViewState — clearly something that could have been done away with. You can also tell that ASP.NET gave a bunch of the elements on the page a unique ID even though they aren’t going to be referenced by any sort of Javascript. How about the id ctl00_BaseBody_FadingHeroEmbeddedSliverlight1_FadingHeroEmbeddedSL_ HeroBottomTitleShortDescriptionDivID (I had to put a break in the middle).

ASP.NET really does an incredible job abstracting the web so that a desktop programmer can jump right into web development, sometimes even using drag-and-drop controls *shudder*. It seems to me that web development ought to be done by people that understands the model.

Here is an example where you can tell that web developers had constructed it. It pains me to show it but I think it is relevant here since they are direct competition.

apple-example-1

[Apple.com/Mac]

Yeah, it’s the website of the enemy. But if you go over the page there is roughly the same amount of information (if not more) but their page is only 25K (smaller than the ViewState alone on the previous example). Even if you compare all of the resources on the two pages, the Apple site loads about 30K less in stylesheets and scripts than the Microsoft site. It is worth mentioning that the Apple site does load more images but their entire pages is full of large, high quality images — which is something that grabs attention much better than text. Not only that, but the Apple site actually does stuff!

Why? If you look at the source code you can an immediate difference between the two. The source code on the Apple page is cleaner, better designed and smaller. There is no ViewState or unnecessary ids for elements on the page. Everything (appears) to have been placed onto the page through careful consideration and not generated by some Page Lifecycle that injects code and markup into your page without you even knowing it.

So What Is My Point

Both these examples are two high profile sites. They are from two very competent technology companies — however, one looks a little less skilled to the other – at least from a web development perspective. It seems to me that extra time and effort should have been placed by the Microsoft developers to trim out all the fat and make it as web friendly as possible.

I might be nit-picking at the HTML output but I do think its relevant. That code – even if it is compressed – is the final rendered output from a WebForms page. As soon as the page opens there is immediately markup errors, unmatched tags, extra body elements. It’s clearly not the best it can be. I’m not trying to make Microsoft look bad either – personally, I want to work for them some day, but the point is that in order to improve then you must first be honest with yourself and those around you.

WebForms are a powerful tool – don’t get me wrong – but it seems to me that they have abstracted web development too far. I always thought it was really cool about .NET the way you could go from web, desktop, console, mobile or whatever development you wanted to and it was still like second nature! It allowed you to focus on solving problems and less on how each area was supposed to work.

I’m not saying people can’t develop great applications with WebForms. In fact I still use them from time to time when I need to hack out a quick application that only the internal eyes of my company are going to see. However, when I’m browsing the web and come across a website that is packing a 50K ViewState or is littered with wasteful, pointless 40 character long ids, I just can’t help but feel that WebForms is starting to hurt the web a little.

That’s why I recommend that if you haven’t already, go try out ASP.NET MVC. It doesn’t take long to break away from WebForms and you’ll probably feel more comfortable within a few days.

Written by hugoware

August 28, 2009 at 2:12 am

Virgin Mobile – Think Twice!

with 7 comments

I try to keep the topics on this blog to strictly programming related posts but after a recent experience with Virgin Mobile, I felt this was something that I should make public.

I’ve got a company phone right now but I figured I ought to have my own phone for personal use. I didn’t really want to get a whole new contract so I figured I would go the “Pay As You Go” route. Between the phone and the minute pack (400 minutes) I spent just over $50. It wasn’t a lot of money but it certainly wasn’t pocket change either. Through the last month I used exactly 1 minute and 4 seconds of my 420 minutes I had available. As of last night — all of my minutes had vanished.

The Website Approach

Being a web guy, naturally the first step is to sign onto their website and see what the problem is. So I opened up Chrome and…

website-chrome-menu

Eh… Okay, well I guess I didn’t want to use that menu system anyways. Thats fine though, I realize it’s hard to get everything to work in every browser so I’ll just pull up FireFox. After messing around with it a bit more and finally getting past their login I get the following…

firefox-error

Okay… FINE. I’ll use Internet Explorer…

ie-error

… 😐

The Automated Service Approach

I really hate calling phone services and hate it even more when I can’t just talk to a person. While a “voice” controlled automated service is cool from a technical perspective they are a pain because you’re forced to listen to every option and try to find your way to the section you need. Coming from the age of twitchy fast-answer internet browsing the whole process is entirely too slow.

I don’t really need to go into great detail about this part since you can probably guess what happened since I’m even mentioning it. After fumbling through menus for awhile and getting stuck in areas where hanging up seemed to be the only ‘back button’ available, I gave up. I never heard an option to speak with a real person, not once.

The E-Mail Route

I headed back to the website figuring that I must be the one doing something wrong but after a few more login attempts I realized I was getting nowhere. After a little more searching I found a customer service feedback form which was exactly what I was hoping to find.

Except they wanted me to provide my PIN number, which is the same number you use when logging in — a step that despite all my efforts had failed every time. I went ahead and explained my situation, entered the rest of my information and sent it away. After I finished the step I couldn’t help but wonder, what about NON-customers? What if I wanted to ask some questions before I paid for the service? How is this form supposed to help these people? Clearly a usability issue but not something of my concern.

The E-Mail Follow Up

The next day I got an e-mail. I won’t post the entire thing but here is the part that rubbed me wrong.

Thanks for your email!

The Account PIN you provided is not matching our records.

We can certainly help resolve your question but first we must verify we have the right account. Can you please respond and provide your correct Account PIN (numeric security code)?

For real? I’m already having problems with this PIN number and now you won’t talk to me unless I give you the correct information? The letter doesn’t tell you how to get your PIN either – it suggests that you either log into the website (with your PIN mind you) or call customer service (and fiddle around with their automated service again… yay!).

Now after going over the PIN information that I already had I realized I had been entering in the wrong number. Now I readily admit that is my fault — but where was the error messages on the site? Where is the validation that says “Hey man, you entered something that doesn’t look like a PIN. The PIN number should look like…”. Anything would have been better than nothing!!

In any case, I sent back the correct PIN number and finally got the answer to my question.

I would like to inform that minute packs are good for 30 days only and if you do not purchase another Minutes Pack within 30 days from the day you purchased your first Minutes Pack, you will loose all unused minutes.

That is the reason, you have lost the unused minutes on your account as you have not purchased another minute pack.

Customer Hostile Business Model

I have another “Pay As You Go” phone that I purchased for my 8 year old daughter. I’d like for my kid to have the option to call me in case of an emergency but know that if the phone is lost then I only lose about $30 which is a lot better than someone racking up a bunch of long distance calls on a subscription.

With her phone, when I buy minutes they come with service days. Not just a couple days but something like 90 days which is excellent. Whats more, is that those days stack on top of each other along with any unused minutes. Even if I some how run out of service days I can simply buy some more and all my minutes stay intact. It is a great system that is both clear and fair to the customer in how it works.

But take Virgin Mobile – 30 days after you buy minutes, unless you give them more cash, they wipe them out – all of them. Sounds like they got their business model directly from the Dark Side if you ask me.

So to be clear, right after you buy some minutes the 30 day timer starts at the end of which your minutes are erased no matter how many you have. What if you have 5 minutes? gone. Have 500 minutes? gone. Or the maximum 5000 minutes? gone. If you want to keep your phone working then you need to spend at least $20 a month — sounds a lot like a subscription to me.

Just to backup my claim, here is part of an e-mail that I got from their customer service. To be fair, in this e-mail they offered to restore my minutes if I purchased a new minutes pack — but it was a one time exception.

To answer your question: yes, you are absolutely correct in understanding that expired minutes will be lost and cannot be restored. However, if you purchase a minute pack and reply to this email, given you are a valued Virgin Mobile customer we will credit the expired minutes to your account balance.

Summary (read the small print every single time)

Don’t get me wrong, I messed up when I didn’t read the fine print. I appreciate the gesture they displayed at the end of this ordeal but I’d rather not have the threat of a complete wipe of my minutes looming over my head. If there are other, more consumer friendly options, then they need to be the default for the account.

In any event I think this experience helped me and $50 is a cheap price for a valuable “life lesson” — even if it was an obvious one.

In summary, I doubt Virgin Mobile is an evil company but they certainly aren’t looking out for the customer. Always remember to read the fine print in detail.

Written by hugoware

August 26, 2009 at 2:14 am

Posted in General Update

Tagged with , , ,

jLinq Screencast #3 – Modifying Records During A Query

with 3 comments

Sometimes when you get your records they aren’t exactly what you we’re needing, or sometimes some of the fields need to be formatted before they can be queried against. Fortunately, jLinq comes with that functionality built into it.

This screencast goes over several of the methods you have available to you that allow records to be formatted before they are selected.

  • each(delegate(record)): Performs a loop through each of the values in the array. This code can be used to modify records, create new properties or anything you need it to do.
  • attach(alias, delegate(record)): Performs the method passed in on each of the records in the array and attaches the result to the record using the alias provided.
  • join(records, alias, foreignKey, primaryKey): Joins two arrays together using the alias and the keys to match the values. Joins tend to be slow when using large arrays, so use caution.


screencast3

If you have any recommendations or requests for the next screencast, please let me know and I’ll see what I can do.

Side note: Never improvise on a screen cast – nothing like having to redo a screen cast twice because you say something that isn’t true and then realize it while recording. 🙂

Written by hugoware

August 24, 2009 at 2:21 am

Laptop Hunt (Coming To A Conclusion)

with 9 comments

The past few weeks I’ve been trying to find myself a new laptop. I’ve wanted something that was lightweight, thin, multi-core, 64 bit, SSD drive and a powerful graphics card. Basically, I wanted to have everything and give up nothing. Needless to say the search has been difficult.

I’m not really much of a hardware guy either so I tend to pick the whatever has the highest spec numbers and the lowest cost – not really a good indicator of laptop quality. However, in the process I came across a really good resource for getting laptop information.

NotebookCheck.com was a great resource for not only laptop information but for graphics accelerator information as well. Most of the summaries of graphics cards focused on quality settings and frame rates for popular video games — that’s a metric even I can understand!

After a lot of searching I finally found a laptop that seemed perfect Just check out these specs — all for $899.00.

hello-sexy

  • Operating System Windows Vista Home Premium 64-bit
  • CPU Type Intel Core 2 Duo P8700 2.53
  • Screen 16.4″
  • Memory Size 4GB DDR2
  • Hard Disk 320GB
  • Optical Drive Dual Layer DVD Burner
  • Graphics Card ATI Mobility Radeon HD 4650 (1GB)
  • Dimensions 15.1″ x 10.3″ x 1.14-1.46″
  • Weight 6.9 lbs.

But wait… did you see that? The USB ports? On… the… front… RIGHT?? That will be nice to have a bunch of cords sticking out right where I’m trying to use my mouse. In fact, if you zoom in closer you can see they even mislabeled the ports!

usb-fail

….well, not really…

In any case, as it turns out the laptop has Blue Tooth so the wireless option is easily solved. I even did a search on the internet for for a Blue Tooth powered USB hub, which I found for around $19.00.

Any thoughts? Suggestions? Feedback? Anyone have any last second warnings before I commit?

Written by hugoware

August 21, 2009 at 2:24 am

Posted in General Update

Tagged with , ,

Keep Your Website Alive (Don’t Let IIS Recycle Your Website)!

with 2 comments

Have you ever opened a page for one of your websites and it lags for awhile before it finally shows a page but then all of your following requests are quick? If you were to look up the problem you’d find that often it ends up having to do with IIS meeting an idle time limit and shuts down your site. There is even some software you can purchase to fix the problem for you.

But who wants to spend money on something like that? Especially when we can solve this ourselves — even for Hosted Environments!

Stayin’ Alive — (ack! bad pun again!)

If you happened to check out that software above then you can probably glean what it does just from the title. I’d rather not devote my personal machine to something like that so lets see if we can’t approach this from an alternative route.

private static void _SetupRefreshJob() {

    //remove a previous job
    Action remove = HttpContext.Current.Cache["Refresh"] as Action;
    if (remove is Action) {
        HttpContext.Current.Cache.Remove("Refresh");
        remove.EndInvoke(null);
    }

    //get the worker
    Action work = () => {
        while (true) {
            Thread.Sleep(60000);
            //TODO: Refresh Code (Explained in a moment)
        }
    };
    work.BeginInvoke(null, null);

    //add this job to the cache
    HttpContext.Current.Cache.Add(
        "Refresh",
        work,
        null,
        Cache.NoAbsoluteExpiration,
        Cache.NoSlidingExpiration,
        CacheItemPriority.Normal,
        (s, o, r) => { _SetupRefreshJob(); }
        );
}

If we place this bit of code in the Global.asax and call it when Application_Start() is raised, we can basically start a job that keeps our website alive. You could just as easily use a Thread to host the refresh method but for this example we simply used an Action delegate (but if you are using an earlier version of .NET then you might HAVE to use a Thread to do this).

Once our application starts the refresh job is also started and is saved to the cache. In this example we’re using 60 seconds, but you can change this to be as often as you like.

So How Can We Keep It Fresh?

So how about an example of some code we can use? Here is a simple example that could keep our website alive. Replace the //TODO: in the example above with something like the following.

WebClient refresh = new WebClient();
try {
    refresh.UploadString("http://www.website.com/", string.Empty);
}
catch (Exception ex) {
    //snip...
}
finally {
    refresh.Dispose();
}

This snippet uses a WebClient to actually make an HTTP call to our website, thus keeping the site alive! We could do any number of things from this code like updating local data or get information from external resource. This can be used to keep our site alive and our content refreshed, even if we’re using a Hosted Environment!

It is worth nothing that might not actually need to do an HTTP call back to your website. It is possible that using any method will keep your website from being killed off (but I haven’t tested it yet so let me know what happens if you try it). This example, however, has been tested and works quite well with my provider.

Written by hugoware

August 19, 2009 at 2:34 am

Using WebControls In ASP.NET MVC Views – Part 4

with 2 comments

Check out my newest blog post about using WebControls inside of MVC (source code included)🙂

WebControls In MVC Series

Disclaimer : This post is a rough overview how the MvcWebForms class works. If you don’t really care then you probably won’t want to finish reading this 🙂

In part 3 of this series we finally got to use some code that actually allowed us to use the entire post back process from an inline call with MVC. The next few parts of the series dives into how the code actually works — and hopefully discovers a few bugs and optimizations along the way!

For part 4 we’re going to focus on this small segment of code.

<% this.Html.WebForm((build) => { %>
<label for="name" >Name</label>
<% build.RenderControl(new TextBox() { id = "name" }); %>
<% }); %>

The WebForm Extension Method

Line 1: <% this.Html.WebForm((build) => { %>

The first step to render a WebForm is to call the HtmlHelper method WebForm. This method might look a little odd since it expects a delegate but it is required so that we can continue to use markup along side our WebControls, which we explain a bit more in a moment.

The delegate accepts a single parameter which is the MvcWebForm. You can think of this as the Page.Form you’re used to having access to. You can make changes to the postback target, attributes, content type, etc. The MvcWebForm is also where you provide the WebControls you want to render using .RenderControl(). There are several overloads to this method so you might want to poke around to see what kinds of options you have.

The delegate you provide isn’t executed immediately, in fact the Form element is created first and then a few content markers are added to the code. After all of the setup has taken place the code is the delegate you provided is rendered onto the page.

You might think that the rest of the code simply renders the output inline and then returns to executing the ViewPage code, but interestingly enough, the controls you created aren’t rendered to the page yet but instead placed into a queue.

Queuing Controls For Rendering

Line 3: <% build.RenderControl(new TextBox() { id = "name" }); %>

In order to render the WebControls correctly we need a context in which they can all be aware of one another. With WebForms, each stage in the Page Life Cycle gives you time to make changes to the document before the content is rendered, but in MVC you’re already in the Render stage — you can’t make changes to the content you just finished rendering! Clearly, we can’t render these controls inline.

Each time we call .RenderControl() we are actually creating a content marker for that control and then moving it to a queue. After the control is rendered the content is inserted back into the correct marker along with any scripts or stylesheets.

You might be wondering how we could do something like that, since we’re in the middle of the Render() call and that part of the page has already passed by. Recently, I had written some code to help me add stylesheets to the header of my MVC page from inline code — To say the least, it ended coming up very handy in this project.

Completing The WebForm Request

Line 4: <% }); %>

After the delegate has finished creating the content the remaining code finishes the rendering process and closes up the WebForm we are creating. After that point it is time to actually render the WebControls to display.

After the delegate has finished the code combines all of the controls into a dynamically loaded .ASPX page and then processes it. Once finished we end up with a string of the rendered HTML output which can be parsed into a XDocument! Each control is then matched up and the rendered HTML is inserted into the matching content marker! If any scripts or stylesheets are created then they are rendered into the top of the WebForm.

Really, There Is A Lot More

This is a rough overview of how the process works but I’ll get into detail more on each section through the rest of the series.

Written by hugoware

August 17, 2009 at 2:42 am

New Hugoware.net Site

with 11 comments

For the longest time now Hugoware.net has basically been the home for jLinq. Lately, I’ve been working on a new version of my site — one that represents all of the stuff I do and not just one of my projects. After working on the site for about a week I’ve updated with a brand new look and grouped all of my projects together into one site.

I’d love to get some feedback — so use the ‘Contact Me’ section to tell me if you think something could be improved.


hugoware

And of course, there is my Twitter Bird (he’s open source as well :))

twit

There isn’t much to talk about with the new site. Basically it is an ASP.NET MVC site with personal information and projects on it.

However, I’m always interested in hearing feedback. If you think something about the site is missing or could be improved, please let me know!

Written by hugoware

August 14, 2009 at 2:53 am

Using WebControls In ASP.NET MVC Views – Part 3

with 18 comments

Check out my newest blog post about using WebControls inside of MVC (source code included)🙂

WebControls In MVC Series

I mean’t to have this post out this morning, but I was busy working on getting my personal website online — Please check it out and tell me what you think!

Up until now all of the post in this series have been tests to see if we could make the process work. Now, finally, now we get into some real code that we can actually use. I’ll take just a little bit of space to explain how it works and how to set it up, but then the rest of the post to explain how to use it.

Getting The Code Setup

Before we discuss how to use the code lets go over briefly how to setup the code.

To start, the code you need to download is found at the end of the post. When you download it, put both the .cs and the .aspx file into your project. By default the code expects the .aspx to be in your Views directory, but you can move it — but if you do then you need to update MVCWebFormExtensionMethods._WebFormRenderControl.TEMPLATE_PAGE with the new location (yeah, it’s a long name :)).

Optionally, you can make a couple changes to your Web.config to make sure that the extension method and MvcControlGroup are available to the rest of your application without needing to add anything special onto each of your pages.

<configuration>
    <!-- snip... -->
    <system.web>
        <pages>
            <controls>
                <!-- snip... -->
                <add tagPrefix="mvc" 
					namespace="MvcWebControls" 
					assembly="YourProjectAssemblyName" />
            </controls>
            <namespaces>
                <!-- snip... -->
                <add namespace="MvcWebControls"/>
            </namespaces>
        </pages>
    </system.web>
    <!-- snip... -->
</configuration>

I’ve hidden most of the Web.config from this example, so make sure to add the areas you see above, not simply replace your entire config.

The rest of this post goes over some demos found out on my website, you may want to follow along to better understand what is going on.

Example 1 — Simple Postbacks

<html>
    <head runat="server">
        <title>Simple Postback Example</title>
    </head>
    <body>    
        <h2>Just A Simple Form</h2>
        <% this.Html.WebForm((form) => { %>        
            <% form.RenderControl(new TextBox()); %>        
            <% form.RenderControl(new Button() { Text = "Save" }); %>
            <hr />
            <% form.RenderControl(new Calendar()); %>
        <% }); %>    
    </body>
</html>

For the first example, we want to see if we can use a few simple WebControls and see if our values are posted back the way we would expect. In this example we add a TextBox, Button and Calendar. Pay attention to how this HtmlHelper method works.

If you notice, the method excepts a delegate to render the control onto the page. We do it like this because it allows us to provide markup to our page along side with the WebControls. The method accepts a single parameter the MvcWebForm. Think of this as a very, very simple version of a WebForm.

The MvcWebForm gives you access to the page that is being used to render the controls. This is important to remember and I’ll go over it in the next section.

Example 2 — Using Events

This is handy so far but unless we are using some events for our controls, nothing much has changed. Let’s look at another example.

<html>
    <head runat="server">
        <title>Using Events</title>
    </head>
    <body>    
        <h2>Simple Button Click Event</h2>
        <% this.Html.WebForm((form) => { %>        
            <strong>Clicked : </strong>
            <% Label text = form.RenderControl(new Label() { Text = "0" }); %>
            
            <br /><br />            
            <% Button submit = form.RenderControl(new Button() { Text = "Add" });
               submit.Click += (s, e) => {
                   int value = 0;
                   int.TryParse(text.Text, out value);
                   text.Text = (++value).ToString();
                   
                   //post back this information
                   form.Page.ClientScript.RegisterStartupScript(
                       typeof(Page),
                       "confirm",
                       string.Format("alert('Updated to {0}');", text.Text),
                       true
                       );
               }; %>
        <% }); %>    
    </body>
</html>

In this example we are assigning a Click event to the button we added to the page. You’ll notice when we run this example the value is incremented up by one on each press.

Notice that we use form.Page instead of this.Page. When you use this code you must remember that you are working with two separate Page instances. One for the View and the other for rendering the control. In this example we use RegisterStartupScript to display an alert box. If you were to have used this.Page.ClientScript, nothing would happen.

It’s a subtle difference that you are going to want to keep in mind while you use this class.

Example 3 — MvcControlGroup

So far all of our examples have only used a couple controls that were all rendered inline with the rest of the page. While this is going to work in most situations, some places won’t work as well.

The example below shows how you can use the MvcControlGroup to group controls together, for example, the Wizard control.

<html>
    <head runat="server">
        <title>Using Events</title>
    </head>
    <body>    
        <h2>Using Wizard Control with MvcControlGroup</h2>
        <div>
        <% this.Html.WebForm((form) => { %>
        <mvc:MvcControlGroup runat="server" >
        <asp:Wizard runat="server" >
            <WizardSteps>
                <asp:WizardStep runat="server" Title="Personal Information" >
                    <p>Leaving fields blank will catch the validators.</p>
                    <strong>Name</strong>
                    <asp:TextBox ID="name" runat="server" />
                    <asp:RequiredFieldValidator runat="server" 
                        ControlToValidate="name" ErrorMessage="Must provide a name" />
                    <br /><br />
                
                    <strong>City</strong>
                    <asp:TextBox ID="city" runat="server" />
                    <asp:RequiredFieldValidator runat="server" 
                        ControlToValidate="city" ErrorMessage="Must provide a city" />                    
                </asp:WizardStep>
                
                <asp:WizardStep runat="server" Title="Reservation Date" >
                    <strong>Date Requested</strong>
                    <asp:Calendar ID="date" runat="server" />                 
                
                </asp:WizardStep>
                
                <asp:WizardStep runat="server" Title="Confirm" >
                    
                    <h2>Confirm This Order?</h2>
                    <p>This step maps to a Controller Action before submitting</p>
                    
                    <% MvcWebForm.Current.Action = "/Projects/MvcWebForms/Submit"; %>
                    <% MvcWebForm.Map(() => new {
                        name = name.Text,
                        city = city.Text,
                        date = date.SelectedDate.ToShortDateString()
                       }); %>
                       
                </asp:WizardStep>
            </WizardSteps>
        </asp:Wizard>
        </mvc:MvcControlGroup>
        <% }); %>
        </div>
        
    </body>
</html>

Just like with other controls, the MvcControlGroup must be rendered in a separate page instance. This control moves it to the correct context before it is processed.

If you remember, the idea behind this project was to allow people to use WebControls with Mvc — not just use WebControls in Mvc. On the last step we point our form to a Controller Action and use a method called Map to format our information for the postback.

When the user finished the Wizard they can post the finished form back to the correct Controller Action!

**whew** — that’s a lot to take in!

Limitations

There are a couple limitations that still need to be worked through…

  • HTML output must be well formed – If your control outputs bad HTML, this thing will croak. The reason is that instead of using Regular Expressions to try and match content the output is parsed using the XDocument.
  • PageMethods, AJAX calls will probably not work – Controls like the UpdatePanel or using PageMethods will most likely not work anymore. Some additional work is going to be required to make those work.

I’m sure there is more that needs to be looked at but at this point it seems as if it can be used — at least for testing.

Please let me know if you have any ideas, feedback or suggestions! I’m going to continue to work on this and see what kinds of improvements can be made.

Source Code

Download MvcWebForms.zip

.

Written by hugoware

August 12, 2009 at 8:58 pm

The Super Secure HttpRequest

with 3 comments

I’ve been working on a little project lately to see if it is possible to use WebControl inline with ASP.NET MVC. It’s been going well so far, but I encountered a little, tiny, insignificant problem… actually, it’s quite a big problem.

The general idea behind the project was to display the normal view, use the inline code to create a second instance of a page, render the content with the correct ViewState information, and then output the content back onto the ViewPage so it can be used.

Now passing a ViewState into the wrong type of page causes some problems. To get around it we simply rename our ViewState to something else and then change the name back when the page is being loaded in our code. It worked well when I was creating a new HttpRequest object, but the problem is that if you create one manually, it changes to a GET request — not a POST!

At first I figured that I would just get in there and reuse the same HttpRequest and make a few changes, but it wasn’t going to be that easy. The problem is that you just can’t do anything to the HttpRequest — Anything!! Try to change the parameters? Read-Only. Try to inherit from the StateBag? Sealed. Inherit from the HttpRequest itself? Sealed! Holy cow!!

I’ve been battling this quite a bit and at this point I’m feeling defeated (and a little grumpy). I’m trying to find a point that I can make a change to the incoming data, but before the ViewState is loaded by the WebForm page.

After going round and round for awhile I’m starting to think my best (maybe only) option is to get work with the HttpApplication class. Not exactly what I was hoping for, but it may be my only option at this point.

… let’s just hope not everything is read only in this class as well.

Written by hugoware

August 10, 2009 at 1:47 am