Enhancing EXT.NET Applications: Practical Development Techniques

  1. Client and Server-Side Browser Detection

Determining the client's browser and its version can be crucial for ensuring compatibility or delivering specific user experiences. EXT.NET applications can implement browser detection on both the server and client sides.

Server-Side Browser Analysis

On the server, you can inspect the incoming request's browser capabilities to identify the client's browser type and version. This information can then be used to conditionally inject targeted ExtJS scripts into the page, for instance, to display warnings for outdated browsers.

using System;
using System.Web;
using Ext.Net;

public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            HttpBrowserCapabilities userBrowser = Request.Browser;

            // Check if the browser is Internet Explorer and its major version
            if (userBrowser.IsBrowser("IE"))
            {
                if (userBrowser.MajorVersion < 8) // For IE versions older than 8
                {
                    string updatePromptScript = @"
                        Ext.onReady(function() {
                            Ext.MessageBox.confirm('Browser Update Recommended', 
                                '<p style=""color:red;""><strong>Your Internet Explorer version is outdated, which may pose security risks and limit application functionality.</strong></p>' +
                                '<p>Would you like to upgrade your browser for an enhanced and more secure experience?</p>' +
                                '<p>If you have recently installed a newer version of IE, please restart your computer.</p>', 
                                function(buttonResponse) {
                                    if (buttonResponse === 'yes') {
                                        window.location.href = '/BrowserSupport/UpgradePage.aspx?action=download';
                                    }
                                }
                            );
                        });";
                    Page.ClientScript.RegisterClientScriptBlock(GetType(), "OldIeWarning", updatePromptScript, true);
                }
            }
            else // For non-IE browsers, a general informational message might be shown
            {
                string infoScript = "Ext.onReady(function(){ Ext.MessageBox.alert('Browser Information', 'You are using a non-IE browser. While supported, some legacy features might behave differently.'); });";
                Page.ClientScript.RegisterClientScriptBlock(GetType(), "NonIeInfo", infoScript, true);
            }
        }
    }
}

Client-Side Browser Detection with ExtJS

ExtJS provides straightforward boolean properties on the global Ext object for direct client-side browser detection. This method is often preferred for dynamic UI adjustments based on the detected browser.

<script type="text/javascript">
    Ext.onReady(function () {
        let detectedBrowser = 'Unknown Browser';
        if (Ext.isChrome) {
            detectedBrowser = 'Chrome';
        } else if (Ext.isIE) {
            detectedBrowser = 'Internet Explorer';
            if (Ext.isIE6) detectedBrowser += ' 6';
            else if (Ext.isIE7) detectedBrowser += ' 7';
            else if (Ext.isIE8) detectedBrowser += ' 8';
        } else if (Ext.isOpera) {
            detectedBrowser = 'Opera';
        } else if (Ext.isGecko3) { // Specific to Firefox 3.x
            detectedBrowser = 'Mozilla Firefox (Gecko 3.x)';
        } else if (Ext.isSafari) {
            detectedBrowser = 'Safari';
        }

        Ext.Msg.alert("Browser Check", "You are currently using: " + detectedBrowser);
    });
</script>

  1. Detecting Silverlight Runtime Installation

For applications that integrated Silverlight components, verifying the client's Silverlight installation was a standard practice. Although Silverlight is a legacy technology, this detection method remains applicable for maintaining existing systems.

<script type="text/javascript">
    function isSilverlightRuntimePresent() {
        let silverlightFound = false;
        try {
            // Check for Internet Explorer using ActiveX control
            try {
                new ActiveXObject('AgControl.AgControl'); 
                silverlightFound = true;
            } catch (e) {
                // Check for other browsers by inspecting navigator.plugins
                if (navigator.plugins["Silverlight Plug-In"]) {
                    silverlightFound = true;
                }
            }
        } catch (e) { 
            // Any error during detection implies Silverlight is not installed
        } 
        return silverlightFound;
    }

    if (!isSilverlightRuntimePresent()) {
        Ext.onReady(function() { 
            Ext.MessageBox.confirm('Required Software Missing', 
                '<p style=""color:red;""><strong>Silverlight 4.0 (approx. 5MB) is not detected on your system.</strong></p>' +
                '<p>Key functionalities such as advanced file uploads and interactive charts require Silverlight 4.0 support.</p>' +
                '<p>Would you like to download and install it now?</p>', 
                function(buttonAction) { 
                    if (buttonAction === 'yes') {
                        window.location.href = '/RequiredSoftware/DownloadSilverlight.aspx?version=4.0'; 
                    } 
                }
            ); 
        });
    }
</script>

  1. Implementing File Downloads

A frequent challenge in EXT.NET applications, particularly when using DirectEvents, is orchestrating file downloads. DirectEvents rely on AJAX, and directly streaming a file within an AJAX response is generally not supported by web browsers, often leading to corrupted data or unexpected behavior.

Client-Side Initiated Downloads (e.g., from a Grid Row)

The recommended approach for initiating downloads from user interactions (like a grid command or a button click) is to trigger a client-side redirection to a dedicated download handler. This allows the browser to correctly interpret the response as a file download.

Consider an EXT.NET GridPanel with a command column designed for downloading attachments:

<ext:ColumnModel ID="DownloadColumnModel" runat="server">
    <Columns>
        <ext:RowNumbererColumn />
        <ext:Column Header="Document ID" Hidden="true" DataIndex="DocId"></ext:Column>
        <ext:Column Header="Document Name" DataIndex="DocumentName" Flex="1"></ext:Column>
        <ext:DateColumn Header="Upload Date" DataIndex="UploadTimestamp" Format="yyyy-MM-dd HH:mm" />
        <ext:Column Header="Author" DataIndex="AuthorName" Width="100" />
        <ext:CommandColumn Header="Actions" Width="80">
            <Commands>
                <ext:GridCommand Icon="PageWhiteDownload" CommandName="RetrieveDocument" Text="Download" />
            </Commands>
            <Listeners>
                <Command Handler="executeGridRowCommand(command, record);" />
            </Listeners>
        </ext:CommandColumn>
    </Columns>
</ext:ColumnModel>

The client-side JavaScript function executeGridRowCommand would then construct a URL and prompt the browser to navigate to it:

<script type="text/javascript">
    function executeGridRowCommand(command, record) {
        if (command === 'RetrieveDocument') {
            // Ensure filename is URL-encoded to handle special characters correctly
            let targetDownloadUrl = "/FileHandlers/DocumentDownload.aspx?docId=" + record.data.DocId + "&docName=" + encodeURIComponent(record.data.DocumentName);
            window.location.href = targetDownloadUrl;
        }
    }
</script>

On the server, DocumentDownload.aspx handles the request and streams the file to the client:

// Inside DocumentDownload.aspx.cs
using System;
using System.IO;
using System.Web;

public partial class DocumentDownload : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            int documentIdentifier;
            string requestedFileName = Request.QueryString["docName"] ?? "download";

            if (int.TryParse(Request.QueryString["docId"], out documentIdentifier))
            {
                // In a production application, retrieve the actual file path and name
                // from a database or storage based on 'documentIdentifier'.
                // For this example, we'll use a placeholder file.
                string baseDownloadPath = Server.MapPath("~/App_Data/Documents/");
                string actualFilePath = Path.Combine(baseDownloadPath, "SampleReport.xlsx"); // Assume this file exists

                if (File.Exists(actualFilePath))
                {
                    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; // Example for .xlsx
                    Response.AddHeader("Content-Disposition", $"attachment; filename=\"{requestedFileName}\"");
                    Response.TransmitFile(actualFilePath);
                }
                else
                {
                    Response.Clear();
                    Response.StatusCode = 404;
                    Response.StatusDescription = "Document Not Found";
                    Response.End();
                }
            }
            else
            {
                Response.Clear();
                Response.StatusCode = 400;
                Response.StatusDescription = "Invalid Document ID";
                Response.End();
            }
        }
    }
}

Server-Side Initiated Downloads Using X.Redirect

When a download needs to be triggered from a DirectEvent (e.g., after server-side processing like report generation), X.Redirect can be utilized. This method displays a user-friendly masked message while the browser is redirected to the download URL, enhancing the user experience.

// Example within a DirectEvent handler, such as a button click
protected void GenerateAndDownloadReport_Click(object sender, DirectEventArgs e)
{
    // Perform server-side operations, e.g., generate a complex report
    string generatedReportKey = Guid.NewGuid().ToString();
    // Store report path or data in Session/Cache with the key
    Session["Report_" + generatedReportKey] = "/temp_reports/GeneratedSalesSummary.pdf"; 

    // Redirect to a specific handler that will serve the file
    X.Redirect($"/FileHandlers/ReportServe.aspx?key={generatedReportKey}", "Generating your report, please wait...");
}

The ReportServe.aspx page would then retrieve the report path using the provided key and stream the file.

  1. Executing JavaScript from the Server-Side

EXT.NET's DirectEvents provide robust capabilities for executing arbitrary JavaScript code on the client after server-side processing. This is a fundamental mechanism for dynamically updating the user interface, triggering client-side functions, or displaying notifications.

// Example code within a C# DirectEvent handler
protected void TriggerClientActions_Click(object sender, DirectEventArgs e)
{
    // Display a simple ExtJS alert message
    X.Msg.Alert("Server Command", "A message from the server has been received!").Show();

    // Inject a direct script block to be executed by the browser
    X.AddScript("console.log('Server-injected script executed.');");

    // Call a predefined client-side JavaScript function with arguments
    X.Call("handleServerMessage", "Operation Complete", DateTime.Now.ToShortTimeString());

    // Show an ExtJS confirmation dialog, with client-side callback logic
    X.Msg.Confirm("Proceed Confirmation", "Are you sure you want to continue this process?", new JFunction("responseBtn", @"
        if (responseBtn === 'yes') { 
            Ext.toast('Action confirmed by user.'); 
        } else { 
            Ext.toast('Action cancelled by user.'); 
        }
    ")).Show();

    // For finer control, or when no specific X. method exists, use ResourceManager directly
    ResourceManager.GetInstance().AddScript("Ext.Msg.prompt('User Input', 'Please enter your feedback:', function(btn, text){ if(btn === 'ok' && text){ alert('Feedback received: ' + text); } });");
}

On the client-side, you would define the JavaScript functions that the server intends to call:

<script type="text/javascript">
    function handleServerMessage(status, time) {
        Ext.toast('Client function \'handleServerMessage\' called. Status: ' + status + ', Time: ' + time);
    }

    // A simple Ext.toast implementation for demonstration (may vary by ExtJS version)
    // For older versions, consider using Ext.Msg.alert or a custom notification system.
    if (!Ext.toast) {
        Ext.toast = function(message) {
            Ext.Msg.alert('Notification', message);
        };
    }
</script>

Upon execution of the TriggerClientActions_Click DirectEvent, EXT.NET serializes these commands and transmits them within the AJAX response for client-side execution.

  1. User-Friendly Page Redirection

The X.Redirect method offers a streamlined way to redirect the user's browser to a new URL while simultaneously displaying a temporary mask with a custom message. This enhances the user experience during navigations that might involve server-side processing or network delays.

// Example: Redirecting to a confirmation page after a successful data submission
protected void SubmitFormAndRedirect_Click(object sender, DirectEventArgs e)
{
    // ... perform data validation, persistence, or other server-side logic ...

    // After successful processing, redirect the user to a success page
    X.Redirect("/Application/Confirmation.aspx", "Processing your submission and redirecting...");
}

Internally, X.Redirect orchestrates the display of an ExtJS mask with the specified message. Following this, it injects a JavaScript command that modifies window.location.href, thereby executing the browser navigation.

  1. Accessing EXT.NET Controls on the Server

While dynamic client-side manipulation of ExtJS components using JavaScript is often efficient, there are situations where direct access and modification of EXT.NET controls from your server-side C# code are necessary. This is typically achieved by finding controls within their parent containers.

Locating Controls by Server ID

You can use the FindControl method, available on any ASP.NET server control (including EXT.NET containers like Panel, Window, or the page itself), to locate a child control by its assigned server ID.

// Assume 'mainContentPanel' is an Ext.Net.Panel declared on the page,
// and 'customerNameInput' is an Ext.Net.TextField within that panel.
protected void UpdateControlProperties_Click(object sender, DirectEventArgs e)
{
    // Access the parent panel directly (if it's a member) or find it
    Panel mainContentPanel = this.FindControl("mainContentPanel") as Panel; 

    if (mainContentPanel != null)
    {
        // Find a specific text field within the panel by its ID
        TextField customerNameInput = mainContentPanel.FindControl("customerNameInput") as TextField;

        if (customerNameInput != null)
        {
            // Modify properties like Disabled state and current Text value
            customerNameInput.Disabled = true;
            customerNameInput.Text = "Data Loaded (Read-Only)";
            customerNameInput.FieldLabel = "Customer Name (Locked)";
        }

        // Example: Iterate through child controls to disable all checkboxes within the panel
        foreach (System.Web.UI.Control childControl in mainContentPanel.Controls)
        {
            if (childControl is Checkbox checkboxComponent)
            {
                checkboxComponent.Disabled = true;
                checkboxComponent.BoxLabel += " (Disabled)";
            }
            else if (childControl is Button actionButton)
            {
                actionButton.Disabled = true;
            }
        }
    }
}

When control properties are modified on the server, EXT.NET intelligently handles rendering the necsesary client-side updates, which are then transmitted with the AJAX response of the DirectEvent. For straightforward property changes, this server-side approach offers convenience. However, for highly dynamic or performance-critical UI manipulations, directly executing JavaScript on the client remains a very potent and often more immediate method.

Tags: ext.net ASP.NET javascript csharp web-development

Posted on Sat, 26 Sep 2026 16:32:27 +0000 by endersix