jsTree – Few examples with ASP.Net/C#

The examples below uses the latest jsTree build as obtained from jsTree. (The stable build – pre 1.0 fixed) I copied all the relevant folders and file under my scripts folder.

img1

The examples are developed using old WebForms.

Example 1:
Any html structured as nested ul->li can be easily transformed into a tree.

img2

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.6/jquery.min.js" type="text/javascript"></script>
<script src="Scripts/json2.min.js" type="text/javascript"></script>
<script src="Scripts/_lib/jquery.js" type="text/javascript"></script>
<script src="Scripts/jquery.jstree.js" language="javascript" type="text/javascript"></script>
<div id="demo1">
    <ul >
        <li><a>Categories</a>
            <ul>
                <li><a>Category 1</a>
                    <ul>
                        <li><a>Product A</a></li>
                        <li><a>Product B</a></li>
                        <li><a>Product C</a></li>
                    </ul>
                </li>
                <li><a>Category 2</a>
                    <ul>
                        <li><a>Product D</a></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>
$(function () {
    $("#demo1").jstree({
        "plugins": ["themes", "html_data"]
    });
});

Example 2:
Tree using Checkbox.(html data and checkbox plugin)

img3

$(function () {
    $("#demo1").jstree({
        "plugins": ["themes", "html_data", 'checkbox', "types"]
    });
});

Example 3:
Tree with various bind/callbacks.

$(function () {
    $("#demo1").jstree({
        "plugins": ["themes", "html_data", 'checkbox', "types", "ui", "crrm"]
    })
.bind("select_node.jstree", function (e, data) {
    var CurrObj = data.rslt.obj;
    //Toggle on the click of that Node's name
    $("#demo1").jstree("toggle_node", data.rslt.obj);
})
.bind("hover_node.jstree", function (e, data) {
    //on hover
    var nodeId = data.rslt.obj[0].id;
})
.bind("loaded.jstree", function (event, data) {
    $(this).jstree("open_all");
    alert("tree loaded");
})
;
$("#OpenAllNode").click(function () {
//Open all nodes
    $("#demo1").jstree("open_all");
});

$("#CloseAllNode").click(function () {
//Close all nodes
    $("#demo1").jstree("close_all");
});

$("#btnRefresh").click(function () {
    //Will do a ajax call to refresh the tree
    $.jstree._reference($("#demo1")).refresh(-1);
});

Example 4:
Tree loaded with JSON data as obtained from server. Manually created the JSON data in codebehind. Later we’ll have this JSON created dynamically.

img4
The C# class representing each node.

public class G_JSTree
{
    public G_JsTreeAttribute attr;
    public G_JSTree[] children;
    public string data
    {
        get;
        set;
    }
    public int IdServerUse
    {
        get;
        set;
    }
    public string icons
    {
        get;
        set;
    }
    public string state
    {
        get;
        set;
    }
}

public class G_JsTreeAttribute
{
    public string id;
    public bool selected;
}

<script type="text/javascript">
$(document).ready(function () {
$("#demo1").jstree({
        "json_data": {
            "ajax": {
                "type": "POST",
                "dataType": "json",
                "contentType": "application/json;",
                "url": "JsTree-Json.aspx/GetAllNodes11",
                "data": function (node) {
                    return '{ "operation" : "get_children", "id" : 1 }';
                },
                "success": function (retval) {
                    return retval.d;
                }
            }
        },
        "plugins": ["themes", "json_data"]
    });
});
</script>

PageMethod

[WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public static List<G_JSTree> GetAllNodes11(string id)
    {
        List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();

        G_JSTree _G_JSTree = new G_JSTree();
        _G_JSTree.data = "x1";
        _G_JSTree.state = "closed";
        _G_JSTree.IdServerUse = 10;
        _G_JSTree.children = null;
        _G_JSTree.attr = new G_JsTreeAttribute { id = "10", selected = false };
        G_JSTreeArray.Add(_G_JSTree);

        G_JSTree _G_JSTree2 = new G_JSTree();
        var children =
            new G_JSTree[]
            {
                new G_JSTree { data = "x1-11", attr = new G_JsTreeAttribute { id = "201" } },
                new G_JSTree { data = "x1-12", attr = new G_JsTreeAttribute { id = "202" } },
                new G_JSTree { data = "x1-13", attr = new G_JsTreeAttribute { id = "203" } },
                new G_JSTree { data = "x1-14", attr = new G_JsTreeAttribute { id = "204" } },
            };
        _G_JSTree2.data = "x2";
        _G_JSTree2.IdServerUse = 20;
        _G_JSTree2.state = "closed";
        _G_JSTree2.children = children;
        _G_JSTree2.attr = new G_JsTreeAttribute { id = "20", selected = true };
        G_JSTreeArray.Add(_G_JSTree2);

        G_JSTree _G_JSTree3 = new G_JSTree();
        var children2 =
            new G_JSTree[]
            {
                new G_JSTree { data = "x2-11", attr = new G_JsTreeAttribute { id = "301" } },
                new G_JSTree { data = "x2-12", attr = new G_JsTreeAttribute { id = "302" }, children= new G_JSTree[]{new G_JSTree{data = "x2-21", attr = new G_JsTreeAttribute { id = "3011" }}} },
                new G_JSTree { data = "x2-13", attr = new G_JsTreeAttribute { id = "303" } },
                new G_JSTree { data = "x2-14", attr = new G_JsTreeAttribute { id = "304" } },
            };
        _G_JSTree3.data = "x3";
        _G_JSTree3.state = "closed";
        _G_JSTree3.IdServerUse = 30;
        _G_JSTree3.children = children2;
        _G_JSTree3.attr = new G_JsTreeAttribute { id = "30", selected = true };
        G_JSTreeArray.Add(_G_JSTree3);
        return G_JSTreeArray;
    }

Example 5:
The jsTree with async loading of the children.
With async loading, all chidren are not created during the initial load of jsTree. The children are loaded, on-demand, when user tries to open any particular node. However, if any node already has childen loaded, but not visible, then an AJAX trip to server is skipped. In the following example, if the state of a given node is closed and children not loaded yet, –> when user tries to open that node, an AJAX query, fetches all children for that node, dynamically from server.

img5       img6  img7

$("#demo1").jstree({
    "json_data": {
        "ajax": {
            "type": "POST",
            "dataType": "json",
            "async": true,
            "contentType": "application/json;",
            "opts": {
                "method": "POST",
                "url": "JsTree-JsonAsync.aspx/GetAllNodes11"
            },
            "url": "JsTree-JsonAsync.aspx/GetAllNodes11",
            "data": function (node) {
                if (node == -1) {
                    return '{ "operation" : "get_children", "id" : -1 }';
                }
                else {
                //get the children for this node
                 return '{ "operation" : "get_children", "id" : ' + $(node).attr("id") + ' }';
                }
            },
            "success": function (retval) {
                return retval.d;
            }
        }
    },
    "plugins": ["themes", "json_data"]
});
private static List<G_JSTree> AddChildNodes(int _ParentID, int NumOfChildren, string ParentName)
{
    List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();
    int n = 10;
    for (int i = 0; i < NumOfChildren; i++)
    {
        int CurrChildId = (_ParentID == 0) ? n : ((_ParentID * 10) + i);
        G_JSTree _G_JSTree = new G_JSTree();
        _G_JSTree.data = (_ParentID == 0) ? "root" + "-Child" + i.ToString() : ParentName + CurrChildId.ToString() + i.ToString();
        _G_JSTree.state = "closed";  //For async to work
        _G_JSTree.IdServerUse = CurrChildId;
        _G_JSTree.children = null;
        _G_JSTree.attr = new G_JsTreeAttribute { id = CurrChildId.ToString(), selected = false };
        G_JSTreeArray.Add(_G_JSTree);
        n = n + 10;
    }
    return G_JSTreeArray;
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static List<G_JSTree> GetAllNodes11(string id)
{
    if (id != "-1") //-1 means initial load else async loading of children
    {
        if (id == "10")
            //Add 3 children to parent node with id=10.
            return AddChildNodes(10, 3, "xxxx");
        else
            return new List<G_JSTree>();
    }
    List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();

    //Creating the JsTree data
    //In live scenarios this will come from db or Web Service
    //Add 5 root nodes
    G_JSTreeArray.AddRange(AddChildNodes(0, 5, ""));

    //Add 4 children to 3rd root node
    //The third node has id=30
    //The child nodes will have ids like 301,302,303,304
    G_JSTreeArray[3].children = (AddChildNodes(30, 4, G_JSTreeArray[3].data)).ToArray();

    //Add 5 children to level1 Node at id=302
    G_JSTreeArray[3].children[1].children = (AddChildNodes(302, 4, G_JSTreeArray[3].children[1].data)).ToArray();
   
    return G_JSTreeArray;
}

Example 6:
Sync the jsTree with server. Basically passing the entire JSON from client end to server.
On server, the JSON is deserialized to corresponding c# class.

<div id="demo1">
</div>
<br />
<asp:button ID="Button1" runat="server" OnClientClick="a1(); return false;" text="Sync Tree" />

function a1() {
    var json1 = $("#demo1").jstree("json_data").get_json();
    var y1 = JSON.stringify(json1);
    $.ajax({
        type: "POST",
        url: "JsTree-SyncTree.aspx/SyncMyTree",  
        contentType: "application/json; charset=utf-8",   
        data: "{'MyTreeJson': '" + y1 + "'}",   
        dataType: "json",
        success: function (response) {
        }
    });
}

$(document).ready(function () {
    $("#demo1").jstree({
        "json_data": {
            "ajax": {
                "type": "POST",
                "dataType": "json",
                "contentType": "application/json;",
                "url": "JsTree-Json.aspx/GetAllNodes11",
                "data": function (node) {
                    return '{ "operation" : "get_children", "id" : 1 }';
                },
                "success": function (retval) {
                    return retval.d;
                }
            }
        },
        "plugins": ["themes", "json_data"]
    });
});

[WebMethod(EnableSession = true)]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public static void SyncMyTree(string MyTreeJson)
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        List<G_JSTree> G_JSTreeArray = ser.Deserialize<List<G_JSTree>>(MyTreeJson);
    }

Example 7:
Interactive jsTree with Add/Rename/Delete Node functionality.

img8

<script type="text/javascript">
    $(document).ready(function () {
        $("#demo1").jstree({
            "json_data": {
                "ajax": {
                    "type": "POST",
                    "dataType": "json",
                    "contentType": "application/json;",
                    "url": "JsTree-ContextMenu.aspx/GetAllNodes11",
                    "data": function (node) {
                        return '{ "operation" : "get_children", "id" : 1 }';
                    },
                    "success": function (retval) {
                        return retval.d;
                    }
                }
            },
            contextmenu: {
                items: function ($node) {
                    return {
                        createItem: {
                            "label": "Add Node",
                            "action": function (obj) { this.create(obj); alert(obj.text()) },
                            "_class": "class"
                        },
                        renameItem: {
                            "label": "Rename Node",
                            "action": function (obj) { this.rename(obj); }
                        },
                        deleteItem: {
                            "label": "Delete Node",
                            "action": function (obj) { this.remove(obj); }
                        }
                    };
                }
            },
            "plugins": ["themes", "json_data", "ui", "crrm", "contextmenu"]
        })
    .bind("rename.jstree", function (NODE, REF_NODE, event, data) {
        // You may run validation or fire an ajax to save it on server
        var nodeId = REF_NODE.rslt.obj[0].id;
        alert("Rename done: " + NODE.type);
        alert("Rename done: " + REF_NODE.rslt.new_name);
        alert("Rename done: " + REF_NODE.rslt.old_name);
        alert("Rename done: " + REF_NODE.rslt.obj[0].id);
        if (NODE.type === 'rename') {
            //Run Validation or
            //fire an ajax call to save the status on server
            //if validations fail rollback
            //$.jstree.rollback(data.rlbk);
            }

    });
    });
</script>
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static List<G_JSTree> GetAllNodes11(string id)
{
    List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();

    G_JSTree _G_JSTree = new G_JSTree();
    _G_JSTree.data = "x1";
    _G_JSTree.state = "closed";
    _G_JSTree.IdServerUse = 10;
    _G_JSTree.children = null;
    _G_JSTree.attr = new G_JsTreeAttribute { id = "10", selected = false };
    G_JSTreeArray.Add(_G_JSTree);

    G_JSTree _G_JSTree2 = new G_JSTree();
    var children =
        new G_JSTree[]
        {
            new G_JSTree { data = "x1-11", attr = new G_JsTreeAttribute { id = "201" } },
            new G_JSTree { data = "x1-12", attr = new G_JsTreeAttribute { id = "202" } },
            new G_JSTree { data = "x1-13", attr = new G_JsTreeAttribute { id = "203" } },
            new G_JSTree { data = "x1-14", attr = new G_JsTreeAttribute { id = "204" } },
        };
    _G_JSTree2.data = "x2";
    _G_JSTree2.IdServerUse = 20;
    _G_JSTree2.state = "closed";
    _G_JSTree2.children = children;
    _G_JSTree2.attr = new G_JsTreeAttribute { id = "20", selected = true };
    G_JSTreeArray.Add(_G_JSTree2);

    G_JSTree _G_JSTree3 = new G_JSTree();
    var children2 =
        new G_JSTree[]
        {
            new G_JSTree { data = "x2-11", attr = new G_JsTreeAttribute { id = "301" } },
            new G_JSTree { data = "x2-12", attr = new G_JsTreeAttribute { id = "302" }, children= new G_JSTree[]{new G_JSTree{data = "x2-21", attr = new G_JsTreeAttribute { id = "3011" }}} },
            new G_JSTree { data = "x2-13", attr = new G_JsTreeAttribute { id = "303" } },
            new G_JSTree { data = "x2-14", attr = new G_JsTreeAttribute { id = "304" } },
        };
    _G_JSTree3.data = "x3";
    _G_JSTree3.state = "closed";
    _G_JSTree3.IdServerUse = 30;
    _G_JSTree3.children = children2;
    _G_JSTree3.attr = new G_JsTreeAttribute { id = "30", selected = true };
    G_JSTreeArray.Add(_G_JSTree3);
    return G_JSTreeArray;
}

That’s all for now. Thanks for reading.

Advertisements
Posted in JQuery | Tagged , , | 2 Comments

iTextSharp – Creating Form fields.

Some of my readers have requested for iTextSharp checkbox, radiobutton C# samples. I basically used the Chapter8 as my reference. So, here they are.

Create RadioButtonList:

Radios[1]

public string P_InputStream = "~/pdfs/k2.pdf";
public string P_OutputStream = "~/MyPDFOutputs/ex1_1.pdf";
public static String[] LANGUAGES_gc = { "English", "German", "Spanish" };
public void CreateRadioList()
{
Document _document = new Document();
PdfReader reader = new PdfReader(Server.MapPath(P_InputStream));
using (Document document = new Document())
{
    using (PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
    {
        document.Open();
        PdfContentByte cb = writer.DirectContent;
        Font _bf = new Font(Font.FontFamily.HELVETICA, 9);
        PdfFormField _radioGroup = PdfFormField.CreateRadioButton(writer, true);
        _radioGroup.FieldName = "language_gc";
        Rectangle _rect;
        RadioCheckField _radioG;
        PdfFormField _radioField1;

        for (int i = 0; i < LANGUAGES_gc.Length; i++)
        {
            _rect = new Rectangle(40, 806 - i * 40, 60, 788 - i * 40);
            _radioG = new RadioCheckField(writer, _rect, null, LANGUAGES_gc[i]);
            _radioG.BackgroundColor = new GrayColor(0.8f);
            _radioG.BorderColor = GrayColor.BLACK;
            _radioG.CheckType = RadioCheckField.TYPE_CIRCLE;
            _radioField1 = _radioG.RadioField;
            _radioGroup.AddKid(_radioField1);
            ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase(LANGUAGES_gc[i], new Font(Font.FontFamily.HELVETICA, 18)), 70, 790 - i * 40, 0);
        }
        writer.AddAnnotation(_radioGroup);
        cb = writer.DirectContent;
        document.Close();
    }
}
}

Create one RadioButton per page:

//Add one radio per page 
public void CreateARadio()
{
    Document _document = new Document();
    PdfReader reader = new PdfReader(Server.MapPath(P_InputStream));
    using (Document document = new Document())
    {
        using (PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
        {
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            BaseFont _bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
            PdfFormField _radioGroup = PdfFormField.CreateRadioButton(writer, true);
            _radioGroup.FieldName = "language_gc";
            Rectangle _rect = new Rectangle(40, 806, 60, 788);
            RadioCheckField _radioG;
            PdfFormField _radioField1;
                
            for (int i = 0; i < LANGUAGES_gc.Length; i++)
            {
                _radioG = new RadioCheckField(writer, _rect, null, LANGUAGES_gc[i]);
                _radioG.BackgroundColor = new GrayColor(0.8f);
                _radioField1 = _radioG.RadioField;
                _radioField1.PlaceInPage = i + 1;
                _radioGroup.AddKid(_radioField1);
            }

            writer.AddAnnotation(_radioGroup);
            for (int i = 0; i < LANGUAGES_gc.Length; i++)
            {
                cb.BeginText();
                cb.SetFontAndSize(_bf, 18);
                cb.ShowTextAligned(Element.ALIGN_LEFT, LANGUAGES_gc[i], 70, 790, 0);
                cb.EndText();
                document.NewPage();
            }
            document.Close();                           
        }
    }
}

Create CheckBoxList:

CheckList[1]

public void CreateCheckBoxList()
{
    Document _document = new Document();
    PdfReader reader = new PdfReader(Server.MapPath(P_InputStream));
    using (Document document = new Document())
    {
        using (PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
        {
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            Rectangle _rect;
            PdfFormField _Field1;

            PdfAppearance[] onOff = new PdfAppearance[2];
            onOff[0] = cb.CreateAppearance(20, 20);
            onOff[0].Rectangle(1, 1, 18, 18);
            onOff[0].Stroke();

            onOff[1] = cb.CreateAppearance(20, 20);
            onOff[1].SetRGBColorFill(255, 128, 128);
            onOff[1].Rectangle(1, 1, 18, 18);
            onOff[1].FillStroke();
            onOff[1].MoveTo(1, 1);
            onOff[1].LineTo(19, 19);
            onOff[1].MoveTo(1, 19);
            onOff[1].LineTo(19, 1);
            onOff[1].Stroke();
            RadioCheckField _checkbox1;

            for (int i = 0; i < LANGUAGES_gc.Length; i++)
            {
                _rect = new Rectangle(180, 806 - i * 40, 200, 788 - i * 40);
                _checkbox1 = new RadioCheckField(writer, _rect, LANGUAGES_gc[i], "on");
                _Field1 = _checkbox1.CheckField;
                _Field1.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", onOff[0]);
                _Field1.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, "On", onOff[1]);
                writer.AddAnnotation(_Field1);

                ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase(LANGUAGES_gc[i], new Font(Font.FontFamily.HELVETICA, 18)), 210, 790 - i * 40, 0);
            }
                
            cb = writer.DirectContent;
            document.Close();
        }
    }
}

Create PushButton:

Button[1]

public void AddButton()
{
    Document _document = new Document();
    PdfReader reader = new PdfReader(Server.MapPath(P_InputStream));
    using (Document document = new Document())
    {
        using (PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
        {
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            Rectangle _rect;
            PdfFormField _Field1;

            _rect = new Rectangle(100, 806, 170, 788);
            PushbuttonField button = new PushbuttonField(writer, _rect, "Buttons");
            button.BackgroundColor = new GrayColor(0.75f);
            button.BorderColor = GrayColor.GRAYBLACK;
            button.BorderWidth = 1;
            button.BorderStyle = PdfBorderDictionary.STYLE_BEVELED;
            button.TextColor = GrayColor.GRAYBLACK;
            button.FontSize = 12;
            button.Text = "Push me";
            button.Layout = PushbuttonField.LAYOUT_ICON_LEFT_LABEL_RIGHT;
            button.ScaleIcon = PushbuttonField.SCALE_ICON_ALWAYS;
            button.ProportionalIcon = true;
            button.IconHorizontalAdjustment = 0;
            _Field1 = button.Field;
            writer.AddAnnotation(_Field1);
            cb = writer.DirectContent;
            document.Close();
        }
    }
}

Create TextBox:

txtBox[1]

public void CreateTextBoxMethod1()
{
    Document _document = new Document();
    PdfReader reader = new PdfReader(Server.MapPath(P_InputStream));
    using (Document document = new Document())
    {
        using (PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
        {
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            TextField _text = new TextField(writer, new Rectangle(40, 806, 160, 788), "g1");
            _text.Alignment = Element.ALIGN_CENTER;
            _text.Options = TextField.MULTILINE;
            _text.Text = "abc";
            writer.AddAnnotation(_text.GetTextField());
            cb = writer.DirectContent;
            document.Close();
        }
    }
}

 

public void CreateTextBoxMethod2()
{
    Document _document = new Document();
    PdfReader reader = new PdfReader(Server.MapPath(P_InputStream));
    using (Document document = new Document())
    {
        using (PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
        {
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            PdfFormField _Field1 = PdfFormField.CreateTextField(writer, false, false, 50);
            _Field1.SetWidget(new iTextSharp.text.Rectangle(40, 100, 160, 130),PdfAnnotation.APPEARANCE_NORMAL);
            _Field1.SetFieldFlags(PdfAnnotation.FLAGS_PRINT);
            _Field1.FieldName = "t1";
            writer.AddAnnotation(_Field1);
            cb = writer.DirectContent;
            document.Close();
        }
    }
}

Thanks for reading.

Posted in External Open Source APIs | Tagged , , | Leave a comment

In-memory Data Caching – few insights.

The content below assumes single Web server hosting the web application. I’m using Framework 4.0, WebForms and System.Runtime.Caching namespace’s MemoryCache class (the in-memory cache provider) meaning cache is stored in web-server’s memory. Any data or complex business object (created with data from multiple sources or after complex calculations) and very often used, can be cached. Cache by default is application scoped although based on the key can be scoped to a more granular level.Cache takes up server memory, but as against session, ASP.Net can invalidate cache and free that memory anytime. Hence it’s better to save in Cache for a small amount of time, serve that data to as many requests as possible and then release it, thereby increasing the scalability when load increases. Items in the cache can expire (will be removed from cache by ASP.Net for various reasons) and not guaranteed to be found all the time. It’s advisable to consider cache as an option, only when the performance is really affected, the page appears noticeably slow and the bottleneck has been identified.

Few examples now:
1:  Let’s say I have a page, which is loaded very often and the page does some expensive calculations on the data and then saves it to DB. Trying to use cache in this dummy example. Now when the page is
requested, if the cache is empty, I retrieve data from DB, run the calculations and save it in cache say for 10 secs. Now when multiple users update/insert data, the cache gets updated. When the cache is about to expire, it raises a callback and posts the complete set of changes to database. So for high multiple requests on this page, lot of database SQLs are saved.Here’s a custom generic cache class and a business-layer using that class.

Generic Cache Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Caching;

public class GenericCacheClass
{
    public static readonly ObjectCache cache = MemoryCache.Default;
    private static CacheEntryUpdateCallback callbackU = null;
    public static void AddToMyCache(string CacheKeyName,
                            Object CacheItem,
                            CacheItemPolicy policy, TimeSpan UpTimeInSecs)
    {
        callbackU = new CacheEntryUpdateCallback(MyCachedItemUpdatedCallback);
        policy = new CacheItemPolicy();
        policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(UpTimeInSecs.Seconds);
        policy.UpdateCallback = callbackU;
        //Set will overwrite if the key already present, 
        //else will insert it.
        cache.Set(CacheKeyName, CacheItem, policy);
    }
    
    private static void MyCachedItemUpdatedCallback(CacheEntryUpdateArguments arguments)
    {
        if (arguments.RemovedReason == CacheEntryRemovedReason.Expired)
        {
            //Post the changes to DB and 
            //then remove the item from cache.
            BusinessLayer.PostToDB(cache[arguments.Key]);
        }
    }

    public void RemoveFromCache(string key)
    {
        cache.Remove(key);
    }
    public static bool IsKeyPresent(string key)
    {
        return cache.Get(key) != null;
    }
    public static CacheItem GetCacheItem(string key)
    {
        return cache.GetCacheItem(key);
    }
    public static List<string> GetAllItems()
    {
        return cache.Select(kv => kv.Key).ToList();
    }
    public static List<string> GetAllKeys()
    {
        return cache.Select(kv => kv.Key).ToList();
    }
}
public class CustomerAddress
{
    public int AddressID { get; set; }
    public string AddressLine1 { get; set; }
    public string City { get; set; }
}

Business Class using the Cache class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Runtime.Caching;

public class BusinessLayer
{
public static IEnumerable<CustomerAddress> GetCustomerAddress()
{
    DataTable dt = new DataTable();
    //Check if present in cache
    var _CustomerAddress = GenericCacheClass.cache.GetCacheItem("AdminRole") as CacheItem;

    // If not in cache, fetch from DB
    if (_CustomerAddress == null)
    {
        dt = DataLayer.getAllAddress();
        if (_CustomerAddress is object)
        {
            //Add it in cache for 10 secs.
            GenericCacheClass.AddToMyCache("AdminRole", 
                        dt, 
                        new CacheItemPolicy(), 
                        TimeSpan.FromSeconds(10));
        }
    }
    IEnumerable<DataRow> var1 = (IEnumerable<DataRow>)dt.AsEnumerable();
    return ConvertToCustomerAddress(dt);
}

private static IEnumerable<CustomerAddress> ConvertToCustomerAddress(DataTable dataTable)
{
    foreach (DataRow row in dataTable.Rows)
    {
        yield return new CustomerAddress
        {
            AddressID = Convert.ToInt32(row["AddressID"]),
            AddressLine1 = row["AddressLine1"].ToString(),
            City = row["City"].ToString(),
        };
    }
}

private DataTable GetCustomerAddressDt()
{
    DataTable dt = new DataTable();
    //Check cache
    var _CustomerAddress = GenericCacheClass.cache.GetCacheItem("AdminRole") as CacheItem;

    // If not in cache, fetch from DB
    if (_CustomerAddress == null)
    {
        dt = DataLayer.getAllAddress();
        if (_CustomerAddress is object)
        {
            GenericCacheClass.AddToMyCache("AdminRole", 
                                    dt, 
                                    new CacheItemPolicy(), 
                                    TimeSpan.FromSeconds(10));
        }
    }
    return dt;
}

public void UpdateAddressPresentInCache(DataRow dr)
{
    DataTable dt = GetCustomerAddressDt();
    DataRow[] RowToUpdate;
    RowToUpdate = dt.Select("AddressID = "+dr["AddressID"].ToString());
    if (RowToUpdate.Count() > 0)
    {
        RowToUpdate[0]["AddressLine1"] = dr["AddressLine1"].ToString();
        RowToUpdate[0]["City"] = dr["City"].ToString();
    }
    GenericCacheClass.AddToMyCache("AdminRole", dt, new CacheItemPolicy(), TimeSpan.FromSeconds(10));
}

public static void PostToDB(object dt)
{
    //The cache is about to expire.
    //Post all the changes done in Address DataTable as present in Cache to DB
    //Your code to UpdateDB
}

}

Codebehind:

private void BindRepeater()
    {
        Repeater1.DataSource = BusinessLayer.GetCustomerAddress();
        Repeater1.DataBind();
    }

2: Cache can be used as an alternative to ViewState.
Say as an example, I have a heavy complex page which uses 4 or 5 UserControls. On the Page Load I fetch a big DataSet containing multiple resultsets from the DB. Now using that Dataset, I can create some
custom objects holding different set of processed data or just plain individual DataTables. When the page postbacks to itself, if required, all those 4/5 user controls can grab data from the cache instead of ViewState. If the data is user specific, then a user-specific key can be generated and cache-duration can be kept to just few seconds depending on that particular page’s functionality. Cache entry can be evicted based on other key-dependency too and not just absolute seconds.

3: SqlDataSource and ObjectDataSource supports built-in caching. As an example, SqlDataSource if used with DataSet can take advantage of Caching. This can be immensely helpful if the parent Databound control like ListView, GridView has pager associated with it. Then during paging, the data can be retrieved from cache. More here  http://msdn.microsoft.com/en-us/library/z56y8ksb(v=vs.100).aspx

4: PageMethods can use caching. For example:
[WebMethod(CacheDuration=90)]
public static void abc()
{
//function implementation
}

Apart from these, any kind of masterdata like country names,products, which changes in-frequently, but used often, are good candidates of caching.The cache configuration can be stored in web.config file, so the eviction times or any other property can be dynamically changed without any code-change. Summarily, caching isn’t free because it saves items in server memory. It’s a delicate balance between memory,usage and cache-eviction. If by keeping certain chunk of data in memory, brings on a big performance-boost then fine, else database is a better place to save. Also no point in reserving server memory (by using cache) for something, which will be used very rarely.

Thanks for reading.

Posted in General ASP.Net C# | Tagged | Leave a comment

Working with Visual Studio’s Profiler

The in-built Visual Studio’s Profiler can quickly detect performance bottlenecks. To get started with Profiler, you would need Visual Studio Ultimate or Premium version. It’s located under VS top menu -> Analyze->Launch Performance Wizard. In step1, choose “Instrumentation” then follow subsequent steps till finish.

2

Few basic definitions, better be familiar with.

Elapsed Inclusive Time = Time spent on this current function and children (ms)
Elapsed Exclusive time = Time spent on this current function (ms)
App Inclusive time = Processing time on this current function and children without wait time for IO or other threads.

Here’s the basic summary view after code profiling is completed on my simplified example page.

5

Notice the section “Functions with most individual work”. At the top is the most expensive function. Click on that and it will lead you to this view.

  6

Most of the time, “Elapsed Exclusive time” along with Caller/Callee view can detect the biggest hurdle in minutes.
Elapsed Exclusive time is basically the time took to execute only those lines of code in that function without any external I/O or wait.
So if I go to the most nested function in any costly execution chain, costly in terms of time/resources, I already know the major hurdle.
This view basically tells all —
1) How much time was spent on that particular function
2) Which all functions called that function and how many times each?
3) This function called which all functions and their respective time.

7

Another view which I found very helpfull is functions.
This view lists all functions with the various amount of time each one took.

9

This tool just helps in detecting the most performance-expensive piece of code. We need to go back and fix the code and again run profiler to see the relative performance-gain.
The profiling results can be compared, filtered, exported to a csv/excel file. The profiler can be paused/resume to profile only the affected chain of logic.

Enjoy profiling. Thanks for reading.

Posted in General ASP.Net C# | Leave a comment

Exploring JQuery plugin ‘FullCalendar’.

Here’s the author’s weblink on this tremendous open-source calendar based scheduler. Everything to get started with this plugin can be found here, (ie docs, demos, download etc.)
http://arshaw.com/fullcalendar/

I basically tried to run those same examples using ASP.Net/C#. Fullcalendar is extremely customizable and very easy to alter/adapt as per the application needs. As of now, Fullcalendar does not inherently support “Recurring Events”. I developed 2 examples on Recurring events on top of this calendar — one that recurs daily and another monthly. All my recurring logic is on the server. On the topic of “Recurring Events”, I actually borrowed the main idea from Telerik’s  RadScheduler. In RadScheduler, there is something called “RecurrenceRule” which basically consists of EventStartdate, EventEndDate, Frequency (ie daily or weekly or monthly), Interval of Occurance in a string variable. An example of RadScheduler Recurrence Rule:

string rRule = "{DTSTART:20120808T110000ZDTEND:20120808T113000ZRRULE:FREQ=DAILY:COUNT=3;INTERVAL=5;BYDAY=MO,TU,WE,TH,FR,SA,SU}";

Based on that, RadScheduler dynamically generates range of occurance dates at runtime. I tried to mimic exact same on fullCalendar. The main challenge was to write the recurring logic myself. Once the event occurance dates are obtained, at runtime, I generate those many events on those dates and push that complete List-array of events to client.That’s it. From there on, FullCalendar takes care of everything. Here are those examples.
Ex 1:- A basic Fullcalendar getting bunch of events from server as well as have the ability to update an event,  Events can be dragged, resized, dropped on the calendar. On any of this action a AJAX request can be sent to server to save the changes.

img1

<link rel='stylesheet' type='text/css' href='fullcalendar/fullcalendar.css' />
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.js" type="text/javascript"></script>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js" type="text/javascript"></script>
    <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
    <script type='text/javascript' src='fullcalendar/fullcalendar.min.js'></script>
    <script src="https://github.com/douglascrockford/JSON-js/raw/master/json2.js" type="text/javascript"></script>
    <script src="jquery/jquery-ui-timepicker-addon-0.6.2.min.js" type="text/javascript"></script>
    <script type='text/javascript' src='Scripts/jquery.qtip-1.0.0-rc3.min.js'></script>
<script type="text/javascript">
function UpdateMyEvent(event) {
var eventToSave = new Object(); ;
eventToSave.EventID = event.id ;
eventToSave.StartDate = event.start.toLocaleString();
eventToSave.EndDate = event.end.toLocaleString();
eventToSave.EventName = event.title;
$.ajax({
type: "POST",
contentType: "application/json",
data: "{eventdata1:" + JSON.stringify(eventToSave) + "}",
url: "ExToolTip2.aspx/UpdateEvent",
dataType: "json",
error: function (XMLHttpRequest, textStatus, errorThrown) {
    debugger;
}
});
}


$(document).ready(function () {
DisplayCalendar();
});

function DisplayCalendar() {
$.ajax({
type: "POST",
contentType: "application/json",
data: "{}",
url: "ExToolTip2.aspx/GetEvents",
dataType: "json",
success: function (data) {
    $('div[id*=calendar]').fullCalendar({
        header: {
            left: 'prev,next today',
            center: 'title',
            right: 'month,agendaWeek,agendaDay'
        },
        selectable: true,
        editable: true,
        droppable: true,
        draggable: true,
        selectable: true,
        selectHelper: true,
        eventTextColor: 'Yellow',
        eventBackgroundColor: 'purple',
        events:
        $.map(data.d, function (item, i) {
            var event = new Object();
            event.id = item.EventID;
            event.start = item.StartDate;
            event.end = item.EndDate;
            event.title = item.EventName;
            event.allDay = false;
            if (event.title == 'Event_1') {
                event.color = "DarkBlue";
                event.textColor = "DarkBlue";
                event.backgroundColor = "yellow";
                event.title = "Important Meeting";
            }
            return event;
        }),
        eventRender: function (event, element) {
            element.attr("categories", event.categoryname),
            element.qtip({
                content: event.title + "<br>" + event.start,
                position: { corner: { tooltip: 'bottomLeft', target: 'topRight'} },
                style: {
                    border: {
                        width: 1,
                        radius: 3,
                        color: 'green'
                    },
                    padding: 10,
                    textAlign: 'left',
                    tip: true
                }
            });
        },
        eventAfterRender: function (event, element, view) {
        },
        eventResize: function (event, dayDelta, minuteDelta, revertFunc) {
            if ($(this).data("qtip")) $(this).qtip("destroy");
            if (!confirm("is this okay?")) {
                revertFunc();
            }
            else {
                UpdateMyEvent(event);
            }
        },
        eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {
            if ($(this).data("qtip")) $(this).qtip("destroy");
        }
    });

},
error: function (XMLHttpRequest, textStatus, errorThrown) {
    debugger;
}
});
}
</script>
<body>
<form id="form1" runat="server">
<div id='calendar'></div>
</form>
public class Event
{
    public int? EventID { get; set; }
    public string EventName { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
}
[System.Web.Services.WebMethod]
public static List<Event> GetEvents()
{
    List<Event> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<Event>)HttpContext.Current.Session["events"];
    else
    {
        events = new List<Event>();
        for (int i = 0; i < 5; i++)
        {
            Event _Event = new Event();
            _Event.EventID = i;
            _Event.EventName = "Event_" + i.ToString();
            _Event.StartDate = DateTime.Now.DayOfWeek + ", " + DateTime.Now.AddDays(i + 2).ToString();
            _Event.EndDate = DateTime.Now.DayOfWeek + ", " + DateTime.Now.AddDays(i + 2).ToString();
            events.Add(_Event);
        }
    }
    HttpContext.Current.Session["events"] = events;
    return events;
}

[System.Web.Services.WebMethod]
public static bool UpdateEvent(Event eventdata1)
{
    List<Event> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<Event>)HttpContext.Current.Session["events"];
    else
        events = new List<Event>();
    if (events.Contains(eventdata1))
    {
        //Update DB
        Event _MyEvent = events.Find(
        delegate(Event bk)
        {
            return bk.EventID == eventdata1.EventID;
        });
        if (_MyEvent is object)
        {
            _MyEvent.StartDate = eventdata1.StartDate;
            _MyEvent.EndDate = eventdata1.EndDate;
        }
    }
    HttpContext.Current.Session["events"] = events;
    return true;
}

Ex 2:- A Daily Recurring Event

img3

<script type='text/javascript'>
$(document).ready(function () {
    DisplayCalendar();
    $('#chkRec').click(function () {
        if ($(this).is(':checked')) {
            $('#RecEvent').show();
        }
        else {
            $('#RecEvent').hide();
        }
    });
});

function DisplayCalendar() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();

var calendar = $('#calendar').fullCalendar({
    header: {
        left: 'prev,next today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay'
    },
    eventRender: function(event, element) {
    element.qtip({
    content: event.description
    });
    },
    selectable: true,
    eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {
    },
    dayClick: function(date, allDay, jsEvent, view) {
        //$(this).css('background-color', 'red');
    },
 
    selectHelper: true,
    select: function (start, end, allDay) {
        $("#StartDt").val("" + start.toLocaleString());
        $("#EvtStartDt").val("" + start.toLocaleString());

        $("#EndDt").val("" + end.toLocaleString());
        $("#EvtEndDt").val("" + end.toLocaleString());

        $("#ModalAdd").dialog(
        {
            title: "Add event",
            width: 500,
            modal: true,
            buttons: {
                "Add": function () {
                    var event = new Object(), eventToSave = new Object(); ;
                    eventToSave.EventID = event.id = Math.floor(200 * Math.random());
                    event.start = new Date($("#StartDt").val());
                    eventToSave.StartDate = $("#StartDt").val();
                    eventToSave.EndDate = $("#EndDt").val();
                    eventToSave.EventName = event.title = eventToSave.title = $("#Name").val();
                    if ($('#chkRec').is(':checked')) {
                        eventToSave.title += " (Recurring)";
                        eventToSave.IsRecurring = true;
                        eventToSave.Freq = "Daily";
                        eventToSave.Count = $("#txtCount").val();
                        eventToSave.Interval = $("#txtInterval").val();
                    }
                    $.ajax({
                        type: "POST",
                        contentType: "application/json",
                        data: "{eventdata:" + JSON.stringify(eventToSave) + "}",
                        url: "Test2.aspx/AddEvents",
                        dataType: "json",
                        success: function (data) {
                            var events = new Array();
                            $.map(data.d, function (item, i) {
                                var event = new Object();
                                event.id = item.EventID;
                                event.start = new Date(item.StartDate);
                                event.end = new Date(item.EndDate);
                                event.title = item.EventName;
                                event.allDay = false;
                                events.push(event);
                            })
                            $('div[id*=calendar]').fullCalendar('addEventSource', events);
                            $("#ModalAdd").dialog("close");
                        },
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            debugger;
                        }
                    });
                }
            }
        });
        calendar.fullCalendar('unselect');
    },
    editable: true,
    droppable: true,
    draggable: true,
    eventTextColor: 'Yellow',
    eventBackgroundColor: 'purple'
});
}
    </script>

<div id="ModalAdd" style="display:none;width:400px;">
<div id="AddEvent" style="width:400px;" >
    Event Name:&nbsp;
    <input id="Name" type="text" style="width:200px;" /><br /><br />
    Start date:&nbsp;&nbsp;
    <input id="StartDt" type="text" style="width:360px;" /><br /><br />
    End date:&nbsp;&nbsp;
    <input id="EndDt" type="text" style="width:360px;" /><br /><br />
    Recurrence: <input type="checkbox" id="chkRec" />
    <br />
</div>

<div id="RecEvent" style="display: none; width:400px;">
    <hr />
    <b>Repeat:</b><br />
    Daily:   | &nbsp;&nbsp;&nbsp; Every <input id="txtInterval" type="text" style="width:30px;" /> day(s).
    <br /><br />
    End after <input id="txtCount" type="text" style="width:30px;" /> occurences.<br />
</div>        
</div>

<div id="calendar"></div>
</form>
[System.Web.Services.WebMethod]
public static List<MyEvent> AddEvents(MyEvent eventdata)
{
    List<MyEvent> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<MyEvent>)HttpContext.Current.Session["events"];
    else
        events = new List<MyEvent>();
    if (eventdata.IsRecurring)
    {
        string stDate = eventdata.StartDate;
        string EndDate = eventdata.EndDate;
        DateTime dtStart = DateTime.Parse(stDate.Split(',')[1] + stDate.Split(',')[2]);
        DateTime dtEnd = DateTime.Parse(EndDate.Split(',')[1] + EndDate.Split(',')[2]);
        int i = 0;
        int TotalCnt = eventdata.Count;
        do
        {
            if (eventdata.Freq == "Daily")
            {
                MyEvent _Event = new MyEvent();
                _Event.StartDate = dtStart.DayOfWeek + ", " + dtStart;
                _Event.EndDate = dtEnd.DayOfWeek + ", " + dtEnd;
                _Event.EventName = eventdata.EventName;
                _Event.EventID = eventdata.EventID + i;

                dtStart = dtStart.AddDays(eventdata.Interval);
                dtEnd = dtEnd.AddDays(eventdata.Interval);
                events.Add(_Event);
            }
            i++;
        } while (i < TotalCnt);
    }
    else
    {
        events.Add(eventdata);
    }
    HttpContext.Current.Session["events"] = events;
    return events;
}
public class MyEvent
{
    public int? EventID { get; set; }
    public string EventName { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
    public bool IsRecurring { get; set; }
    public string Freq { get; set; }
    public string ByDay { get; set; }
    public int Count { get; set; }
    public int Interval { get; set; }
    public bool allDay = false;
}

Ex 3:- A monthly recurring Event
In this example an outside event is dragged on the calendar. On the event click that particular event is made monthly recurrent. Client side code is similar as above.

img5

img7

public class RecMthEvent
{
    public int? EventID { get; set; }
    public string EventName { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
    public bool IsRecurring { get; set; }
    public string Freq { get; set; }
    public double DayInterval { get; set; }
    public int Count { get; set; }
    public int Interval { get; set; }
    public bool allDay = false;
}

[System.Web.Services.WebMethod]
public static List<RecMthEvent> AddEvents(RecMthEvent eventdata)
{
    List<RecMthEvent> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<RecMthEvent>)HttpContext.Current.Session["events"];
    else
        events = new List<RecMthEvent>();
    string stDate = eventdata.StartDate;
    string EndDate = eventdata.EndDate;
    DateTime dtStart = DateTime.Parse(stDate.Split(',')[1] + stDate.Split(',')[2]);
    DateTime dtEnd = DateTime.Parse(EndDate.Split(',')[1] + EndDate.Split(',')[2]);

    int TotalCnt = eventdata.Count;
    TimeSpan ts = dtEnd - dtStart;
    for (int r = 0; r < TotalCnt; r++)
    {
        RecMthEvent _MyEvent = new RecMthEvent();
        int CurrMonth = dtStart.Month;
        DateTime dtStart2 = dtStart.AddMonths(eventdata.Interval);
        int DestMonth = dtStart2.Month;
        dtStart2 = dtStart2.AddDays(-(dtStart.Day-1));
        dtStart2 = dtStart2.AddDays(eventdata.DayInterval - 1);
        DateTime dtEnd2 = dtStart2.Add(ts);
        dtStart = dtStart2;

        _MyEvent.EventID = eventdata.EventID + r;
        _MyEvent.StartDate = dtStart2.DayOfWeek + ", " + dtStart2;
        _MyEvent.EndDate = dtEnd2.DayOfWeek + ", " + dtEnd2;
        _MyEvent.EventName = eventdata.EventName;
        events.Add(_MyEvent);
    }
    return events;
}

That’s all for now. Thanks for reading.

Posted in External Open Source APIs, JQuery | Tagged , | 5 Comments

Few random development Tips-N-Tricks-8

A simple technique to generate weekly recurring dates in C#.

img1

aspx

<form id="form1" runat="server">
<div>
<h1>Weekly Recurring Date Generation</h1>
<b>Choose Date:</b>&nbsp;<asp:Calendar ID="Calendar1" runat="server"></asp:Calendar><br />
Generate Dates For every <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> weeks.
<br />
    <asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatDirection="Horizontal" RepeatColumns="4">
    <asp:ListItem Value="1" Text="Monday"></asp:ListItem>
    <asp:ListItem Value="2" Text="Tuesday"></asp:ListItem>
    <asp:ListItem Value="3" Text="Wednesday"></asp:ListItem>
    <asp:ListItem Value="4" Text="Thursday"></asp:ListItem>
    <asp:ListItem Value="5" Text="Friday"></asp:ListItem>
    <asp:ListItem Value="6" Text="Saturday"></asp:ListItem>
    <asp:ListItem Value="7" Text="Sunday"></asp:ListItem>
    </asp:CheckBoxList>
<br />
End after <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> occurances.
<br />   
<asp:button ID="Button1" runat="server" text="Generate Occurances" 
        onclick="Button1_Click" />
<br /><br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</div>
</form>

Codebehind.

protected void Button1_Click(object sender, EventArgs e)
{
    Label1.Text = "";
    DateTime today = Calendar1.SelectedDate;
    int _Interval = int.Parse(TextBox1.Text);
    for (int r = 0; r < int.Parse(TextBox2.Text); r++)
    {
        foreach (ListItem li in CheckBoxList1.Items)
        {
            if (li.Selected)
            {
                GenerateOccurances(today, _Interval, int.Parse(li.Value));
            }
        }
        //Change the week for next interval
        today = today.AddDays(7 * _Interval);
        Label1.Text += "<br>***************************";
    }
}
private void GenerateOccurances(DateTime today, int _interval, int CurrdayOfWeek)
{
    int n1 = -1;
    if (today.DayOfWeek == DayOfWeek.Monday)
    {
        n1 = 1;
    }
    if (today.DayOfWeek == DayOfWeek.Tuesday)
    {
        n1 = 2;
    }
    if (today.DayOfWeek == DayOfWeek.Wednesday)
    {
        n1 = 3;
    }
    if (today.DayOfWeek == DayOfWeek.Thursday)
    {
        n1 = 4;
    }
    if (today.DayOfWeek == DayOfWeek.Friday)
    {
        n1 = 5;
    }
    if (today.DayOfWeek == DayOfWeek.Saturday)
    {
        n1 = 6;
    }
    if (today.DayOfWeek == DayOfWeek.Sunday)
    {
        n1 = 7;
    }
    //Add weeks
    DateTime CurrDate = today.AddDays(7*_interval);
    int DayDiff = n1 - CurrdayOfWeek;
    if (DayDiff != 0)
    {
        DateTime FutureDate = CurrDate.AddDays(-DayDiff);
        Label1.Text += "<br> Future Date:&nbsp;&nbsp;&nbsp;" + FutureDate.DayOfWeek + ", " + FutureDate.ToString();
    }
    else
    {
        DateTime FutureDate = CurrDate;
        Label1.Text += "<br> Future Date:&nbsp;&nbsp;&nbsp;" + FutureDate.DayOfWeek + ", " + FutureDate.ToString();
    }
}

Thanks for reading.

Posted in General ASP.Net C# | Leave a comment

Accessing ViewState mutually between PageControl and UserControl.

In my current project, I needed to save a bool variable in UserControl’s ViewState and had to access that in the Parent Container Page. After some thought, here’s a refined approach on this task. To begin with, in asp.net webforms world, ViewState is every control’s own private small storage, usefull during postbacks, for small quantity of data.   
http://msdn.microsoft.com/en-us/library/system.web.ui.control.viewstate.aspx

System.Web.UI.Control  (has the ViewState property) 
   |
   ——>  System.Web.UI.Page  (Page Control has it’s own ViewState, which no other control can access)
   |
   —–>  System.Web.UI.UserControl (UserControl has it’s own ViewState, which no other control can access)   
Hence the Page control’s (aspx Page’s) ViewState can NOT be accessed in a UserControl directly and vice-versa. However if the ViewState information is exposed through public property, this gets easy. In this example below, the aspx Page is derived from a Base page class. The Base Page class has a public property which exposes the Page’s ViewState Value — which in turn can be accessed by the UserControl contained within that page. And similar, with UserControl too.

Base Page class

public class BasePage : System.Web.UI.Page
{
    public int ParentPageVSValue
    {
        get
        {
            if (ViewState["_ParentPageVSValue"] != null)
                return int.Parse(ViewState["_ParentPageVSValue"].ToString());
            else
                return 0;
        }
        set
        {
            ViewState["_ParentPageVSValue"] = value;
        }
    }
}

codebehind

public partial class ParentPage1 : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        ParentPageVSValue = 89;
    }
}
protected void Button1_Click(object sender, EventArgs e)
{
    //Can not access UserControl's ViewState
    var t = ViewState["_Test1"]; //t is null

    //Can access UserControl's public property which
    //returns Viewstate value
    int y1 = TestUserControl11.Test1;
}
}

UserControl

public int Test1
{
    get
    {
        if (ViewState["_Test1"] != null)
            return int.Parse(ViewState["_Test1"].ToString());
        else
            return 0;
    }
    set
    {
        ViewState["_Test1"] = value;
    }
}

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Test1 = 3;
    }
}

protected void Button1_Click(object sender, EventArgs e)
{
    //returns null if you try to access Parent Page's ViewState
    var t = ViewState["_ParentPageVSValue"];  //t is null.

    //The public property returns the valid value.
    int y1 = ((BasePage)(this.Page)).ParentPageVSValue; 
}

2

That’s all about it. Thanks for reading.

Posted in General ASP.Net C# | Leave a comment