Caching plays a major role in developing highly scalable web applications. We can cache any http get request in the user browser for a predefined time, if the user request the same URL in that predefined time the response will be loaded from the browser cache instead of the server. You can archive the same in ASP.NET MVC application with the following action filter:

using System;
using System.Web;
using System.Web.Mvc;

public class CacheFilterAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Gets or sets the cache duration in seconds. The default is 10 seconds.
    /// </summary>
    /// <value>The cache duration in seconds.</value>
    public int Duration
    {
        get;
        set;
    }

    public CacheFilterAttribute()
    {
        Duration = 10;
    }

    public override void OnActionExecuted(FilterExecutedContext filterContext)
    {
        if (Duration <= 0) return;

        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);

        cache.SetCacheability(HttpCacheability.Public);
        cache.SetExpires(DateTime.Now.Add(cacheDuration));
        cache.SetMaxAge(cacheDuration);
        cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
    }
}

You can apply the filter in your Controller action method like the following.

[CacheFilter(Duration = 60)]
public void Category(string name, int? page)

The following shows the screen-shot in firebug  when cache filter is not applied:

and this is the screen-shot when the cache filter is applied:

Another important thing is compression. Now a days, all modern browsers accept compressed contents and it saves huge bandwidth. You can apply the following action filter to compress your response in your  ASP.NET MVC application:

using System.Web;
using System.Web.Mvc;

public class CompressFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(FilterExecutingContext filterContext)
    {
        HttpRequestBase request = filterContext.HttpContext.Request;

        string acceptEncoding = request.Headers["Accept-Encoding"];

        if (string.IsNullOrEmpty(acceptEncoding)) return;

        acceptEncoding = acceptEncoding.ToUpperInvariant();

        HttpResponseBase response = filterContext.HttpContext.Response;

        if (acceptEncoding.Contains("GZIP"))
        {
            response.AppendHeader("Content-encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
        else if (acceptEncoding.Contains("DEFLATE"))
        {
            response.AppendHeader("Content-encoding", "deflate");
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
    }
}

Just decorate your controller action with this filter:

[CompressFilter]
public void Category(string name, int? page)

The following shows when compression is not applied:

and this is the screen-shot when the compress filter is applied:

You can also apply both these filter in the same action method, like the following:

[CompressFilter(Order = 1)]
[CacheFilter(Duration = 60, Order = 2)]
public void Category(string name, int? page)

And this is the screen-shot:


Enjoy!!!

Download: Source.zip

kick it on DotNetKicks.com

[Note: This post was meant to be published the day after MIX08 version was out]

I have upgraded Kigg with the new bits.  Upgrading was plain and simple, though I created a new project and added the files instead of changing the Guids. There has been few changes in the web project which are required by the MIX08 release such as routing declaration, removing attribute for controller actions, using lambdas for action link where it is appropriate and finally changing the Unit test with Scott Hanselman's MVCMockHelper and Fake View Engine from Phil Hack's Test Specific Subclass pattern.

As Phil Hack already mention the  MIX08 release was focused on to improve the Routing system and the next drop will streamline the testability issues, I think it is the right time to put my requirement list and comments on the new bits, not in any specific order, here I go:

Mix Release:

  • It is good to see that controller now can implement IDisposable, I was wondering why  not going one step further and make the IController inherits from IDisposable?
  • The ControllerAction has vanished, certainly a good choice and I am sure the in next .NET Framework, we do not have to deal with WebMethod and OperationContract attributes anymore, of course it does not make any sense having a double standard in the same platform.
  • Filter attributes is a better substitute of HttpModule in MVC world.
  • The team has not published any list on the Bug that has been fixed in this release. But I am sure there has not been many, currently two things that are really bothering me:
    • It is still not possible to use a base class in Master Page and a concrete class in Content Page. (Details)
    • You cannot turn-off the Session Module. (Details)
  • Previous MVCToolkit has been imported into the core MVC framework which is good, but I would like to see most of the Url building methods of  HTMLHelper are also available in UrlHelper, specially those with lambda versions.

Future Release:

  • Validation Support. Currently we have to write both client side and server side codes, which is really painful, we need to have a similar kind of web form validation controls in MVC space.
  • Close Integration with ASP.NET AJAX. I think the main reason that ASP.NET Ajax is mostly used framework in developing ASP.NET application due to its tight integration with ASP.NET. We need the same kind of support in MVC. Currently, the AjaxHelper is left empty, I guess later on the partial rendering will be implemented over there, but I would like to put more emphasis on the controller actions, what I would love to see is some attributes e.g. AjaxOperation, AjaxMethod which will generate the client side proxy, same as we have today for the web service and page methods.
  • I do not believe that those Control Helper methods of Rob Conery can really substitute the real controls. Instead I find those problematic. Why:

    • I loose the rich design time support of VS.
    • Certain but very common scenario like bind some data source with a select list with some predefined items what the AppendDataBoundItems property of the List Control does in web form world. Or, consider how do you generate a Url with # with those helpers.
    • Currently helper exists for intrinsic controls, but did you consider the number of parameters when you introduce helper methods for GridView/DataList/Template supported controls.
    Since most of the existing controls of ASP.NET become handicapped in MVC world, why not develop a separate set of controls for MVC, it is hard to imagine running VS without toolbox.

  • Prior MIX08, ScottGu posted the roadmap of mix08 release. I would like to see a detail list of features that are planned for the final version. Certainly, a lot of things will be added/modified from the community feedback.

kick it on DotNetKicks.com

Earlier, I mentioned that I will be writing a series of articles on developing Kigg. The first part is now live. Check it out.

kick it on DotNetKicks.com

For last few weeks, I was bit busy developing a sample application with the new ASP.NET MVC Framework and I am really glad that we finally made it. So, from the DotNetSlackers.com Team I am presenting Kigg. Kigg  is Developed with:

  • Regular Web Forms for View.
  • LINQ to SQL for developing the Model.
  • ASP.NET Ajax for Ajax operation.
  • Both VSTest and NUnit for Unit Test.
  • Rhino Mock.

While developing it, our main goal was to make it simple and stupid, without considering those Ioc/DI, View Engine, View Factory etc, So the average Joe developer can get a good start on the ASP.NET MVC Framework.
We will soon publish a series of Articles which will cover the complete development details of Kigg.

You can see the live version running in DotNetSlackers.com.
The Source is as usual hosted in CodePlex.com.

Enjoy!!!.

Note: The Name Kigg = K is taken from DotNetKicks and igg from Digg.

kick it on DotNetKicks.com

It seems, today is my celebration day. First, our open source project AjaxDataControls get mentioned in Ajaxian.  And now Joe Stagner shows ajax style file upload in the new ASP.NET How do I video series which I posted few months ago. I have used this technique extensively and it really serves my purpose. A must see if you want to implement the same.

Checkout that AjaxDataControls has been reviewed in the Ajaxian.  Really sweet!!!

Do let us know what you like and don't like and what else do you want to see in future.

My ex-buddy Tanzim Saqib has wrote an excellent article on creating controls in Volta. Really worth to check it out.



I am proud to announce the final release of v1.0 of AjaxDataControls. The v1.0 has a lot of enhancements and bug fixes, which I have mentioned in my previous post, the whole API is now available in CHM format. The Latest sample also has few cool demo of Ajax Control Toolkit integration. Checkout the following screenshots:

Integrating with Calendar Extender:

Integrating with MaskEdit Extender:

Integrating with NumericUpDown and  FilteredTextBox Extender:

You can download the latest version from the CodePlex release tab.

I would love to see your comments and feedbacks.

kick it on DotNetKicks.com

In my previous post, I have shown how to do data binding, data sorting and different type of columns of AjaxDataControls GridView. In this post, I will show how to enable Drag and Drop of the GridView Columns and automatically persist it with the help of Ajax Profile Service.

The GridView internally uses the preview version of Asp.net Ajax Drag and Drop script for the column Drag and Drop. So the first thing you have to do is to add these scripts in your script manager, the GridView also uses the animation script (PreviewGlitz.js) to do the animation when binding with data, So I would also recommend to add this script to exploit the full feature of  GridView.

<asp:ScriptManager ID="TheScriptManager" runat="server">
    <Services>
        <asp:ServiceReference Path="~/DataService.asmx" />
    </Services>
    <Scripts>
        <asp:ScriptReference Path="~/PreviewScripts/PreviewScript.js" />
        <asp:ScriptReference Path="~/PreviewScripts/PreviewDragDrop.js" />
        <asp:ScriptReference Path="~/PreviewScripts/PreviewGlitz.js" />
    </Scripts>
</asp:ScriptManager>

By default the GridView turns on the drag and drop for all type of columns except Button, Command and Radio columns. But you can also allow Drag and Drop for those column types by setting the AllowDragAndDrop property to true of the individual columns. Now, lets take quick example of the GridView, here we will see the Suppliers of the Northwind database. The following shows the control declaration in the aspx page:

<AjaxData:GridView ID="GridView1" runat="server" CssClass="DataWebControlStyle">
   <AlternatingRowStyle CssClass="AlternatingRowStyle" />
   <RowStyle CssClass="RowStyle"/>
   <HeaderStyle CssClass="HeaderStyle"/>
   <Columns>
    <AjaxData:GridViewBoundColumn HeaderText="Company" DataField="Company"/>
    <AjaxData:GridViewBoundColumn HeaderText="Contact" DataField="ContactName"/>
    <AjaxData:GridViewBoundColumn HeaderText="Title" DataField="ContactTitle"/>
   </Columns>
</AjaxData:GridView>

As you can see we are doing nothing special except adding the preview scripts in the script manager. Next, add the following JavaScript codes in your aspx page:

<script type="text/javascript">

    var _gridView;

    function pageLoad(sender, e)
    {
        _gridView = $find('<%= GridView1.ClientID %>');
        loadSuppliers();
    }

    function loadSuppliers()
    {
        DataService.GetAllSupplier(onLoadSuccess);
    }

    function onLoadSuccess(result)
    {
        _gridView.set_dataSource(result);
        _gridView.dataBind();
    }

</script>

Once done, run it, you will able to do the drag and drop like the following:

As you can see it gives some cool drag and drop abilities of the columns, but once you refresh the page the GridView appears same as it appears for the first time, which means the Drag and Drop of the columns has not been persisted. To add the persistence support we have to do the following things:

  • Configure the Asp.net Profile Provider.
  • Configure the Ajax Profile Services to allow access the Profile Object. Click here if you need to know how to configure the Ajax Profile Service. 
  • Few modification in the control declaration and javascript code.

For the shake of this example I have add the Asp.net Provider support in the Northwind database and added the following settings in the web.config file:

<anonymousIdentification enabled="true"/>
<membership defaultProvider="SqlMemberShipProvider" userIsOnlineTimeWindow="1">
  <providers>
    <clear/>
    <add name="SqlMemberShipProvider" applicationName="Northwind" connectionStringName="NorthwindConnectionString" type="System.Web.Security.SqlMembershipProvider"/>
  </providers>
</membership>
<profile defaultProvider="SqlProfileProvider">
  <providers>
    <clear/>
    <add name="SqlProfileProvider" applicationName="Northwind" connectionStringName="NorthwindConnectionString" type="System.Web.Profile.SqlProfileProvider"/>
  </providers>
  <properties>
    <add name="DndColumns" type="System.String" provider="SqlProfileProvider" allowAnonymous="true"/>
  </properties>
</profile>
</system.web>
<system.web.extensions>
<scripting>
    <webServices>
        <profileService enabled="true" readAccessProperties="DndColumns" writeAccessProperties="DndColumns"/>
    </webServices>
</scripting>
</system.web.extensions>

As you can see, in the profile provider I have added a property named DndColumns which type is string. You can name it anything but the type needs to be string. Next, I gave both read/write permission of this property to Ajax Profile Service. Now we have to change the previous javascript code and the control to load and persist the columns. The following shows control, the modifications are in bold:

<AjaxData:GridView ID="GridView1" runat="server" CssClass="DataWebControlStyle" ColumnsLoadedFromProfileEvent="onColumnsLoaded" ColumnDroppedEvent="onColumnDropped">
   <AlternatingRowStyle CssClass="AlternatingRowStyle" />
   <RowStyle CssClass="RowStyle"/>
   <HeaderStyle CssClass="HeaderStyle"/>
   <Columns>
    <AjaxData:GridViewBoundColumn HeaderText="Company" DataField="Company"/>
    <AjaxData:GridViewBoundColumn HeaderText="Contact" DataField="ContactName"/>
    <AjaxData:GridViewBoundColumn HeaderText="Title" DataField="ContactTitle"/>
   </Columns>
</AjaxData:GridView>

In the new declaration, I have added two new client side events, the control will fire the onColumnsLoaded function when the grid completes the column loading from the asp.net profile and it will also fire the onColumnsDropped function when a column is dropped. And the following shows the modified code for the client side:

<script type="text/javascript">

    var _gridView;

    function pageLoad(sender, e)
    {
        _gridView = $find('<%= GridView1.ClientID %>');
        _gridView.loadColumnsFromProfile('DndColumns');
    }

    function onColumnsLoaded(sender, e)
    {
        loadSuppliers();
    }

    function loadSuppliers()
    {
        DataService.GetAllSupplier(onLoadSuccess);
    }

    function onLoadSuccess(result)
    {
        _gridView.set_dataSource(result);
        _gridView.dataBind();
    }

    function onColumnDropped(sender, e)
    {
        _gridView.saveColumnsToProfile('DndColumns');
    }

</script>

As you can see, here in the pageLoad event (which automatically fired by the Asp.net Ajax Framework) we are instructing the GridView to load the columns from the previously configured Profile property DndColumns. Once the columns are loaded, the GridView fires the onColumnLoaded function where we are loading the suppliers and when a column is dropped the onColumDropped function gets executed where we are storing the newly ordered columns in the Profile. Now when you refresh the page or re visit the page you will find it persisted.

You will find the full working demo in the Sample folder of the CodePlex Release tab.

kick it on DotNetKicks.com

I have recently started writing a multi-part series article on AJAX Control Toolkit. Throughout the series I will cover the following items:

Explore
  • Input Helpers - FilteredTextBox and NumericUpDown.
  • Input Helpers - MaskEdit and Slider.
  • Input Helpers - CascadingDropDown and Calendar.
  • Input Helpers - ToggleButton, Rating and ValidatorCallout.
  • Containers - Dynamic Populate and CollapsiblePanel.
  • Containers -Tabs.
  • Containers - Accordion.
  • Popups - Popup, DropDown and ModalPopup.
  • Others- NotBot and PasswordStrength.
  • Others- ToolkitScriptManager.
Architecture
  • Core Framework
  • Animation Framework
Build
  • Demonstrate how to develop a first class control on top of Ajax Control Toolkit.

The introductory part explores a few basic input helpers.

I would love to see your comments and feedbacks.

kick it on DotNetKicks.com

More Posts Next page »