Archive

Archive for the ‘JavaScript’ Category

AJAXing in .NET – #3 – Live Volta and Script#

January 8, 2008 Comments off

This is the third and final part of the series looking at several “AJAXing” technologies for .NET—ranging from “old school” JavaScript to new, VERY alpha technologies like Volta.

Post 1:

  • Example #1 – Plain ASP.NET Page with PostBacks
  • Example #2 – ASP.NET AJAX with UpdatePanels

Post 2:

  • Example #3 – Standard HTML and JavaScript
  • Example #4 – ASP.NET AJAX Framework and JavaScript

Post 3 (this post):

  • Example #5 – Nikhil Kothari’s Script#
  • Example #6 – Microsoft Labs Live Volta

This post, to be totally honest, will be short.  Why?  After FAR too long of dinking with them, I simply can’t get either solution to work.  Here’s where I’m at NOW.  Once I get these working, I’ll better evaluate them against current JavaScript solutions.  That said, the sheer idea of learning a language to avoid writing a language seems odd at best…

#4. Microsoft Live Labs Volta

I previewed Microsoft Live Labs Voltron Volta back in December and was quite impressed—a Microsoft-designed solution for creating type-safe JavaScript within C#.  I wasn’t thrilled with the special project layouts or 45K of compiled Volta code that attached to each project; however, it’s in … alpha, I expected that.

In our Volta code-behind, we have the following logic. 

public partial class VoltaPage1 : Page

{

 

Select photoList;

Image photoPreview;

 

public VoltaPage1()

{

InitializeComponent();

photoList.Change +=

new HtmlEventHandler(photoList_Change);

}

 

void photoList_Change()

{

photoPreview.Style.Display = “block”;

       photoPreview.Src =  “Images/” + photoList.Value;

}

 

partial void InitializeComponent()

{

photoList =

Document.GetById<Select>(“PhotoList”);

photoPreview =

Document.GetById<Image>(“PhotoPreview”);

}

}

That compiles, is easy to read, and type safe.  Neato.  The HTML code is identical to our prior examples, so a simple copy and paste from there.  That saves some time.

The problem?

It appears that Volta doesn’t appreciate resources that are not embedded.  I’ve posted up to the Volta community groups and will slowly work through either a) rectifying what the correct code should be or b) accepting that this is “outside the scope” of the current Volta design.  I can’t fathom having hundreds of embedded resources in a project—for simple graphics.

Finally, it appears the problem that Henry discussed in my last post also exists in Volta—Document.GetById isn’t case sensitive at all. :(  Thanks Henry for the heads-up to keep that in mind!

[Update: 10 January 2008 : Danny van Velzen’s explaination in the forums helped out a lot.  At this time, as expected, the CTP simply doesn’t support anything besides embedded resources; however, has logged the request as a future work item.  *cheer*  To work around this problem, he recommended a post-build event, which is basically a batch command.  I’ve tried that out and this example works like a champ!

The only gotcha is figuring out where to copy the files to and what correlates to the “root” of your application.  It’s not the root of our bin\Debug or bin\Output.  It’s the Volta directory underneath.  With that information, you can write up a quick event:

xcopy /i /y “$(ProjectDir)Images” “$(TargetDir)Volta\Images”

Given this simply copies the images for this prototype project; however, you could use these events to copy pages, .css, or anything that you didn’t feel like “embedding” into your project.  As I noted on the Volta communities post—I’m looking forward to this maturing and having this functionality built into the compiler. :)

With this updated information, I can finally compare implementation with our other options..

  • HTML Code: 9, Code Behind: 5 with whitespace and method names.
  • To me, this code is just as simple to read as JavaScript—maybe a bit easier because it’s strongly typed and hooks up event handlers just like .NET code.
  • All tests come back clean—and Volta supports FireFox debugging out-of-the-box, which is great because I have come to prefer FireBug over the IE Developer Toolbar.
  • Pitfalls are, at this time, the fact it’s VERY alpha and still in development.  Most of the DOM appears to be ready to go, however, issues like the embedded resources make this impractical for production use at this time.  In addition, Volta requires a special project type for its tier-splitting—you can’t just drop some Volta/JavaScript into a project and go.  That’s a HUGE drawback to me.  I’d love to see the technology integrated into the existing web platform so I could program JavaScript like this against Web Forms, MVC, or whatever.

#5. Script# 0.4.5.0

The latest build of Script#, 0.4.5.0, appears to have a few glitches in the Scriptlet editor (cutting out the top and bottom lines, throwing compile errors when they don’t exist, etc) and after blowing through about a dozen project—it just won’t compile.  Period. 

Here’s the code for the class.  It looks right, from what I have as examples, but blows up that I have extra “}” (which is a known bug apparently) and believes that my IDisposable doesn’t exist, though I see it right there. :(

using System;

using System.DHTML;

using ScriptFX;

using ScriptFX.UI;

 

public class Viewer : IDisposable

{

    private SelectElement _photoList;

    private ImageElement _photoPreview;

    private DOMEventHandler _photoListOnChangeHandler;

 

    public Viewer()

    {

        _photoListOnChangeHandler =

new DOMEventHandler(PhotoListOnChange);

        _photoList =

(SelectElement)Document.GetElementById(“PhotoList”);

        _photoList.AttachEvent(“onchange”, _photoListOnChangeHandler);

    }

 

    public void PhotoListOnChange()

    {

        _photoList =

(SelectElement)Document.GetElementById(“PhotoList”);

        _photoPreview =

(ImageElement)Document.GetElementById(“PhotoPreview”);

 

        _photoPreview.Src = “Images/” + _photoList.Value;

    }

 

    public void Dispose()

    {

        if (_photoListOnChangeHandler != null)

        {

            _photoList =

(SelectElement)Document.GetElementById(“PhotoList”);

            _photoList.DetachEvent(“onchange”, _photoListOnChangeHandler);

 

            _photoListOnChangeHandler = null;

        }

    }

}

I’m going to keep working with it (because the prototypes I have gotten working have worked well, but also don’t seem to work under 0.4.5.0) and I’ll update this post when I have more information.  If anyone out there is a Script# expert and has 0.4.5.0 up and going with VS2008, email me, please. :).

AJAXing in .NET – #2 – Pure JavaScript and AJAX Framework JavaScript

January 7, 2008 7 comments

This is the second in the three part series looking at “AJAXing” technologies for .NET developers.

Post 1:

  • Example #1 – Plain ASP.NET Page with PostBacks
  • Example #2 – ASP.NET AJAX with UpdatePanels

Post 2 (this post):

  • Example #3 – Standard HTML and JavaScript
  • Example #4 – ASP.NET AJAX Framework and JavaScript

Post 3 (this post):

  • Example #5 – Nikhil Kothari’s Script#
  • Example #6 – Microsoft Labs Live Volta

In these two examples, we’ll take a look at the differences of JavaScript programming—between “standard” JavaScript and using the methods and objects provided by the ASP.NET AJAX Framework, but without using the actual server-side controls.

#3. Standard HTML and JavaScript

The next example is a classic—clean HTML and a JavaScript function.  This is a standard HTML page without any “fancy” .NET or framework technologies.  How does this compare to .NET?

In our header, there’s a simple JavaScript function to handle the OnChange event of the drop down list:

<script type=”text/javascript” language=”javascript”>

function LoadPhoto()

{

PhotoPreview.style.display = ‘block’;

       PhotoPreview.src = Images/ + PhotoList.value;

}

</script>

Next, our HTML.

<select id=”PhotoList” onchange=”LoadPhoto()”>

<option label=”ABCs – Blocks” value=”abc_blocks.jpg” />

       <option label=”ABCs – Chalkboard #1″ value=”abc_board.jpg” />

       <option label=”ABCs – Chalkboard #2″ value=”abc_board2.jpg” />

       <option label=”Graduation” value=”capandgown.jpg” />

</select>

<br /><br />

<img id=”PhotoPreview” style=”display: none; src=”” />

As we can see from the Fiddler capture, the HTML, of course, is EXTREMELY thin here and, since postback events are not firing, the page ever reloads, simply loads the resources (in this case, images) as necessary.  In addition, the images are cached, so additional downloading isn’t necessary..

  1. HTML Code: 8 + 2 4 JavaScript function lines (see below).
  2. I may be a bit older, but this is how it “used” to be done, so it’s readable to me.  For those unfamiliar with JavaScript may be turned off by it.
  3. IE 7 and Safari (*shocked*) work, however, Opera and FireFox are broken.  See details below.
  4. As you’ll read below, managing compatibility between JavaScript functionality on each platform is a HASSLE and can be a major turn off for DIY JavaScript AJAX.

Details for Compatibility Issues:

IE 7 and Safari actually render correctly because they use the “label” property from HTML 4.0 for option boxes.  FireFox and Opera turn out blank.  To have options in those browsers, we’ll need to place the text in the body of the tag. 

<option label=”ABCs – Blocks” value=”abc_blocks.jpg”>
ABCs – Blocks
</option>

That fixes Opera, but FireFox is still broken.  Why?  Because FireFox can’t read the DOM directly, you have to populate each element into a variable and manipulate the variable.  Updating our JavaScript to the following code will fix the problem.  Also, since this method works in all the OTHER browsers, this would be the “preferred” method to accomplish this.

var photoPreview = document.getElementById(‘PhotoPreview’);

var photoList = document.getElementById(‘PhotoList’);

 

photoPreview.style.display = ‘block’;

photoPreview.src = ‘Images/’ + photoList.value;

While this code works, you can run into challenges for browsers that do not yet support getElementById.

#4. ASP.NET AJAX Framework and JavaScript

In our last example, browser compatibility was the most challenging pitfall to overcome.  If we want to write our own JavaScript, but would like the padding of a framework, we can use the ASP.NET AJAX framework without all the fancy server-side controls.

When we add a new AJAX Web Form, a single control is added, the ScriptManager.  In this example, we’re not going to use UpdatePanels, but simply access the objects provided for us by the ScriptManager.

The JavaScript in our Header:

<script type=”text/javascript”>     

function LoadPhoto() {    

       $get(‘PhotoPreview’).style.display = ‘block’;

       $get(‘PhotoPreview’).src = ‘Images/’ + $get(‘PhotoList’).value;

}

</script>

And the HTML:

<asp:ScriptManager ID=”ScriptManager1″ runat=”server” />

<select id=”PhotoList” onchange=”LoadPhoto()”>

<option label=”ABCs – Blocks” value=”abc_blocks.jpg”>

              ABCs – Blocks</option>

<option label=”ABCs – Chalkboard #1″ value=”abc_board.jpg”>

              ABCs – Chalkboard #1</option>

<option label=”ABCs – Chalkboard #2″ value=”abc_board2.jpg”>

              ABCs – Chalkboard #2</option>

<option label=”Graduation” value=”capandgown.jpg”>

              Graduation</option>

</select>

<br /><br />

<img id=”PhotoPreview” style=”display: none; src=”” />

The $get alias simply returns browser-compatible JavaScript for getElementById.  You can read more about how this alias works on Irena Kennedv’s blog.  The short is that this alias will generate the correct code based on the browser.

The Fiddler logs are nearly identical to the plain JavaScript; however, the .aspx page is a bit heavier.

  1. HTML Code: 9 + 2 JavaScript function lines.
  2. Aside from familiarization with the aliases and framework functions in JavaScript, this code is nearly identical to the
  3. The only difference at this point is that the code allows us to access the $get alias and, most importantly, cross-browser compatibility handled by the framework—not you.
  4. Past the bit of losing “update panels”, this is a nice middle ground between pure JavaScript and pure server-side AJAX Framework.

This methodology also has another benefit: you can directly access web services (.asmx) from your JavaScript client code.  For more information on this topic, read Calling Web Services from Client Script.  I haven’t done a lot with this yet, but have a few notes sitting around to give it a try and see how it compares when reading actual data across the wire.

AJAXing in .NET – #1 – Plain ASP.NET and ASP.NET AJAX

January 7, 2008 2 comments

With the release of Microsoft Live Labs Volta, Nikhil Kothari’s recent update of Script# to support VS 2008, the ASP.NET AJAX Library’s new functionalities, and good ‘ol JavaScript—developers are not limited on AJAX solutions for the Microsoft platform.  Given, JavaScript can be on any platform, I tend to focus more on .NET solutions. :)

One of my holiday projects was to weigh and see exactly what went back and forth across the wire for each of these technologies and compare that to:

  • Implementation lines of code,
    • I don’t count using statements, headers, and “required” coding lines, simply those lines that implement the solution.
  • Intuititiveness of code,
    • Does the code make sense to write?
  • Browser support,
    • Does it work and look the same on IE 7.0, FireFox 2.0, Opera, and Safari?
  • Weight of transmissions (using Fiddler).
    • How much data is going across the line for comparable transactions?
  • Pitfalls?
    • What are the gotchas?

Download Source Code : Download Project Solutions (coming soon)

Note: This project contains two solutions, one for Volta project and one for all the others.

To make this a bit easier to read (and to write :) ), I’ve broken the content into a series of posts.

Post 1 (this post):

  • Example #1 – Plain ASP.NET Page with PostBacks – Seeing our prototype page with standard ASP.NET—no AJAX.  This will provide our baseline.
  • Example #2 – ASP.NET AJAX with UpdatePanels – The “default” implementation of the ASP.NET AJAX Framework—using UpdatePanels to manage partial rendering with “postbacks” still happening in the background.

Post 2:

  • Example #3 – Standard HTML and JavaScript – This is the “old” way to do things: directly manipulating the DOM.
  • Example #4 – ASP.NET AJAX Framework and JavaScript – Manipulating the DOM using the aliases and cross-browser compatibility features of the AJAX Framework.

Post 3:

  • Example #5 – Nikhil Kothari’s Script# – Script# is a scripting solution that sits on top of the C# development environment.
  • Example #6 – Microsoft Labs Live Volta – Previewed before, we’ll build the same example as the rest of the examples in Volta for comparison.

Now, let’s get started!

#1. Plain ASP.NET Page – Postbacks

Moving into .Net, let’s start with a simple ASP.NET page—no AJAX involved.  This page has a drop down list (PhotoList) and an image control (PhotoPreview)—populating the image control OnChange of the drop down list.

<asp:DropDownList ID=”PhotoList” runat=”server” AutoPostBack=”true”

OnSelectedIndexChanged=”PhotoList_SelectedIndexChanged”>

<asp:ListItem Text=”ABCs – Blocks” Value=”abc_blocks.jpg” />

<asp:ListItem Text=”ABCs – Chalkboard #1″ Value=”abc_board.jpg” />

<asp:ListItem Text=”ABCs – Chalkboard #2″ Value=”abc_board2.jpg” />

<asp:ListItem Text=”Graduation” Value=”capandgown.jpg” />

</asp:DropDownList>

<br /><br />

<asp:Image ID=”PhotoPreview” runat=”server” Visible=”false” />

In our code behind:

protected void PhotoList_SelectedIndexChanged(object sender, EventArgs e)

{

PhotoPreview.ImageUrl = “~/Images/” + PhotoList.SelectedValue;

       PhotoPreview.Visible = true;

}

Using Fiddler, an HTTP debugging tool, we can see that each time the page is requested, it posts back and grabs the image.  It’s also important to note that there isn’t any caching at this point.  Notice how events #39 and #43 request the same image and transmit it.

Using our scale above:

  • HTML Code: 9, Code Behind: 2
  • Being standard HTML and .NET code-behind, this is easily readable and makes sense. 
  • As we can see from the image below, the page looks much the same on every browser (given, it’s pretty basic).  The browsers, clockwise from top-left, are: Safari b3, IE 7, Opera 9, and FireFox 2.
  • Avoid postback “flash” is the most common, I think, to implement some sort of AJAX technology—cleaning up a UI and improving the user experience.  The lack of caching (with the post back) is also a trouble; however, caching could be implemented with additional coding.

#2. ASP.NET AJAX with UpdatePanel

Our first method would be the standard ASP.NET AJAX technique—surrounding those two controls with an UpdatePanel and adding a ScriptManager to the page.

<asp:ScriptManager ID=”ScriptManager” runat=”server” />

<asp:UpdatePanel ID=”UpdatePanel” runat=”server”

UpdateMode=”Conditional”>

<ContentTemplate>

<asp:DropDownList ID=”PhotoList” runat=”server”

AutoPostBack=”true”

OnSelectedIndexChanged=”PhotoList_SelectedIndexChanged”>

<asp:ListItem Text=”ABCs – Blocks” Value=”abc_blocks.jpg” />

<asp:ListItem Text=”ABCs – Chalkboard #1″ Value=”abc_board.jpg” />

<asp:ListItem Text=”ABCs – Chalkboard #2″ Value=”abc_board2.jpg” />

<asp:ListItem Text=”Graduation” Value=”capandgown.jpg” />

</asp:DropDownList>

<br /><br />

<asp:Image ID=”PhotoPreview” runat=”server” Visible=”false” />

</ContentTemplate>

</asp:UpdatePanel>

While our UI hasn’t changed, our HTTP traffic has changed quite a bit.  Here we can see the WebResource and ScriptResource files pull down to the local client and cache as well as the first load of the page.  What is interesting here is that on request #89, I’ve rerequested the capandgown.jpg image, but it never re-requests it, the cached image just loads on the client.  Good deal and MUCH faster.

Using our scale above:

  • HTML Code: 14, Code Behind: 2
  • This is the basic way of implementing the ASP.NET AJAX Framework—enclosing existing controls in panels and letting partial rendering do it’s magic.  I see this as very intuitive syntax.
  • Functionality is identical on all four platforms; this is because the ASP.NET AJAX framework handles browser support for us via ScriptManager.
  • As you can see from the Fiddler log, this page is extremely heavy—trading off smooth performance during usage for a resource load at the page load.

Flash and Proxy Support on .NET WebBrowser Controls

January 3, 2008 10 comments

At work, I’ve been dealing with Big Brother for the past few weeks (well, before the holiday break)—attempting to both accomplish a bit of work and some play in light of our annoying filter (blocking MSFT blogs, forums, community sites, and almost all useful search engines).

I love Daniel Mackey’s Pandora’s Box application, an encapsulation of the web browser for playing Pandora; however, it doesn’t support proxy servers.  I found a few other players, but, it appears, that IE 7 screws up a few things and the proxy settings don’t work correctly.  Bleh.  So, okay, it’s web browser and I’m a web developer—this can’t be that hard.

Heh.  If I only had a dollar for each time I said that…

Creating a Flash-enabled WebBrowser Control

One of the drawbacks to the current .NET WebBrowser control is that Flash, for some reason, can’t operate.  It just sits there—staring back at you.  I came across a post a few months ago to fix this.  It was originally targeted at 2.0, but seems to work just fine in 3.5

The fix?  Create a new user control and inherit from the WebBrowser control.  The only work is to override the WndProc method:

protected override void WndProc(ref Message m)

{

switch (m.Msg)

       {

             case 0x021:

             case 0x201:

             case 0x204:

             case 0x207:

                     base.DefWndProc(ref m);

                    return;

}

base.WndProc(ref m);

}

If you’re not familiar with how Windows forms messages are processed, you can find more information on MSDN.

Important: If you’re developing on an x64 (64–bit) machine, you must change your compile target platform to x86 (32–bit).  The WebBrowser control renders according to your platform—x64 in 64–bit, x86 in 32–bit.  Most of us use the 32–bit version of Internet Explorer on our x64 Windows because plugins, such as Flash, only have 32–bit editions.  In this case, Flash will not be able to load under the x64 WebBrowser control and will throw errors.

Implementing the Flash-enabled WebBrowser Control

I’m not real original on my control names… my derived control is called FlashWebBrowser.  Good deal.

To implement the control, add a Form to your page and size accordingly.  You can drag/drop your controls onto the form; however, for this example, I chose to do everything in code behind.

public partial class PandoraForm : Form

{

private FlashWebBrowser flashBrowser = new FlashWebBrowser();

 

       public PandoraForm()

       {

            InitializeComponent();

            flashBrowser.Dock = DockStyle.Fill;

            flashBrowser.AllowWebBrowserDrop = false;

            flashBrowser.IsWebBrowserContextMenuEnabled = false;

            flashBrowser.WebBrowserShortcutsEnabled = false;

            flashBrowser.ScriptErrorsSuppressed = true;

                       

            Controls.Add(flashBrowser);

            Load += new EventHandler(Form1_Load);

       }

Our flashBrowser object applies a few common attributes, such as filling the form and locking out the context menus.  Also, you’ll notice ScriptErrorsSuppressed.  Any JavaScript errors will pop-up automatically using the WebBrowser control (on IE, they’re visible in the status bar and only displayed if you explicitly have the option set to); this causes quite a bit of annoyance using services like Pandora, Google, and Flickr.  ScriptErrorsSuppressed will… suppress those errors.

Information: I’d like to caveat that last statement with a note.  It will USUALLY suppress those errors.  For some reason, IE 7.0 seems to ignore that statement and still throws the errors.  *sigh*  More information can be found ala Google.  I’m still researching this and hope to have a better understanding soon.

Our final method, Form1_Load as specified above, simply contains our flashBrowser’s Navigate method.

private void Form1_Load(object sender, EventArgs e)

{

flashBrowser.Navigate(http://www.pandora.com/?cmd=mini&#8221;);

}

Implementing Proxy Support for the WebBrowser Control

I haven’t cleaned this up into the FlashWebBrowser control yet, but I wanted to post this up for those interested.  Proxy support is REALLY useful if you’d like a particular application or service to use a proxy server, but don’t want to deal with the hassle of constantly changing your Internet settings.

You could use the HttpWebRequest object, pass along a WebProxy, and go that route.  However, quite honestly, I haven’t worked out how you can apply that to a WebBrowser control—only at the console.  I’m sure it can be done and may be more secure than this method, but this forum code works.

Cleaned up, the code looks like:

public struct INTERNET_PROXY_INFO

{

public int dwAccessType;

public IntPtr proxy;

public IntPtr proxyBypass;

};

 

[DllImport("wininet.dll", SetLastError = true)]

private static extern bool InternetSetOption(IntPtr hInternet,

int dwOption, IntPtr lpBuffer, int lpdwBufferLength);

 

private void RefreshIESettings(string strProxy)

{

const int INTERNET_OPTION_PROXY = 38;

const int INTERNET_OPEN_TYPE_PROXY = 3;

 

INTERNET_PROXY_INFO struct_IPI;

 

// Filling in structure

struct_IPI.dwAccessType =

INTERNET_OPEN_TYPE_PROXY;

struct_IPI.proxy =

Marshal.StringToHGlobalAnsi(strProxy);

       struct_IPI.proxyBypass =

Marshal.StringToHGlobalAnsi(“local”);

 

       // Allocating memory

       IntPtr intptrStruct =

Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI));

 

       // Converting structure to IntPtr

       Marshal.StructureToPtr(struct_IPI, intptrStruct, true);

 

       bool iReturn = InternetSetOption(IntPtr.Zero,

INTERNET_OPTION_PROXY,

intptrStruct,

Marshal.SizeOf(struct_IPI));

}

wininet.dll is the Windows library that contains most of the internet functions used by Windows and Windows-based applications.  Proxy settings are not the only things configurable using this API; for more information, read here.  Also, for a full understanding of what this code is doing, MSDN has a nice walkthrough demonstrating the various options and how to get/set them.

With that method added to our project, there’s only one change needed—we need to call our RefreshIESettings method prior to the Navigate method of our WebBrowser control.  Our Form1_Load method now looks like:

private void Form1_Load(object sender, EventArgs e)

{

RefreshIESettings(“myproxy.server.com:99″);

       flashBrowser.Navigate(http://www.pandora.com/?cmd=mini&#8221;);

}

I want to integrate the proxy settings INTO the WebBrowser control—and still might.  When that’s done, I’ll post up the code.  For now, however, that’s it.  We now have a WebBrowser control and a baby Windows Forms application that loads up a Flash site, like Pandora AND goes through a proxy server (so I can sit and listen to tunes at work OR be productive and access the MSFT community forums).  Good deal.

Microsoft Live Labs Volta Framework

December 12, 2007 3 comments

This is the first post in a series that will discuss some of the new web development frameworks that have come out the past few weeks that revolve around the .NET development platform.

Microsoft Live Labs Volta

Microsoft Live Labs recently released a new web development platform/toolset codenamed Volta (http://labs.live.com/volta/).  Built as a toolkit extension package for Visual Studio 2008, Volta removes the developer from dealing with the complexity of rolling out multi-tiered web applications and handling when and where client/server activities take place—that’s all a check box for “on” or “off”.

How does it do it?  Well, from what I can tell, with a LOT of JavaScript—almost 45KB of JavaScript between the “compact.js” and “VoltaManagedInteropHelpers.js” files that are attached to every compiled Volta project.

Labs defines the project as:

The Volta technology preview is a developer toolset that enables you to build multi-tier web applications by applying familiar techniques and patterns. First, design and build your application as a .NET client application, then assign the portions of the application to run on the server and the client tiers late in the development process. The compiler creates cross-browser JavaScript for the client tier, web services for the server tier, and communication, serialization, synchronization, security, and other boilerplate code to tie the tiers together.

If you have Visual Studio 2008, you can download the package and give it a try.  The most surprising “design requirement”?  Volta has built in support for Firefox 2.0 and higher—with debugging tools and all.  Impressive and leads more to the fact that not ALL of MSFT is addicted to IE.

I’ll by pass the typical “hello, world” project—you can view that here on the Labs site.  The walkthrough details how to create a project, linking to the DOM, etc.  What I’m going to create is CIS 100 Project #2–-adding and subtracting two numbers.  With this, a bit of discussion regarding the work that goes into this.

Source Code For This Post: Download .NET 3.5 Version

NOTE: Before we start, the current CTP (read: alpha) build of Volta seems to have one glitch—there isn’t a way to create NEW pages within Volta Applications.  I’m not sure if this is an architectural design decision or simply missing templates.  If you try to copy the existing page, it copies, but you can’t rename the embedded resources from “Copy of…”.  Annoying.

Elements of a Volta Page

One of the unique aspects, so far, to Volta is the project structure.  If you look at your project, you see two files: Program.cs and VoltaPage1.cs.  To being, the rest of the logic (specifically design logic) exists as embedded resources to VoltaPage1.

Each page comes three embedded files: favicon.ico, Page.html, and {PageName}.designer.cs.  

Project Layout in Volta.The favicon.ico is a neat feature that, quite honestly, I usually forget to put in web sites.  The “Favorites” icon shows up in, you guessed it, the user’s favorites and in the Title bar when visiting the page.

Page.html is the interface of the page, generated in pure HTML.  No .NET controls, nothing fancy—just labels, textareas and buttons.  It took me a while to NOT type <asp:…>.

{PageName}.designer.cs is, for lack of a better description, similar to the AssemblyInfo.cs file in other web design projects.  It contains the pointers to the html page, icons, and is where you can reference external scripts.

Creating the User Interface / Presentation “Layer”

Now that we’ve discussed the elements of a page, let’s get into writing some exciting HTML.  Well, not really, but it’s nice and clean HTML.

Page layout from page.html

Our page (page.html) has 5 elements – two input boxes, two buttons, and a label.  Feeling 1999, yet?

Creating the Business Logic

Now, we need to “attach” our Volta code to the objects in the DOM.  This takes place in the class file for our file.  In my case, it’s Calculator.cs.  As with a regular WebForms application, the class file inherits from the Page class—except it’s not System.Web… it’s from Microsoft.LiveLabs.Volta.Html.Page. 

WARNING: Be careful, classes and objects you MAY be familiar with are reused within Volta—check the full class path when you add in a class, it’s likely you’re attaching to specific Volta objects, not web objects.

Our first task is to create the private variables to hold our DOM objects.

Creating private variables for the DOM objects.

Next, creating the link between our private variables and the DOM objects.  This is handled by our InitializeComponent method.

Linking the private variables to the DOM using generics.

The syntax looks very similar to JavaScript, which really helps out.  You’ll also notice that GetById is a generic method, accepting any type of Type you wish to pass to it and keeping everything strongly typed.

Once we’ve specified the private variables, we need a public constructor to build the page and wrap up any events we need, such as clicking on the buttons.  You can wrap events two ways: through specifying a new HtmlEventHandler or using a delegate.  I’ve demonstrated both here—and both work; it’s a matter of preference.

Adding event handlers to the public constructor.

The GetInputValues method is a quick helper method to refactor out converting the two input boxes from strings to integers.

Generated HTML

With that in place, what does the generated HTML look like?

<HTML><HEAD><TITLE>LearningVolta - Calculator</TITLE>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<LINK href="/favicon.ico" rel="shortcut icon"> <STYLE type=text/css> </STYLE> </HEAD> <BODY> <H2>Simple Math</H2> <P>First Number: <INPUT id=FirstNumber value=1>
<BR>Second Number: <INPUT id=SecondNumber value=2></P> <P><BUTTON id=AddButton>Add</BUTTON>&nbsp;
<BUTTON id=SubButton>Subtract</BUTTON></P> <P><LABEL id=Result>3</LABEL></P>
<![if !IE]><script src="compact.js"></script>
<![endif]>
<script src="VoltaManagedInteropHelpers.js"></script>

</BODY>
</HTML>

It’s interesting to note that the generated HTML isn’t identical to what I put in page.html, which means that even the HTML is being interperted by the Volta engine. 

Second, the page is slim—even to the point of not having visible JavaScript.  At this point, everything is being handled client-side and, I’m assuming, is handled through those two external JS files. 

So, how can we change that?  We can start by enabling the “Volta tier-splitter” toggle and adding a few attributes to our methods.

Enabling Tiersplitting

Project Properties | Volta | check “Enable Volta tiersplitter”

Next, we can add an attribute to our CalculatorLogic (the Add and Subtract methods) to run those on the server.  This can be done two ways.  First, right-click on the method and Refactor “Tier-split To Run at Origin”… or just type the attribute.

Adding RunAtOrigin tags.

In my mind, RunAtOrigin is simply another way to say RunAt=”server”

Run the project again and open the Volta WebServer (swirly pink icon in the system tray).  Check “Log Requests” and attempt add up a few numbers.  You’ll see now that there is a post back event; however, the HTML code hasn’t changed—Volta is taking care of that.

Volta POST and GET in the Web Server logs.

Now that we’re running on the server, we can add a bit of AJAX into the mix using the Async attribute.

From what I’ve gathered in the documentation and poking around the model, Async methods are called as external methods and require the extern keyword.  There isn’t a specified DllImport like you may be used to; I’m assuming the Async takes it’s place—”hey, I’m “outside the client”, so check all the rest of the code for this method.”  Hopefully that architecture will be cleared up as further releases come out.  For now, it’s just the way it works.

To test this, we’ll add two more buttons: Add Async and Subtract Async.  Be sure to add them in all three places—page.html, the private variables, and the init method to link the two together.

Async Callbacks in Volta

The callback parameter replaces the prior assignment used for the non-async method.  Using the pattern from the Volta guides, we can use a lambda expression here to specify where the output is going.  Also, as you can see, you can use both EventHandlers or inline delegates.

Handling the ASync Events.

When you run the page, you’ll notice the “delay” (the buttons stay stuck down while it processes) that existed on the regular add and subtract doesn’t exist on the Async buttons. 

Conclusion

So far, it’s an interesting technology.  Everything I’ve done here could have easily been written in JavaScript—without code behind or anything else—or even ASP.NET WebForms; however, the async stuff is kinda nice and tidy—keeping everything in the CLR.

I’m not sure I’m into letting my web server handle everything—at least not yet, but keeping everything separated out—HTML for presentation and C# for everything else (even manipulating the browser itself) is pretty nice.

I look forward to seeing how this project matures and integrates into some of the other new development frameworks, like the .NET MVC patterns.  For now, it’s a good start and excellent step in adding functionality we’ve coded around for so long.

So many .NET Frameworks – Which is which?

December 10, 2007 3 comments

Over the past few weeks, Microsoft have been hammering out frameworks and structures for .NET Development. 

Microsoft Voltron Volta

Earlier last week, Microsoft Live Labs released the prototype of Microsoft Volta, a “let’s do AJAX and control the DOM without writing JavaScript” framework that is pretty cool.  I’ve whipped up a few examples that I’ll post up later today. 

The dream is that the system manages the tiered architecture of design—and automagically refactors your code onthe fly.  Think of the syntax an odd mix of Astoria (web-based data services), Nikhil Kothari’s Script# access to the DOM from C#-esque code, and Volta’s new twist of tags and attributes for async transactions—all mixed into one bit application.

So, is this the platform of the future?  AJAX-ala-C# and full DOM control with automagic architecture separation?

And yes, I keep accidently calling it Voltron.

Microsoft MVC Framework (ala 3.5 Extensions CTP)

Finally!  Late last night, ScottGu announced that the .NET 3.5 Extentions were available; read all about it and download the bits from his blog.

The MVC framework sites at the same .NET revolutionary stage as LINQ (in my opinion)—something that .NET has been missing for quite a while.  During the short works I’ve had with Java, the clear break between the layers of development made swapping in and out forms quite simplistic.  I followed a similar path with .NET development, but this required a bit more work and didn’t flow quite as easily (and you had to hand code all the handlers).

So, is this the platform of the future?  True tiered separation at design time and a step closer to the Ruby/Java world?

Silverlight 1.1 2.0 Alpha

While the Silverlight still boasts the 1.1 version number, the drastic changes between the two version (and the rumors from Microsoft) will probably see it at 2.0 when it hits CTP.  I would like to have a few good examples to show regarding Silverlight (the prototypes on Silverlight.net are fun to play with), however, I’ve yet to get the VS2008 Extentions to work—I can create, but it won’t accept that I have Silverlight installed.  :(.

So, is this the platform of the future?  Rich, interactive applications using XAML markup and XML templates?

.NET WebForms Development

This isn’t new, but the changes in .NET 3.5 for WebForms and AJAX can’t discount this medium.  I, for one, am still more comfortable with this than the “new fangled” technologies and find the latest tools that are out (VS2008, the new controls in .NET 3.5, and even the extensions that keep coming) are making WebForms easier and easier to create.  Also, while the “new” may be cool, we have a slew of existing applications that can’t be forgotten.

So, is this the platform of the future?  The pluggable framework and web forms that allows for the easy creation of anything from personal web sites to enterprise applications?

 

For now, the my gut feeling is that the “platform of the future” is what works for the situation.  I can think of a few of our minor “web applications” that have no need for the complexity of Volta, MVC, or Silverlight; however, I cannot ignore the specific appears to each of the technologies for future projects.  I do not believe that these REPLACE our current WebForms, but simply add additional tools to the toolkit (and requirements for us to learn).

It keeps it new and exciting!

 

Creating a Modal Popup Template Control

November 5, 2007 8 comments

Download : .NET 3.5 Source Project

The ModalPopupExtender is one of my favorite AJAX extenders.  It provides a slick UI experience for little overhead.  The most difficult part of implementing the extender is recreating the popup panels over and over again for similar tasks.

ModalPopupTemplate with Matt Berseth's YUI CSS

To rectify this and create a “template” for use in our organization, I created a custom composite control that encapsulates

  • Creation of the AJAXToolkit’s ModalPopupExtender,
  • Creation of a Panel control,
  • Styles the Panel according to pre-set styles or custom styles,
  • Ties the Panel and Extender together,
  • Passes various events to the common UI elements of the popup,
  • Allows the popup’s events to be visible to other controls on the page.

As it stands, this is a prototype and needs quite a bit more tweaking before I’d put it into production; however, it stands as a fun project to tinker with. This will be an ongoing project and as I finish or update various aspects of the control, I’ll post up the changes.  I’m also interested in feedback and ideas for improvement. :)

The Control’s Structure

The ModalPopupTemplate's class diagram.

Here you can see the properties that are configurable with the control as well as the public and private methods and events.  I’ve also included the PopupStyle enumeration which prestyles the popup.

  • _Element_Style (BodyStyle, ContainerStyle, etc) properties accept strings from your embeded or attached CSS.
  • DefaultStyle is linked to the PopupStyle enumeration (and may lend itself to rename eventually).  The example I showed above is the YUI theme which uses Matt Berseth’s YUI Css.  I’ve also included a “Clean” theme similar to what we use in our projects at work.  I hope to grow the collection of themes as time progresses.
  • OnOkClick, OnCancelClick, and OnCloseClick methods link to the corresponding buttons on the popup and throw the like named events.  By default, if these events are not tied to methods in your project, they simply close the popup window.
  • BodyText and HeaderText are the two primary configuration elements of the popup.

Here’s an example including shaky arrow lines matching the properties to their relative location.  For examples of the Style (ContainerStyle, BodySTyle, HeaderStyle, etc) check out Matt Berseth’s YUI example—the CSS is the same (Thanks Matt for an EXCELLENT job and template to follow!)

Elements of the ModalPopupTemplate

Control Usage

Using the control on your .NET page is quite simple.  Remember, as with the normal ModalPopupExtender, your ModalPopupTemplate control must be in the same UpdatePanel as the TargetControl that activates it.  You’ll also need to ensure that EnablePartialRendering is set to true for your ScriptManager control.

<asp:UpdatePanel ID=”updatePanel” runat=”server” UpdateMode=”Conditional”>

<ContentTemplate>

<asp:Button ID=”btnTrigger” runat=”server” Text=”Show Popup” />

<cc1:ModalPopupTemplate

ID=”ModalPopupTemplate1″

runat=”server”

DefaultStyle=”YUI”

HeaderText=”Load Product Information”

BodyText=”Are you sure you want to load the product information?”

TargetControlId=”btnTrigger”

OnOkClick=”LoadDataTable” />

</ContentTemplate>

</asp:UpdatePanel>

How it Works

I’ll dig into how it works in the next posting—being somewhat late and being very sick and on some good drugs isn’t conducive to lots of writing. :)  If you can’t wait, download the source and go—it’s pretty well code commented.

kick it on DotNetKicks.com

Creating a Google AJAX Search Control in .NET

October 30, 2007 13 comments

As I discussed yesterday, the current non-SOAP Google approach is to use 100% JavaScript and their own custom UIs.  That really annoys me that I can’t take the service, call it, pass along some values, and get search results back.

My next thought was, if nothing else, encapsulate all the odd options and such into a nice little control.  This isn’t necessary for the Yahoo! search, as it’s SDK has it’s own controls, result objects, etc.  For the full list of Google AJAX Search options, check out the class reference.

Download .net 3.5 Complete Project [updated 30 Oct 07/10:55]

Our control has five properties:

  • The Google AJAX Search API Key: this string property is for the key specific to this particular instance and is URL aware, so you’ll need one per application (or directory).
  • Four “Enable” properties: EnableWebSearch, EnableImageSearch, EnableVideoSearch, EnableBlogSearch.  These are booleans are true by default and toggle the searchers applied to the control.  I made these toggleable because in some environments, like at my office, Google’s Image and Video searches are blocked, and others may not want those results. :)

The only method to override in our custom control is CreateChildControls; we’ll use it to populate the page with our JavaScripts.

protected override void CreateChildControls()

{

base.Page.ClientScript.RegisterClientScriptInclude(“apiScript”,

http://www.google.com/jsapi?key=&#8221; + this.Key);

StringBuilder searchers = new StringBuilder();

       searchers.AppendLine(“google.load(‘search’, ‘1’);”);

       searchers.AppendLine(“function initialize() {“);

searchers.AppendLine(“\tvar searchControl = new

google.search.SearchControl();”);

       if (EnableWebSearch)

searchers.AppendLine(“\tsearchControl.addSearcher(new

google.search.WebSearch());”);

if (EnableImageSearch)

searchers.AppendLine(“\tsearchControl.addSearcher(new

google.search.ImageSearch());”);

if (EnableVideoSearch)

searchers.AppendLine(“\tsearchControl.addSearcher(new

google.search.VideoSearch());”);

if (EnableBlogSearch)

searchers.AppendLine(“\tsearchControl.addSearcher(new

google.search.BlogSearch());”);

searchers.AppendLine(“\tsearchControl.draw(document.getElementById(‘” +

this.ClientID + “‘));”);

searchers.AppendLine(“}”);

       searchers.AppendLine(“google.setOnLoadCallback(initialize);”);

 

       base.Page.ClientScript.RegisterClientScriptBlock(this.GetType(),

“searchers”,

             searchers.ToString(), true);

}

The apiScript provides the link to the Google JavaScript objects (and passed along the unique key).  The searchers is the guts of the search component and generates a JavaScript block wherever you place your control. 

Notice on the .draw method of the searchControl, it’s drawing back to itself (the control, by default, generates a span tag; we’re simply returning the “drawing” of the control back to that.  It’s possible to add another property, something like TargetControlId, and use that to separate out the search logic and the actual location the search UI is presented.

To place the control on your page, drop and drag it from the toolbar, or code.  Here’s an example with the VideoSearch disabled.

<googleControls:GoogleSearch

ID=”GoogleSearch1″

runat=”server”

EnableVideoSearch=”false”

Key=”KEYHERE” />

Unfortunately, this still doesn’t resolve using the Search API for non-web interfaces. :(

Consuming Services: Yahoo! API vs. Google API

October 29, 2007 1 comment

As both a proof of concept for some internal uses as well as demonstration, I’ve been doing a bit of research into how the Yahoo! and Google APIs work—especially in .NET.  Here’s a bit of a comparison of what I’ve found so far.  I welcome any comments and such as I’m quite sure others out there have been using these technologies far longer than I have—and may have some workarounds for the odd glitches found in each framework.

Yahoo! Developer API

I’ll start out that I’m quite impressed by Yahoo!.  The Developer API was introduced to me in an AJAX session I attended a few months ago and I had totally forgotten about it until recently.  Their .NET Developer Center provides articles, SDK libraries, and most anything you’d need to wrap Yahoo! functionality into your .NET Application. Since Yahoo! returns standard XML (or JSON if you so desire and want to use the FromJson extension method and a custom type), I built a quick console-based searcher app.  The UI is irrelevant, I simply wanted to see how fast I could take data, search for it, and return information.

Most of the code here can be gleamed from the Yahoo! examples…

static void Main(string[] args)

{

// Capture the Yahoo query from the console.

       Console.WriteLine(“Your query to http://www.yahoo.com’s Image Search engine:”);

       string query = Console.ReadLine();

       // If query is blank, end.

       if (query == “”) return;

                      

       foreach (XmlNode node in GetImageSearch(query))

       {

              Console.WriteLine(“{0} @ {1}”,

node["Title"].InnerText,

node["Url"].InnerText);

}

}

This bit of code takes the input (from the console at this point) and then searches.  My GetImageSearch method returns an XmlNodeList (encapsulating the whole “get an XML, convert it, get the elements, etc” process) and then allows us to iterate through it, set it to a DataSet, etc.

static XmlNodeList GetImageSearch(string query)

{

// Create the web request

       Uri address = new

Uri(http://search.yahooapis.com/

ImageSearchService/V1/imageSearch”);

string appId = “YahooDemo”;

HttpWebRequest request =

 WebRequest.Create(address) as HttpWebRequest;

       // Set type to POST  

       request.Method = “POST”;

       request.ContentType = “application/x-www-form-urlencoded”;

       // Create the data we want to send  

       StringBuilder data = new StringBuilder();

       data.Append(“appid=” + HttpUtility.UrlEncode(appId));

       data.Append(“&query=” + HttpUtility.UrlEncode(query));

       // Create a byte array of the data we want to send  

byte[] byteData =

UTF8Encoding.UTF8.GetBytes(data.ToString());

       // Set the content length in the request headers  

       request.ContentLength = byteData.Length;

       // Write data  

       using (Stream postStream = request.GetRequestStream())

       {

              postStream.Write(byteData, 0, byteData.Length);

}

       // Get response

       using (HttpWebResponse response =

request.GetResponse() as HttpWebResponse)

       {

              // Get the response stream  

             StreamReader reader =

new StreamReader(response.GetResponseStream());

             XmlDocument xmlOutput = new XmlDocument();

             xmlOutput.LoadXml(reader.ReadToEnd());

             XmlNodeList resultsNodes =

xmlOutput.GetElementsByTagName(“Result”);

             return resultsNodes;

}

}

That’s it!  Note for real world use, you’ll need to replace that AppId with a real Yahoo Application Id.

Pros:

  • XML Output is standard, JSON optional.  Works like a snap for .NET usage.
  • Amazing support and community for the APIs.
  • A Search SDK exists for C# and VB.NET, though I didn’t use it.  That’d probably replace all of the coding above to a simple call or two.
  • You only need one Yahoo! Application ID per… application! (you’ll see why this is a pro in a minute).
  • Almost any language/framework has a Developer Center.

Cons:

  • It’s Yahoo.  I’m a Google fan myself (using Web Search, Google Mail, Google Docs, etc.), maybe this will change my mind and make this into a Pro as time goes on.

Google Developer APIs

Google’s been my Search of Choice for years now.  As I mentioned above, I use several of their services and have never had much of a problem.  In the results I get back from their search services, I tend to get what I’m looking for in the top ten or twenty, not the top 100 to 200 as I do with Yahoo and Live Search. With that in mind, their Developer Center is almost horrifying.  While AJAX and JavaScript are grand technologies, I had hoped for a bit of the same control as the Yahoo! solution provided—especially if I wanted to consume the information in non-web applications. 

[update 30 Oct 07: Google previously had a SOAP Search, but as of 5 December 2006, the SOAP Search is no longer available.  Bloody hell, why?! 

“Depending on your application, the AJAX Search API may be a better choice for you instead. It tends to be better suited for search-based web applications and supports additional features like Video, News, Maps, and Blog search results.

Okay, I’ll give you that, but what if you don’t want to use it in a web application?  *grumble*]

To provide an example of the AJAX Web Search, here’s what we have:

 

<html>
<head>
<title>Search Example</title>

<script type=”text/javascript”
  src=”http://www.google.com/jsapi?key=KEY&#8221; />
<script type=”text/javascript”> 

google.load(“search”, “1”);

function initialize()
{
 var searchControl = new google.search.SearchControl();
 searchControl.addSearcher(new google.search.WebSearch());
 searchControl.draw(document.getElementById(“searchcontrol”));
}

google.setOnLoadCallback(initialize);

</script>
<script type=”text/javascript”>

</script>

</head>
<body>
    <div id=”searchcontrol”></div>
  </body>
</html>

 

That code works just fine, but it doesn’t give me control of the UI or the results, it generates: Now, I did find the google-gdata project, a Google Data API for .NET—but apparently GData doesn’t include things like searches, only Claendars, Docs, and such.  Bleh. So, what could be done to wrap this up?  I could put the JavaScript into a custom control and intercept the text coming back into the element from the .Draw method, but ehh… beyond that, I’m interested to see how others are wrapping Google technologies into .NET applications—if you have, please post links and feedback!

 

Pros:

  • Development outside .NET or outside the OOP side of .NET, it’s pretty slick.
  • Creates a nice interface for the tools.

Cons:

  • You need a new application key for every service you use, for every site you create.  If your site consumes Search, AJAX Feed, and Maps, you need 3 keys.  Really a hassle.
  • Appears to be little or no language specific support outside of HTML and JavaScript for the API.  That’s fine, but wrappers would be nice too.
  • Google Web Toolkit is Java only. :(

For now, both of these services still interest me and both are excellent examples of what could be done to mash up technologies into a modern web application—it all depends on what you need. For grins, I’m sure the “Microsoft” answer is to consume Live Services rather than the competition, but I’ve never had much luck using Live—anyone using it now?

Creating a Vista-like Menu Bar Custom Control

October 15, 2007 4 comments

I came across an excellent post on the Itookia website that described creating a Aero-glass like menu bar (from Vista) using just three images and CSS.  Like most cool web components, I have been on a kick lately to find a way to encapsulate the functionality into an ASP.NET server control.

Note: The original CSS source and descriptions are available on the Itookia site.  Thanks to them for the cool CSS.  The control was built using .NET 3.5; however, does not contain any 3.5–specific libraries.  For convenience, I’ve provided both the 2.0 and 3.5 projects.

To begin, take a look at the aforementioned site and familiarize yourself with the CSS and what’s going on.  Even run the demo.  It’s very simple—not even a scrap of JavaScript on the page.

From there, let’s begin to put that into a control. 

Download Control (v3.5) | Download Control (v2.0)

The control will have six components. 

  1. Three images (back.gif, left.png, right.png)
  2. One standard CSS file.
  3. A VistaMenuBar control
  4. A VistaMenuItem class.

Our goal is to generate HTML that forms itself to:

<div id=”vista_toolbar”>

<ul>

<li>

<a href=”#”>

<span>

       <img align=”left” src=”VistaMenuBar/add.gif” alt=”add new” />

Add New

</span>

</a>

</li>

</ul>

</div>

There will be one ListItem element (li) for each “menu item” we add.

There are four attributes to a menu item, the Navigation URL (string), the Image URL (string), the Display Text (string) , and whether or not to right align the item (bool).

Embedding Resources

This control will need those three basic image files and a style sheet for operation.  The best way to handle this is to embed the resources into the control—rather than relying on the user to have the files in the correct place.

To embed the resources (and create an Embedded Resource…):

  1. Add the files to your project.  If you look at the image above, you’ll see a folder called VistaMenuBar with the files inside.
  2. Set the Build Action property of each of the files to “Embedded Resource”.
  3. Add a line in the AssemblyInfo.cs file for each of the resources.

[assembly: WebResource("TSCustomControls.VistaMenuBar.VistaMenuBar.css", 

        "text/css",

        PerformSubstitution=true)]

[assembly: WebResource("TSCustomControls.VistaMenuBar.back.gif",

        "image/gif")]

[assembly: WebResource("TSCustomControls.VistaMenuBar.left.png",

        "image/png")]

[assembly: WebResource("TSCustomControls.VistaMenuBar.right.png",

        "image/png")]

Your code will be different.  Resources are named according to their location and namespace.

Namespace.PathToFile.FileName >> 
  TSCustomControls.VistaMenuBar.back.gif

Note: You may need to add a reference to System.Web.UI to use WebResource.

You may notice that the VistaMenuBar.css file has an additional attribute, PerformSubstitution.  That’s because we need our CSS file to consume these Embedded Resources as well.

There are three classes you’ll need to modify in the base CSS (if you’re getting it from Itookia; the three that point to images.

Replace the url attribute code with a reference to your WebResource.  Here’s an example for the “#vista_toolbar ul” style’s background-image:

background-image:  url(‘<%=WebResource(“TSCustomControls.VistaMenuBar.back.gif”)%>’);

The PerformSubstitution allows this functionality to work.  Good deal!

Creating the Control

Instead of a standard WebControl, this control will need to inherit from the DataBoundControl base class.  This allows us to use DataSource and grants access to the PerformingDataBinding method.

public class VistaMenuBar : DataBoundControl { }

Adding public properties.  Next, add four public properties to hold the four attributes previously discussed.  In this example, they’re named NavigateUrl, ImageUrl, Text, and AlignRight and each are Bindable. 

In addition, set the default value to match the name of the property—this eases the use of the MenuItem object we’ll create later.

Here’s an example of the NavigateUrl property.

[Bindable(true)]

[Category("Appearance")]

[DefaultValue("NavigateUrl")]

[Localizable(true)]

public string NavigateUrl

{

get

       {

              String s = (String)ViewState["NavigateUrl"];

             return ((s == null) ? “NavigateUrl” : s);

}

set

       {

ViewState["NavigateUrl"] = value;

       }

}

Overriding methods.  Our first method to override is the OnPreRender method.  Remember the embedded CSS file we added, we need to populate that on our page BEFORE the control loads.

protected override void OnPreRender(EventArgs e)

{

base.OnPreRender(e);

 

       string includeLocation =

              Page.ClientScript.GetWebResourceUrl(this.GetType(),

             “TSCustomControls.VistaMenuBar.VistaMenuBar.css”);

HtmlLink cssLink = new HtmlLink();

       cssLink.Href = includeLocation;

       cssLink.Attributes.Add(“rel”, “stylesheet”);

       cssLink.Attributes.Add(“type”, “text/css”);

       this.Page.Header.Controls.Add(cssLink);

}

This code first runs all base OnPreRender methods, then grabs the Embedded Resource’s URL (handed from WebResource.axd) and pushes a style tag into the header of the page.  The resultant HTML looks something like:

<link href=”/WebResource.axd?d=rU-1RLo4XEyK0VOMEAnIN_nd6CTbmgWvq6yvdQhV50siqXTSQTB
57Bs0xp4W35_nJlUtHKFRqEepGi1t4tkpHVtT9VHRDQvDKchAE7uKv6w1&amp;t=633280611067677145″ rel=”stylesheet” type=”text/css” />

Please memorize that URL—there will be a quiz later (maybe).  If you’re unfamiliar with Embedded Resources, do some Googling—it’s a great way to keep files attached to objects and such.

The second method does the heavy lifting.  The PerformDataBinding method accepts an IEnumerable data source and allows you the freedom to control what happens with the data.  For this control, we want to generate simple HTML.

protected override void PerformDataBinding(IEnumerable retrievedData)

{

 

base.PerformDataBinding(retrievedData);

 

if (this.DataSource != null)

{

Literal literal = new Literal();

StringBuilder output = new StringBuilder();

 

output.AppendLine(“<div id=’vista_toolbar’>”);

output.AppendLine(“<ul>”);

foreach (object dataItem in retrievedData)

{

PropertyDescriptorCollection props =

TypeDescriptor.GetProperties(dataItem);

 

string navigateUrl =

props[this.NavigateUrl].GetValue(dataItem).ToString();

string imageUrl =

props[this.ImageUrl].GetValue(dataItem).ToString();

string text =

props[this.Text].GetValue(dataItem).ToString();

bool alignRight =

Convert.ToBoolean(props[this.AlignRight].GetValue(dataItem));

 

if (alignRight)

{

output.AppendFormat(“<li><a class=’right’ href='{0}’><span>”,

navigateUrl);

}

else

{

output.AppendFormat(“<li><a href='{0}’><span>”, navigateUrl);

}

output.AppendLine();

 

if (imageUrl != “”)

{

output.AppendFormat(“<img align=’left’ src='{0}’ alt='{1}’ />”,

imageUrl, text);

}

output.AppendFormat(“{0}</span></a></li>”, text);

}

 

output.AppendLine(“</ul>”);

output.AppendLine(“</div>”);

 

literal.Text = output.ToString();

this.Controls.Add(literal);

}

 

}

Woah—lots of code.  It’s actually not too bad, just a bit more to deal with the boxing of the object.  Here’s what it does:

  1. Process the DataBinding.
  2. Verify that the DataSource isn’t null—if it is, skip all this work.
  3. Create a Literal object and a StringBuilder object—that’s where we’ll put our HTML.
  4. For each “data item” object in the IEnumerable collection, loop through.
  5. Reflect into the “data item” object and get it’s properties.  Set those properties to strings and a boolean.  This could be done inline down below—but, it just seems messier that way.
  6. Fill in the blanks with your variables and perform logic depending on what’s passed (not adding image tags, right align, etc).
  7. Output the literal control back to the page.

Adding a VistaMenuItem Class

The last piece is totally optional.  I created a VistaMenuItem object to allow me to pass in a generic List of VistaMenuItems.  Here’s the structure; more on how to use it when we start consuming the control.

public class VistaMenuItem

{

public string Text { get; set; }

       public string ImageUrl { get; set; }

       public string NavigateUrl { get; set; }

       public bool AlignRight { get; set; }

 

       public VistaMenuItem(string text,

string imageUrl,

string navigateUrl, bool alignRight)

        {

            Text = text;

            ImageUrl = imageUrl;

            NavigateUrl = navigateUrl;

            AlignRight = alignRight;

        }

}

Using the Control

On your ASPX form, compile your new control and add it to the page.

<cc1:VistaMenuBar ID=”VistaMenuBar1″ runat=”server” Width=”100%” />

We have two ways we can populate the menu items: pass an IEnumerable DataSource or pass an IEnumerable list of VistaMenuItem objects. 

The difference?  The VistaMenuItems already know what value goes where in the menu.  The DataSource (a DataTable, etc) will require you to specify the NavigateUrl, ImageUrl, Text, and AlignRight properties if your columns do not match the attribute names.  If they do match, it will pre-fill.

Using a quick DataTable as an example, let’s see what we get.  Now, this is just an example—for “manual entry”, I’d suggest using the VistaMenuItems.  The best way, of course, would be to simply provide a DataSourc that’s pre-populated.

DataTable dt = new DataTable();

dt.Columns.Add(“MyNavigateUrl”, typeof(string));

dt.Columns.Add(“MyImageUrl”, typeof(string));

dt.Columns.Add(“MyText”, typeof(string));

dt.Columns.Add(“MyAlignRight”, typeof(bool));

 

dt.Rows.Add(“Default.aspx”, “VistaMenuBar/mona.gif”,

“Home”, false);

dt.Rows.Add(“Default.aspx”, “VistaMenuBar/chart.gif”,

“Add a Chart”, false);

dt.Rows.Add(“Default.aspx”, “VistaMenuBar/sos.gif”,

“Get Help”, false);

dt.Rows.Add(“Default.aspx”, “VistaMenuBar/mail.gif”,

“Send Email”, false);

 

VistaMenuBar1.DataSource = dt;

VistaMenuBar1.NavigateUrl = “MyNavigateUrl”;

VistaMenuBar1.ImageUrl = “MyImageUrl”;

VistaMenuBar1.Text = “MyText”;

VistaMenuBar1.AlignRight = “MyAlignRight”;

VistaMenuBar1.DataBind();

Vista Menu Example

We can also use the list of VistaMenuItems and bypass setting those properties.  It’s up to you!

 

List<VistaMenuItem> menuItems = new List<VistaMenuItem>();

menuItems.Add(new VistaMenuItem(“Add Record”,

“VistaMenuBar/add.gif”, “#”, false));

menuItems.Add(new VistaMenuItem(“Run Report”,

“VistaMenuBar/chart.gif”, “#”, false));

menuItems.Add(new VistaMenuItem(“Alert Admin”,

“VistaMenuBar/sos.gif”, “#”, false));

menuItems.Add(new VistaMenuItem(“Email Admin”,

“VistaMenuBar/mail.gif”, “#”, true));

 

VistaMenuBar2.DataSource = menuItems;

VistaMenuBar2.DataBind();

Download Control (v3.5) | Download Control (v2.0)

 

kick it on DotNetKicks.com 

Follow

Get every new post delivered to your Inbox.