Blog

Ext.NET 2.4 Now Available

We have a great news - Ext.NET Pro 2.4 is now available. You can download directly from the Ext.NET download page, or using NuGet.

PM> Install-Package Ext.NET

As well, a separate ASP.NET MVC specific NuGet package of Ext.NET is available. Search for Ext.NET.MVC in the NuGet Package Manager, use the following console command to install, or download directly from Ext.NET.

PM> Install-Package Ext.NET.MVC

We've also added new ASP.NET MVC 4 and MVC 5 specific packages to NuGet. By default, the Ext.NET.MVC NuGet command will assume your project is running the latest ASP.NET MVC release (currently MVC 5). Both .NET 4.5 and 4.5.1 are supported.

Install Ext.NET.MVC Package into an ASP.NET MVC4 Application: PM> Install-Package Ext.NET.MVC4

Install Ext.NET.MVC Package into an ASP.NET MVC5 Application: PM> Install-Package Ext.NET.MVC5

A full list of new features, revisions and fixes for this release are available in the CHANGELOG.

New Tag Components

TagLabel

The TagLabel is a container for Tags to help organize labels and make them more interactive. For example, you can close tags, select tags, add icons, etc.

Ext.NET TagLabel Example
Ext.NET TagLabel Example
<ext:TagLabel 
    ID="TagLabel1" 
    runat="server" 
    DefaultClosable="true" 
    Width="180">
    <Tags>
        <ext:Tag Text="Tag 1" />
        <ext:Tag Text="Tag 2" />
        <ext:Tag Text="Tag 3" Closable="false" />
    </Tags>
</ext:TagLabel>

<ext:Button 
    runat="server" 
    Text="Get Values" 
    Handler="alert(#{TagLabel1}.getValue());" 
    />

Another important feature is to configure Tags as selectable. The SelectionMode of the TagLabel has the same modes of selection as Ext.selection.Model.

SelectionMode Description
Single Only allows selecting one Tag at a time. This is the default.
Simple Allows simple selection of multiple Tags one-by-one. Each click of a Tag will either select or deselect the Tag.
Multi Allows complex selection of multiple Tags using Ctrl and Shift keys.

For example, Single.

<ext:TagLabel runat="server" SelectionMode="Single" TrackOver="true">
    <Tags>
        <ext:Tag Text="Tag 1" />
        <ext:Tag Text="Tag 2" />
        <ext:Tag Text="Tag 3" Closable="false" />
    </Tags>
</ext:TagLabel>
It's also possible to assign a right-click Menu to the TagLabel:
<ext:TagLabel runat="server">
  <Tags>
    <ext:Tag Text="Tag 1" />
    <ext:Tag Text="Tag 2" />
    <ext:Tag Text="Tag 3" />
  </Tags>
  <Menu>
    <ext:Menu runat="server">
      <Items>
        <ext:MenuItem 
          runat="server" 
          Text="Insert Tag" 
          Handler="var menu = this.up('menu'); menu.tagLabel.insert(menu.tagLabel.indexOf(menu.activeTag), {text: Ext.id()});" 
          />
        <ext:MenuItem 
          runat="server" 
          Icon="Decline" 
          Text="Delete Tag" 
          Handler="var menu = this.up('menu'); menu.tagLabel.remove(menu.activeTag);" 
          />
      </Items>
    </ext:Menu>
  </Menu>
</ext:TagLabel>
Ext.NET TagLabel with a Menu Example
Ext.NET TagLabel with a Menu Example

A full example of the TagLabel control can be found in our Examples Explorer (Form > Tag > TagLabel)

TagField

We're also including a new TagField component with a rich set of functionality and UI. The logic of the TagField is similar to the MultiCombo component (Form > ComboBox > MultiCombo), although uses Tag UI elements to render the values. For example, in order to remove a value from the TagField the user just clicks the 'x' symbol to close. ComboBox type functionality is also provided with TypeAhead and ForceSelection. TagField can hide already selected values from the DropDownList by setting HideSelected=true property.

<ext:TagField runat="server" Editable="false" HideSelected="true" >
Ext.NET TagField with HideSelected Property Example
Ext.NET TagField with HideSelected Property Example

Multiple Tags inside a TagField will default their alignment to float onto the next line.

Ext.NET TagField Example
Ext.NET TagField Example

And of course, TagField includes Methods to add or remove tags, and get or set Values:

<ext:TagField 
    ID="Tags1" 
    runat="server" 
    Width="500" 
    TypeAhead="true" 
    EmptyText="[Add tags]">
    <Items>
        <ext:Tag Value="1" Text="Jack" Icon="User" />
        <ext:Tag Value="2" Text="Bob" Icon="UserAdd" />
        <ext:Tag Value="3" Text="John" Icon="UserAlert" />
        <ext:Tag Value="4" Text="Bill" Icon="UserB" />
        <ext:Tag Value="5" Text="Ronald" Icon="UserDelete" />
    </Items>
</ext:TagField>
<ext:Container runat="server" Layout="HBoxLayout">
    <Items>
        <ext:Button 
          runat="server" 
          Text="Add Jack" 
          Handler="#{Tags1}.addTag('1');" 
          />
        <ext:Button 
          runat="server" 
          Text="Add Ext.Net" 
          Handler="#{Tags1}.addTag('Ext.Net');" 
          />
        <ext:Button 
          runat="server" 
          Text="Remove Jack" 
          Handler="#{Tags1}.removeTag('1');" 
          />
        <ext:Button 
          runat="server" 
          Text="Set value" 
          Handler="#{Tags1}.setValue(['1', '2']);" 
          />
    </Items>
</ext:Container>

A full TagField example is available in the Examples Explorer (Form > Tag > TagField)

TagColumn

Last but not least, we've added the new TagColumn component. Utilizing the same Tags UI elements, TagColumn enables you to display Tags inside a GridPanel or TreePanel. Tags inside the TagColumn also support Icon configuration. In the example below, we've added a TagColumn to a TreePanel and use special syntax to define Icons for tags.

Ext.NET TagColumn within TreePanel Example
Ext.NET TagColumn within TreePanel Example
<ext:TreePanel 
    runat="server"
    Title="Dev Team Projects"
    Width="500"
    Height="150"
    Collapsible="true"
    RootVisible="false"
    FolderSort="true">
    <Fields>
        <ext:ModelField Name="task" />
        <ext:ModelField Name="user" />
    </Fields>
    <ColumnModel>
        <Columns>
            <ext:TreeColumn 
                runat="server"
                Text="Task" 
                Flex="2" 
                Sortable="true"
                DataIndex="task" 
                />
            <ext:TagColumn 
                runat="server" 
                Text="Assigned" 
                DataIndex="user" 
                Width="300" 
                />
        </Columns>    
    </ColumnModel>
    <Root>
        <ext:Node Text="Tasks">
            <Children>
                <ext:Node Icon="Folder" Expanded="true">
                    <CustomAttributes>
                        <ext:ConfigItem 
                            Name="task" 
                            Value="Project: Public API" 
                            Mode="Value" 
                            />
                        <ext:ConfigItem 
                            Name="user" 
                            Value="[{'text':'Terry Johnson','iconCls':'#User'},{'text':'Core Team','iconCls':'#Group'}]" 
                            Mode="Raw" 
                            />
                    </CustomAttributes>
                    <Children>
                        <ext:Node Leaf="true">
                            <CustomAttributes>
                                <ext:ConfigItem 
                                    Name="task" 
                                    Value="REST Development" 
                                    Mode="Value" 
                                    />
                                <ext:ConfigItem 
                                    Name="user" 
                                    Value="[{'text':'Terry Johnson','iconCls':'#User'}]" 
                                    Mode="Raw" 
                                    />
                            </CustomAttributes>
                        </ext:Node>
                    </Children>
                </ext:Node>
            </Children>
        </ext:Node>
    </Root>
</ext:TreePanel>   

To provide data for a TagColumn, you can configure the Tags Collection by setting a simple comma separated string of values, an array of strings, an array of anonymous objects, or an array of Tag objects.

Ext.NET TagColumn within GridPanel Example
Ext.NET TagColumn within GridPanel Example
private IEnumerable Data
{
    get
    {
        return new List<object>()
        {
            new { tags = "Tag 1,Tag 2,Tag 3" },
            new {
                tags = new string[] {
                    "Tag 1", "Tag 2", "Tag 3" 
                }
            },
            new {
                tags = new object[] {
                    new { text = "Tag 1", iconCls = "#User" },  
                    new { text = "Tag 2", iconCls = "#UserAdd" }, 
                    new { text = "Tag 3", iconCls = "#UserDelete" } 
                }
            },
            new {
                tags = new Tags {
                    new Tag{ Text = "Tag 1", Icon = Icon.CommentAdd }, 
                    new Tag{ Text = "Tag 2", Icon = Icon.CommentDelete }, 
                    new Tag{ Text = "Tag 3", Icon = Icon.CommentEdit } 
                }
            }
        };
    }
}

A full example is available in the Examples Explorer (Form > Tag > TagColumn)

New Resource Strategies

Resources Strategy is Ext.NET's new functionality to allow management of how and from where Ext.NET and ExtJS resources will be retrieved. By default, Ext.NET retrieves resources depending on configuration of the RenderScripts and RenderStyles properties of ResourceManager. Values include:

Value Description
None Resources are not rendered
Embedded Resources are retrieved from assembly
File Resources are retrieved from ResourcePath location
CDN Resources are retrieved from Ext.NET CDN

Let’s consider a case when configuring a custom ResourceStrategy could be useful; we need our ResourceStrategy to retrieve in the following manner:

  1. ExtJS resources are retrieved from Sencha CDN
  2. Ext.NET resources are retrieved from Ext.Net CDN
  3. Resources from own control are retrieved from location on the server

First, we need to create a ResourcesStrategy class and override the GetUrl method:

public class MyStrategy : Ext.Net.ResourcesStrategy 
{
    public override string GetUrl(ResourceDescriptor descriptor) 
    {
        if (descriptor.Type == ResourceType.ExtJS)
        {
            var parts = descriptor.Parts.Subarray(1); 

            // exclude "extjs" part
            return "http://cdn.sencha.com/ext/commercial/4.2.1/" + parts.Join("/");
        }
        else if (descriptor.Type == ResourceType.ExtNet) 
        {
            var parts = descriptor.Parts;

            return "http://speed.ext.net/ext.net/2.3.1/" + parts.Join("/");
        } 
        else if (descriptor.Type == ResourceType.Other && descriptor.Resource.StartsWith("Ext.Net.Sandbox"))
        {
            var parts = descriptor.Parts.Subarray(3); 

            // exclude "Ext.Net.Sandbox" part
            return "~/" + parts.Join("/");
        }

        // Returning 'null' uses the default strategy
        // Returning an empty string means resources should not be rendered
        return null;
    }
}

The GetUrl method accepts one argument with Ext.Net.ResourceDescriptor type. The descriptor contains the following Properties:

ResourceDescriptor Description
Parts Part of WebResource's URL
Type Resource Type: ExtJS, ExtNet or Other
Manager Reference to ResourceManager
LocationType Current mode for Resource: None, Embedded, File and CDN
Resource Resource Name
Scope Class Type which belongs that Resource

Let’s create a custom component with own resources.

namespace Ext.Net.Sandbox.CustomControls
{
    public class TestButton : Button
    {
        public TestButton() { }
        
        protected override List<ResourceItem> Resources
        {
            get
            {
                List<ResourceItem> baseList = base.Resources;

                baseList.Add(
                    new ClientScriptItem(typeof(TestControl), 
                    "Ext.Net.Sandbox.CustomControl.testresource.js", 
                    "Ext.Net.Sandbox.CustomControl.testresource-debug.js", 
                    "/CustomControls/testresource.js", 
                    "/CustomControls/testresource-debug.js"));

                return baseList;
            }
        }
    }
}

So, TestButton requires testresource.js as a required resource. Now create a page and add our new TestButton.

<%@ Page Language="C#" %>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        this.ResourceManager1.ResourcesStrategyType = typeof(MyStrategy);
        this.Page.Form.Controls.Add(new TestButton { Text = "Test" });
    }
</script>

<!DOCTYPE html>

<html>
<head runat="server">
       <title>ResourcesStrategy Test</title>
</head>
<body>
    <form runat="server">
        <ext:ResourceManager ID="ResourceManager1" runat="server" />
    </form>
</body>
</html>

Let’s see how resources will be rendered to the Page (View > Source):

<link type="text/css" rel="stylesheet" href="http://cdn.sencha.com/ext/commercial/4.2.1/resources/ext-theme-gray/ext-theme-gray-all-debug.css" id="ext-theme" />
<link type="text/css" rel="stylesheet" href="http://speed.ext.net/ext.net/2.3.1/extnet/resources/css/extnet-all-debug.css" id="extnet-styles" />
<script type="text/javascript" src="http://cdn.sencha.com/ext/commercial/4.2.1/ext-all-debug.js"></script>
<script type="text/javascript" src="http://speed.ext.net/ext.net/2.3.1/extnet/extnet-all-debug.js"></script>
<script type="text/javascript" src="http://speed.ext.net/ext.net/2.3.1/extnet/locale/ext-lang-ru.js"></script>
<script type="text/javascript" src="/CustomControls/testresource.js"></script>

With the above Resources Strategy, ExtJS resources are retrieved from cdn.sencha.com, Ext.NET from speed.ext.net and custom control resources  from our local /CustomControls/ server folder.

You can also set a strategy globally in the Web.config. Just add the following parameter to <extnet /> Web.config section:

<extnet resourcesStrategyType="Ext.Net.Sandbox.MyStrategy, Ext.Net.Sandbox" />

Let’s consider another case. For example, you host your own ext-all.js file (contains all ExtJS code) and you want to use your custom location instead of delivery from the Ext.NET Assembly. In this case, a Resources Strategy class can look like the following:

public class MyStrategy : Ext.Net.ResourcesStrategy
{
    public override string GetUrl(ResourceDescriptor descriptor)
    {
        if (descriptor.Type == ResourceType.ExtJS 
            && Regex.IsMatch(descriptor.Resource, "ext-all(-debug)?\\.js"))
        {
            return descriptor.Manager.ResolveUrlLink("~/my-ext-all.js");
        }
    
        return null;
    }
}

Improved CDN services

Ext.NET Pro license holders will benefit immediately from our recent upgrade of CDN providers.

If CDN is configured for RenderScripts and/or RenderStyles, all JavaScript and Stylesheet files are now automatically minified, compressed using gzip, and delivered to the browser directly from the closest of 23 data centers around the world. We're seeing very nice performance increases in all Ext.NET CDN enabled Apps.

CDN Network Map
CDN Network Map

By default, Ext.NET delivers all Resource Files from your local server, but enabling the high speed Content Delivery Network is as simple as setting the properties in the ResourceManager or Web.config. No extra configuration is required on your servers.

// ResourceManager
<ext:ResourceManager runat="server" RenderScripts="CDN" RenderStyles="CDN" />

// Web.config
<extnet renderScripts="CDN" renderStyles="CDN" />

Another nice benefit of the CDN upgrade is full SSL/HTTPS support is now included for all CDN resources. If your app is running in https, Ext.NET will automatically detect the secure mode and deliver the required JavaScript (.js), Stylesheet (.css), and embedded images (Icons) straight from the secure Ext.NET CDN servers.

As outlined above, you also have absolute full control over how resources are delivered by configuring a Resources Strategy.

Purchase Ext.NET Pro

You can purchase Ext.NET Pro licenses and Premium Support Subscriptions directly from the online store. Your support and commitment is greatly appreciated!

To the best of our knowledge, there are no Breaking Changes. Any Breaking Changes would be listed in the BREAKING_CHANGES document. If you happen to find a Breaking Change not included in this list, please feel free to post in the Ext.NET Community Forums.

Technical support questions are also best asked in the in the Community Forums. The Ext.NET forums are monitored 24 hours a day.

Be sure to follow us on Twitter @extnet, or join us on Facebook.