Mike Borozdin's Blog

A blog about programming, web and IT in general

AJAX File Upload in ASP.NET with the AsyncFileUpload Control

Finally, it has become possible to easily add AJAX file uploading capabilities to ASP.NET applications. The newly released version of the AJAX Control Toolkit ships with two new controls, one of them is called AsyncFileUpload control which was designed specially for the above mentioned purpose. It’s really great that a new version of AJAX Control Toolkit has arrived, because the project seemed to be dead, especially since ASP.NET MVC had taken its place on the stage and many developers switched to it and to jQuery which can also be used with ASP.NET WebForms.

Anyway, it is the time to introduce the control for asynchronous file uploading. First of all, you should download the newest version of the ACT, unpack it and add to the Visual Studio toolbox, or replace the previous versions controls. Actually, you can follow these installation instructions.

After installing the toolkit, just create a new web site, place a ScriptManager on a web page and eventually drop a AsyncFileUpload. Basically, here is a small code snippet asynchronous image uploading and immediate displaying it on the page.

 Default.aspx

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%
@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<
html xmlns="http://www.w3.org/1999/xhtml">
<
head runat="server">
<
title></title>
<
script type="text/javascript">
function
showUploadConfirmation() {
alert("Upload finished!");
}
</script>
</
head>
<
body>
<
form id="form1" runat="server">
<
asp:ScriptManager runat="server" />
<
div>
Just some time to make sure that the page doesn't get reloaded after uploading: <%=DateTime.Now %><br />

<
cc1:AsyncFileUpload ID="AsyncFileUpload1" runat="server" UploadingBackColor="Yellow"
OnUploadedComplete="ProcessUpload" OnClientUploadComplete="showUploadConfirmation" ThrobberID="spanUploading" />
<
span id="spanUploading" runat="server">Uploading...</span>
<
br />

<
img src="" id="imgUpload" alt="" />
</
div>
</
form>
</
body>
</
html>

There are a few points of interest in this piece of code. In this particular example I’m only using some of the AsyncFileUpload attributes.

OnUploadComplete – the name of a public code-behind method that is invoked after uploading is completeat

OnClientUploadComplete – as the name suggests it is the same thing but it’s for client-side, therefore it’s just a JavaScript function

ThrobberID – the ID of a control to display while uploading is in process, please note it can be either a WebForm control or an HTML one but with the necessary runat=”server” attribute

UploadingBackColor – the background colour of the upload control during the uploading process

For the complete list of the control attributes, please use this reference page.

Also, please pay attention at the <img /> that is going to be used for immediate display of an uploaded image.

The code-behind code is also not difficult to use.

Default.aspx.cs

protected void ProcessUpload(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
string fileName = Server.MapPath("./") + "image.jpg";
AsyncFileUpload1.SaveAs(fileName);

ScriptManager.RegisterClientScriptBlock(AsyncFileUpload1, AsyncFileUpload1.GetType(), "img",
"top.document.getElementById('imgUpload').src='image.jpg';",
true);
}

Here we just have the method used for handling the event. The main idea is not just to save a received file, but also to display an uploaded image immediately. For this purpose we have to use ScriptManager.RegisterClientScriptBlock() that basically injects a portion of JavaScript code into a page. It is also important to notice that we are using top.document.getElementById(), this is because the AsyncFileUpload is still making use of the iframe to make the asynchronous upload possible.


Tags: ,
Posted by Mike Borozdin on Monday, October 12, 2009 11:24 AM GMT
Shout it Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed

Static Page Methods Instead of Web Services in ASP.NET AJAX Control Toolkit

As you may already know, it is required to create a web service to make use of some ASP.NET AJAX Control Toolkit controls. However, you can use static methods of your pages instead, you just have to mark them with the [System.Web.Services.WebMethod] attribute and not set the ServicePath parameter in the ACT controls.

In the example from my article on CascadingDropDown we used a web service for populating the drop-down lists, now we'll use static methods instead, we can just copy-paste the methods from the web service to the code-behind file of the page and remove the ServicePath parameters from the controls.

Extract from Default.aspx.cs

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    [System.Web.Services.WebMethod]
    public static CascadingDropDownNameValue[] GetContinents(string knownCategoryValues, string category)
    {
        CascadingDropDownNameValue[] continents = new CascadingDropDownNameValue[2];
        continents[0] = new CascadingDropDownNameValue("North America", "North America");
        continents[1] = new CascadingDropDownNameValue("Europe", "Europe");
        return continents;
    }
 
Extract from Default.aspx
<%--No ServicePath attribute here--%>
<cc1:CascadingDropDown ID="cddContinent" runat="server" TargetControlID="ddlContinent" 
    Category="continent" ServiceMethod="GetContinents" />

If you don't need to expose the methods consumed by the ACT controls, then you can use static methods instead of web services.


Tags: ,
Posted by Mike Borozdin on Sunday, August 17, 2008 1:15 PM GMT
Shout it Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

Creating Linked Drop-Down Lists with the CascadingDropDown Control

Download the project files

Creating dependant drop-down lists is a very common task, for example, when making a registration form, you usually have to add a country and a state fields, the contents of the state drop-down depends on the selected item in the country drop down field. Actually, it's not so difficult to implement that with the standard controls of ASP.NET. However if you don't want the page to be reloaded every time a user selects a value in the drop-down list, you should make use of AJAX. While you can use UpdatePanel for this task, it will be difficult if you have 3 or even linked drop-downs. Hopefully, you don't have to add a lot of UpdatePanels, instead you can pick up the CascadingDropDown Control from ASP.NET AJAX Control Toolkit.

You can see the demo here.

CascadingDropDown is an extender for the standard DropDown control that retrieves the data from a web service. In the example, we'll create 4 linked drop-downs - for the continent, for the country, for the territory and for the city.

Continent: <asp:DropDownList ID="ddlContinent" runat="server" />
<cc1:CascadingDropDown ID="cddContinent" runat="server" TargetControlID="ddlContinent" 
    Category="continent" ServicePath="Helper.asmx" ServiceMethod="GetContinents" />
<br />
Country: <asp:DropDownList ID="ddlCountry" runat="server" />
<cc1:CascadingDropDown ID="ccdCountry" runat="server" TargetControlID="ddlCountry" 
    ParentControlID="ddlContinent" Category="country" 
    ServicePath="Helper.asmx" ServiceMethod="GetCountries" />
<br />
Territory: <asp:DropDownList ID="ddlTerritory" runat="server" />
<cc1:CascadingDropDown ID="ccdTerritory" runat="server" TargetControlID="ddlTerritory" 
    ParentControlID="ddlCountry" Category="territory" 
    ServicePath="Helper.asmx" ServiceMethod="GetTerritories" />
<br />
City: <asp:DropDownList ID="ddlCity" runat="server" />
<cc1:CascadingDropDown ID="ccdCity" runat="server" TargetControlID="ddlCity" 
    ParentControlID="ddlTerritory" Category="city" 
    ServicePath="Helper.asmx" ServiceMethod="GetCities" />

 

I must explain some attributes we have here:

ParentControlID - the ID of the parent drop-down control

Category - the key of the collection we parse in a web service. I'll explain it below.

ServicePath - the path to a web service the control gets the data from

ServiceMethod - the name of the method the control invokes to retrieve the data

Let's proceed to the web service now. First, we should mark it with ScriptService attribute:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[System.Web.Script.Services.ScriptService]
public class Helper : System.Web.Services.WebService

 

Then, the methods we are going to invoke must have the following signature:

 

[WebMethod]
public CascadingDropDownNameValue[] MethodName(string knownCategoryValues, string category)

 

The parameters names should match as well.

knownCategoryValues - contains the values of the all chosen cascading-drop downs. It can be transformed to a collection by CascadingDropDown.ParseKnownCategoryValuesString() method, which return the StringDictionary collection, the keys of the collection math the Category attributes of CascadingDropDowns.

category - contains the value of the Category atttribute of the CascadingDropDown that invokes the current method.

Some sample methods:

[WebMethod]
public CascadingDropDownNameValue[] GetContinents(string knownCategoryValues, string category)
    {
        CascadingDropDownNameValue[] continents = new CascadingDropDownNameValue[2];
        continents[0] = new CascadingDropDownNameValue("North America", "North America");
        continents[1] = new CascadingDropDownNameValue("Europe", "Europe");
        return continents;
    }

[WebMethod]
public CascadingDropDownNameValue[] GetCountries(string knownCategoryValues, string category)
{
    StringDictionary ddlData = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
    string continent = ddlData["continent"];

    List<CascadingDropDownNameValue> countries = new List<CascadingDropDownNameValue>();

    if (continent == "North America")
    {
        countries.Add(new CascadingDropDownNameValue("United States", "United States"));
        countries.Add(new CascadingDropDownNameValue("Canada", "Canada"));
    }
    else if (continent == "Europe")
    {
        countries.Add(new CascadingDropDownNameValue("United Kingdom", "United Kingdom"));
        countries.Add(new CascadingDropDownNameValue("France", "France"));
    }
    else
    {
        countries.Add(new CascadingDropDownNameValue("N/A", "N/A"));
    }

    return countries.ToArray();
}

 

You can download the entire project here.

Conclusion

CascadingDropDown is a very powerful AJAX enabled control that should be used when you have two or more linked drop-down lists. You can read more here and there.


Tags: ,
Posted by Mike Borozdin on Wednesday, August 13, 2008 1:34 PM GMT
Shout it Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

Adding Client-Side Events To Extender Controls

In the previous articles I wrote about how to use the extender controls available in ASP.NET AJAX Control Toolkit, how to process them on the server, validate the data. It mainly dealt with a server-side part. Today, I'll show you how to add client-side events to the extender controls.

As an example, I'll use Slider again. But unlike the previous article where we processed its value on the server, we'll use its value directly on the page with JavaScript to resize an image, although it won't actually resize the picture, but it will just resize it on the page, i.e., just change the width and height attributes of the <img /> tag.

Let's start, add some image, two sliders for width and height, two text boxes and two labels.

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
    Width:<br />
    <asp:TextBox ID="txtWidth" runat="server" />
    <asp:Label ID="lblWidth" runat="server" />
    <cc1:SliderExtender ID="sliderWidth" runat="server" TargetControlID="txtWidth"
        BoundControlID="lblWidth" Minimum="100" Maximum="800">
    </cc1:SliderExtender>
    <br />
    
    Height:<br />
    <asp:TextBox ID="txtHeight" runat="server" />
    <asp:Label ID="lblHeight" runat="serBver" />
    <cc1:SliderExtender ID="sliderHeight" runat="server" TargetControlID="txtHeight"
        BoundControlID="lblHeight" Minimum="100" Maximum="532">
    </cc1:SliderExtender>
    <br />
    
    <asp:Image ID="imgPanda" runat="server" ImageUrl="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Giant_Panda_2004-03-2.jpg/800px-Giant_Panda_2004-03-2.jpg" />
</div>
</form>

 

We want to resize the image on moving the slider, since when we move the slider handler, the actual value is being changed in the assigned TextBox, we should add the onChanged even to the TextBox.

 

protected void Page_Load(object sender, EventArgs e)
{
    txtWidth.Attributes.Add("onChange", "ChangeWidth()");
    txtHeight.Attributes.Add("onChange", "ChangeHeight()");
}

 

And add the JavaScript event handlers.

<script type="text/javascript">
    function ChangeWidth()
    {
        $get("imgPanda").width = $get("txtWidth").value;
    }
    
    function ChangeHeight()
    {
        $get("imgPanda").height = $get("txtHeight").value;
    }
</script>

By the way, please note the we are using the $get() shortcut here that actually invokes document.getElementById()

Let's test it. The image gets really resized but only when you release the button, but not when you just move the slider handle. This can be corrected by setting the RaiseChangeOnlyOnMouseUp to false.

<cc1:SliderExtender ID="sliderWidth" runat="server" TargetControlID="txtWidth"
    BoundControlID="lblWidth" Minimum="100" Maximum="800" RaiseChangeOnlyOnMouseUp="false">
</cc1:SliderExtender>
<%-- some other tags--%>
<cc1:SliderExtender ID="sliderHeight" runat="server" TargetControlID="txtHeight"
    BoundControlID="lblHeight" Minimum="100" Maximum="532" RaiseChangeOnlyOnMouseUp="false">
</cc1:SliderExtender>

Conclusion

In this tutorial we have learnt how to add how add client-side events to the extender controls, how to handle them. We have also learnt about the RaiseChangeOnlyOnMouseUp attribute of the Slider control.

Your feedback is appretiated.


Tags: ,
Posted by Mike Borozdin on Sunday, August 03, 2008 10:15 AM GMT
Shout it Kick it!  
Permalink | Comments (3) | Post RSSRSS comment feed

ASP.NET AJAX Control Toolkit Extenders: Processing And Validation

In the previous article I told you about ASP.NET AJAX Control Toolkit, I explained its purpose, listed the available controls and showed an example. However, I think some things should be explained a bit more detailed. Today I'm going to talk about the extenders controls, I already mentioned them in the previous article, but I can repeat. An extender is a control that is a based on an ASP.NET web control, but provides an additional client-side functionality. Slider is a good example of an extender, in looks like a real sliding control in desktop applications, but in fact it just extends the TextBox control.

So, its value is actually stored in the TextBox that is linked with a slider by the TargetControlID attribute, thus when processing a form you should look for the value in the TextBox. Example:

Default.aspx

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
    <%--The TextBox that contains the Slider value--%>
    <asp:TextBox ID="txtSlider" runat="server" />
    <asp:Label ID="lblSlider" runat="server" />

    <cc1:SliderExtender ID="SliderExtender1" runat="server" TargetControlID="txtSlider"
        BoundControlID="lblSlider">
    </cc1:SliderExtender>
    
    <asp:Button ID="btnSubmit" runat="server" Text="Submit" onclick="btnSubmit_Click" />
</div>
</form>

Default.aspx.cs

protected void btnSubmit_Click(object sender, EventArgs e)
{
    //We use TextBoxID.Text to access the Slider value
    Response.Write(txtSlider.Text); 
}

The next important thing is validation. Although many extenders do help users to enter a correct value (i.e. sliders, numeric up-downs, mask edits, filtered text boxes), we still need to validate the input, because if JavaScript, for some reasons, is disabled, users will see a plain text box instead of a fancy control or some people can try to hack your application by putting incorrect values into the form. So, there is nothing difficult, just use plain ASP.NET validators. If the value should fall between 1 and 10, then add a RangeValidator and RequiredValidator to check if the value isn't empty.

<%--The TextBox that contains the Slider value--%>
<asp:TextBox ID="txtSlider" runat="server" />
<asp:Label ID="lblSlider" runat="server" />

<%-- The validator that checks the value range --%>
<asp:RequiredFieldValidator runat="server" ControlToValidate="txtSlider" 
    ErrorMessage="The value shouldn't be empty" Display="Dynamic" />
<%-- The validator that checks whether the value is empty --%>
<asp:RangeValidator runat="server" ControlToValidate="txtSlider" Type="Integer" 
    MinimumValue="1" MaximumValue="10" ErrorMessage="The value should be between 1 and 10" 
    Display="Dynamic" />

<cc1:SliderExtender ID="SliderExtender1" runat="server" TargetControlID="txtSlider"
    BoundControlID="lblSlider" Minimum="1" Maximum="10">
</cc1:SliderExtender>

Tags: ,
Posted by Mike Borozdin on Friday, August 01, 2008 10:09 AM GMT
Shout it Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

Recommended Advanced ASP.NET Books

I often see questions in the forums regarding ASP.NET books, usually people ask not only about reference style books, but about more advanced books that explain not only ASP.NET basics but teach you to write real world applications.

I know a really good book on that topic. This book focuses on building a web portal including news system, guest book, user registration, e-shop and many other features. Actually, this portal is a popular starter-kit called "E-commerce starter-kit" or "The Beer House" that you can find here.

The book is called "ASP.NET 2.0 Website Programming: Problem - Design - Solution".

The new edition that describes ASP.NET 3.5 including LINQ and ASP.NET AJAX will soon arrive.

So, the books are highly recommended by many professional ASP.NET developers.


Posted by Mike Borozdin on Thursday, July 31, 2008 1:36 PM GMT
Shout it Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed

Building Rich Internet Applications With ASP.NET AJAX Control Toolkit

Introduction

Nowadays web isn't a web as it was 10 years ago. Web isn't a collection of static pages anymore. Actually, there was JavaScript and DHTML, but still web sites were far behind desktop applications in terms of interactivity. After the invention of AJAX it became possible to build really interactive web applications that are nearly the same as desktop applications except they are run in a browser.

Writing AJAX JavaScript code is a pretty routine task, so it's sensible to use a library that already has the necessary functionality. While Visual Studio 2008 has built-in ASP.NET AJAX 1.0 library, it doesn't contain many useful things we need when we are writing rich Internet applications.

ASP.NET AJAX Control Toolkit

ASP.NET AJAX Control Toolkit or simply ACT is a thing that can help to write rich Internet applications. Basically, it's set a of useful interactive web controls that we usually find in desktop applications, but missing in web applications. These controls include sliders, pop-up calendars, modal dialogs and many others. We don't have to write any JavaScript code to use them in our applications, we just need to use ACT controls that are very similar to ordinary ASP.NET controls.

ACT is run both by Microsoft and community, so everybody can take part in the creation of the decent AJAX toolkit.

Installation

The installation isn't difficult, but still worth mentioning.

First, you need to download the kit, go to their CodePlex page and choose the appropriate package. After downloading unpack the contents of the archive somewhere. Open Visual Studio, expand Toolbox, right-click, choose "Add Tab", name it "AJAX Control Toolkit", then right-click again within the space of the newly created tab and select "Choose Items...", click "Browse", open the folder where you extracted the contents of the archive, open "SampleWebsite\Bin\AjaxControlToolkit.dll". The tab must become populated with the controls. If you drag any control to a web form, the necessary assemblies will be copied to the "Bin" folder of the web site and the ACT assembly will also got registered on the page.

Controls

ACT provides two types of controls:

  • Web controls
  • Extenders

Web controls are just ordinary ASP.NET controls with some enhanced client-side functionality

Extenders are controls built on top of the existing ASP.NET controls with an additional client-side functionality, for example, many controls, for instance Slider, use TextBox and store their value in it.

The full list of controls is:

An Example

Enough with the theory, let's do something practical, for example, let's try the Slider control.

Drag Slider from Toolbox onto your page.

Since, Slider is an extender and it extends TextBox, you should add a TextBox and add the TargetControlID attribute to the Slider:

<asp:TextBox ID="txtSlider" runat="server" />

<cc1:SliderExtender ID="SliderExtender1" runat="server" TargetControlID="txtSlider" />

Don't forget to add ScriptManager to the page, because the page won't compile without it. You can compile it now and drag the slider. Unfortunately, it doesn't show the current value. You need to add a bound control, add Label next to the TextBox and set the BoundControlID of the SliderExtender:

<asp:TextBox ID="txtSlider" runat="server" />
<asp:Label ID="lblSlider" runat="server" />

<cc1:SliderExtender ID="SliderExtender1" runat="server" TargetControlID="txtSlider" 
    BoundControlID="lblSlider" />

Now when sliding it you can see the value.

You can set the minimum value with the Mininum attribute, the maximum value with the Maximum attribue and the number of steps with the Steps attribute.

Conclusion

If you need to add some rich functionality to your web application, then you should consider using ASP.NET AJAX Control Toolkit that is still in its community sandbox, however as many projects that were marked as beta it can be shipped with the new versions of Visual Studio and become an integrated part of the further .NET Framework releases.

I recommend you to check this page where you can find all the examples and the documentation of every control available in the kit.


Tags: ,
Posted by Mike Borozdin on Wednesday, July 30, 2008 3:26 PM GMT
Shout it Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed