Exploring the depths and potentials of ASP.NET RSS 2.0 or Subscribe to .BenRush by Email
 Saturday, March 31, 2007

Say you have a situation like this:



Here you see we have a master/content page scenario with the content page containing an UpdatePanel and the master page containing a ScriptManager. If you look at the bottom of the master page, you'll also see a LinkButton creatively named "LinkButton". Within the UpdatePanel on the content page, you'll see a Label.

What we want to do is handle the LinkButton click event asynchronously (through ASP.net AJAX) so that the Label within the UpdatePanel on the content page refreshes seamlessly. The catch, however, is that you want to centralize all your code for handling the click event from within the ContentPage. How would you do this?

First, within the Page_Load event for the MasterPage control, you would do this:

    protected void Page_Load(object sender, EventArgs e)
    {
        this.ScriptManager1.RegisterAsyncPostBackControl(
            LinkButton1);
        return;
    }


You see here that we're registering the LinkButton with the ScriptManager control as one that should generate asynchronous postbacks. We then publicize the LinkButton by actually creating an accessor property for it directly within the code for the MasterPage as follows:

    public LinkButton MyLinkButton
    {
        get
        {
            return LinkButton1;
        }
    }


This let's us interact with the LinkButton on the master page strongly (as opposed to using the FindControl method and locating it "weakly" or by name).

The Page_Load event for the content page, then, will look like this:

    protected void Page_Load(object sender, EventArgs e)
    {
        MasterPage mp = (MasterPage)this.Master;
        mp.MyLinkButton.Click += new EventHandler(OnButtonClick);
    }


We grab a reference to the MasterPage object and type it to our particular variant on the MasterPage class (remember we have modified it to have the MyLinkButton property above). Once we have a valid reference, we use the MyLinkButton reference to grab a reference to the LinkButton itself and register an event handler for its click event from within our ContentPage.

We then actually write the event handler within the ContentPage itself:

    private void OnButtonClick(Object sender, EventArgs args)
    {
        this.Label1.Text = DateTime.Now.ToString();
        return;
    }


The result is a control on the MasterPage firing an asynchronous postback event that is then handled properly from the ContentPage (the arrow in the picture points to the region that was asynchronously updated):


Recommended reading:

kick it on DotNetKicks.com
Saturday, March 31, 2007 1:27:16 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
AJAX | ASP.Net | Programming
 Friday, March 30, 2007

This is just darn cool.

How long has this been there...no, wait...don't tell me...I don't want to look like an idiot....


kick it on DotNetKicks.com
Friday, March 30, 2007 5:10:27 PM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Short and Simple
 Wednesday, March 28, 2007

I'm not going to go through a step-by-step tutorial on how to setup a script localization example here because it's done very well on the AJAX.ASP.Net site. One thing that's missing there, though, is a firm understanding of exactly how script localization works under ASP.Net AJAX. Understanding a little about how it all works might also help you understand a few bits about what happens when things go wrong.

First, the basic concept: Script localization means building scripts so that they make sense to the culture of the person using them. It would be *nicer* if someone in Germany saw something in German instead of English, and if someone in France saw something in French instead of German. Localizing something means making it local for the user.

ASP.Net has a system for localizing web pages using a satellite-assembly paradigm where you can add individual language support as totally independent modules that are used when available, or else a default language is used. Now with the introduction of ASP.Net AJAX, the concept is shifting towards more client-centric web design for ASP.Net and therefore the breadth of localizing components is spreading off the server and to the client browser.

Second, the samples: The sample from Microsoft on the subject of localizating ASP.Net AJAX has you build a web site which looks like this:

Here you see a dropdown that says "English". You can also change the language of the page through the dropdown:

....."Okay", you'd say, "But how is this any different from localization in earlier versions of ASP.Net?" You're right. So far nothing has changed. However, if you try to click one of the buttons, you're going to execute a block of script code that produces this (if you're running under Italian):


The script that generated this (the script we wrote) looks like this:

function CheckAnswer()
{
    var firstInt = $get('firstNumber').innerText;
    var secondInt = $get('secondNumber').innerText;
    var userAnswer = $get('userAnswer');

    if ((Number.parseLocale(firstInt) + Number.parseLocale(secondInt)) == userAnswer.value)
    {
        alert(Answer.Correct);
        return true;
    }
    else
    {
        alert(Answer.Incorrect);
        return false;
    }
}

...and THIS is where the ASP.Net AJAX stuff comes into play. Look at how the argument to the alert() method uses this mysterious Answer object to get the strings to use (Answer.Incorrect or Answer.Correct). The Answer object actually refers to a .resx or resource file you generated on the server to hold all the localized strings. How is the script referencing the file and how is it getting the right strings?

You tell ASP.Net AJAX to load the resources needed for a script by using a Web and ScriptResource attribute in your Assembly.XX file (.cs or .vb). Like this (in C#):

[assembly: System.Web.UI.WebResource("LocalizingScriptResources.CheckAnswer.js", "application/x-javascript")]
[assembly: System.Web.UI.ScriptResource("LocalizingScriptResources.CheckAnswer.js", 
      "LocalizingScriptResources.VerificationResources", "Answer")]

You see here that you make a reference to the javascript file CheckAnswer.js in the first attribute as a WebResource. You then make a reference to a resource needed to localize the script via the ScriptReference (the second attribute). In the second attribute you reference a resource for the script with the name VerificationResources on the server, and refer to it as "Answer" on the client. As it turns out, I have two resource files on the server:

VerificationResources.it.resx
VerificationResources.resx


...Or the resource for the Italian and default culture, respectively. When the ASP.net AJAX framework is building the script to return to the client (either as a result of the first page load or a partial postback), it will look at the culture for the calling thread on the server and reference the resource files using the standard ASP.Net 2.0 methodology. It will take all of the resource data out of the resource file it grabs (VerificationResources.it.resx if the thread is running under the Italian culture, or VerificationResources.resx if anything else), package it up as a javascript type and return it to the client. On the client, it is given the name "Answer" in this sample, where the client code can reference it.

A look in fiddler will show an example of the "Answer" class generated for the default culture:

Answer={
"Verify":"Verify Answer",
"Correct":"Yes, your answer is correct",
"Incorrect":"No, your answer is incorrect"
};

If you reload the page and have it generate an Italian page, the fiddler dump will show the following amongst everything else that comes down:

Answer={
"Verify":"Verificare la risposta",
"Correct":"Si, la risposta e’ corretta",
"Incorrect":"No, la risposta e’ sbagliata"
};

When this block gets downloaded, it will change the contents of the type referenced by your script code. This is how localization works under ASP.Net.

 Recommended reading:

kick it on DotNetKicks.com

Tuesday, March 27, 2007 11:26:30 PM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
AJAX | ASP.Net | Programming
 Monday, March 26, 2007

Read my previous post.

You can use this method from Page_Load in the following manner (if you want the ASPX page to return an image).

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        MemoryStream mem = TransparentGif.DrawTransparentGif(
            "Test", Color.Red, 128, 128);
        Response.Clear();
        Response.BufferOutput = true;
        Response.ContentType = "image/gif";
        Response.BinaryWrite(mem.ToArray());
        Response.Flush();
        return;
    }
}

Recommended reading:

kick it on DotNetKicks.com
Monday, March 26, 2007 6:20:55 PM (Central Standard Time, UTC-06:00)  #    Comments [1] - Trackback
AJAX | ASP.Net | Programming

To run script before and after an async postback through ASP.Net AJAX, you do the following:

First, add the ScriptManager to your page.

Second, after the ScriptManager add the following script:

            <script language="javascript">
                var req = Sys.WebForms.PageRequestManager.getInstance();
                req.add_endRequest(OnFinishedRequest);
                req.add_beginRequest(OnStartedRequest);
                function OnFinishedRequest(sender, args)
                {
                    alert('postback done'); 
                }
                function OnStartedRequest(sender, args)
                {
                    alert('postback started');
                }
            </script>

Third, run the ASP.Net app.

add_beginRequest and add_endRequest events are fired when the request is started or has ended, respectively. The result of the above code will be a dialog saying "postback started" when you generate an async postback, followed immediately by "postback done".

Simple enough.

Recommended reading:

kick it on DotNetKicks.com
Monday, March 26, 2007 6:02:22 PM (Central Standard Time, UTC-06:00)  #    Comments [1] - Trackback
AJAX | ASP.Net | Programming

I was helping someone out on the newsgroups who wanted to draw a GIF from his ASP.Net web page; one of the requirements was that it had a transparent background. As it turns out, this little exercise is a bit more complicated than it at first seems due to - what I think - is either a bug or an anomaly in the GDI+ framework.

First - a bit of education. GIF is an indexed image format, meaning that it uses a color palette and individual pixels reference a color by indexing into the palette. One of the "colors" in the palette is a non-color or transparent; a transparent color is anything with an alpha value of 0 (ie both 0-255-255-255 and 0-128-128-128 are "invisible" where the first digit represents the value of the alpha octet).

Interestingly, the .Net runtime's GDI+ Graphics.FromImage() method DOES NOT like indexed file formats, so if you want to draw onto a GIF using the GDI+ framework, it cannot be done via this method. It's screwy; don't ask me why it is this way. Well, this guy wanted to draw text onto a GIF with a transparent background, so....how to you go about drawing text onto a GIF with a transparent background?

My first thought was modifying the palette so that all references to, say, black had an alpha transparency level of 0 - meaning invisible. What this would mean is that anything that referenced a black index into the color palette wouldn't be visible (100% alpha value). Another interesting "quirk" of the .Net runtime GDI+ framework, however, is that whenever you save the data to a stream (file, memory stream, output stream, etc) it will screw with the color palette. I didn't really try to understand what it was doing, but if you look at the color palette in a debugger window while using it, the save method just toys with it and mucks up your mods to it.

So...the only option, lock down the data, and reference each individual pixel in the image, pointing it to the entry in the GIFs color palette for a transparent color instead of black. And it worked....here is the code (implemented as a C# library that you may use freely - please be mindful that I have not tested this but for just a little bit, there may be resource leaks, etc):

public class TransparentGif
{
 public TransparentGif()
 {
 }
    public static MemoryStream DrawTransparentGif(
        String text, Color textColor, Int32 width, Int32 height)
    {
        Bitmap drawableBMP = new Bitmap(width, height);
        Graphics gdc = Graphics.FromImage(drawableBMP);
        try
        {
            gdc.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, width, height));
            gdc.DrawString(text, new Font("Arial", 13), new SolidBrush(textColor), 0, 0);
            MemoryStream memStream = new MemoryStream();
            drawableBMP.Save(memStream, ImageFormat.Gif);

            memStream.Seek(0, SeekOrigin.Begin);
            System.Drawing.Image gifed = System.Drawing.Image.FromStream(memStream);

            ColorPalette cp = gifed.Palette;
            Int32 alpha = 0;
            for (Int32 c = 0; c < cp.Entries.Length; c++)
            {
                if (cp.Entries[c].A == 0)
                {
                    alpha = c;
                     break;
                }
            }

            BitmapData data = ((Bitmap)gifed).LockBits(
    new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, gifed.PixelFormat);

            Byte[] buffer = new Byte[width* height];
            Marshal.Copy(data.Scan0, buffer, 0, width* height);

            for (Int32 c = 0; c < buffer.Length; c++)
            {
                if (cp.Entries[buffer[c]].ToArgb() == Color.Black.ToArgb())
                {
                    buffer[c] = (Byte)alpha;
                }
            }

            Marshal.Copy(buffer, 0, data.Scan0, buffer.Length);

            ((Bitmap)gifed).UnlockBits(data);

            MemoryStream outStream = new MemoryStream();
            gifed.Save(outStream, ImageFormat.Gif);
            outStream.Seek(0, SeekOrigin.Begin);

            return outStream;
        }
        finally
        {
            if (gdc != null)
                gdc.Dispose();
        }
    }
}

If you comment out the actual pixel manipulation, what gets drawn to my web page is the following:

...or a GIF with a black background. If you bring back in the actual pixel manipulation part of the above code, you get this:

Total alpha transparency of the GIF....

Addendum:

For an example of using this class, see here.

Recommended reading:

kick it on DotNetKicks.com
Monday, March 26, 2007 12:19:27 PM (Central Standard Time, UTC-06:00)  #    Comments [1] - Trackback
ASP.Net | Programming | WinForms and WPF
 Sunday, March 25, 2007

The earlier you can do it in the page lifecycle, the better. Make sure you do it before the page's prerender event.

    void b_Click(object sender, EventArgs e)
    {
        ((Label)FindControl("mylabel")).Text = DateTime.Now.ToString();
    }
    protected void Page_Load(object sender, EventArgs e)
    {

        ScriptManager sm = new ScriptManager();
        sm.ID = "sm1";
        sm.SupportsPartialRendering = true;
        sm.EnablePartialRendering = true;

        this.form1.Controls.Add(sm);

        UpdatePanel up = new UpdatePanel();
        up.ID = "up";
        up.RenderMode = UpdatePanelRenderMode.Block;
        up.UpdateMode = UpdatePanelUpdateMode.Always;

        this.form1.Controls.Add(up);

        Button b = new Button();
        b.Text = "Click me";
        b.Click += new EventHandler(b_Click);

        up.ContentTemplateContainer.Controls.Add(b);

        Label l = new Label();
        l.Text = "";
        l.ID = "mylabel";

        up.ContentTemplateContainer.Controls.Add(l);
    }


kick it on DotNetKicks.com
Sunday, March 25, 2007 12:35:27 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
ASP.Net | AJAX
 Saturday, March 24, 2007

If you happen to have an ASP.Net blog, etc. and want to add links to many of the popular traffic sites out there; you can use this code:

<a href="http://del.icio.us/post?url=<%=this.Request.Url.ToString() %>&title=<%=this.Page.Title %>">Del.icio.us</a>
<a href="http://digg.com/submit?phase=2&url=<%=this.Request.Url.ToString() %>">Digg</a>
<a href="http://technorati.com/cosmos/search.html?url=<%=this.Request.Url.ToString() %>">Technorati</a>
<a href="http://blinklist.com/index.php?Action=Blink/addblink.php&url=<%=this.Request.Url.ToString() %>&Title=<%=this.Page.Title %>" >Blinklist</a>
<a href="http://furl.net/storeIt.jsp?t=<%=this.Page.Title %>&u=<%=this.Request.Url.ToString() %>">Furl</a>
<a href="http://reddit.com/submit?url=<%=this.Request.Url.ToString() %>&title=<%=this.Page.Title %>" >reddit</a>


kick it on DotNetKicks.com
Saturday, March 24, 2007 12:22:14 PM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
ASP.Net | Programming

Computers Blogs - Blog Top Sites

Archive
<March 2007>
SunMonTueWedThuFriSat
25262728123
45678910
11121314151617
18192021222324
25262728293031
1234567
Blogroll
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009
Benjamin Rush
Sign In
Statistics
Total Posts: 444
This Year: 0
This Month: 0
This Week: 0
Comments: 128
Themes
Pick a theme:
All Content © 2009, Benjamin Rush
DasBlog theme 'Business' created by Christoph De Baene (delarou)