Thursday, May 31, 2012
Win A Free Copy of Packt's Windows Identity Foundation book
Overview of Microsoft
Windows Identity Foundation Cookbook
Wednesday, March 10, 2010
Leveraging new delegates in C# 3.0
I interview a lot of developers and when I ask them about delegates there is this one answer everybody seems to know – “delegates are nothing but function pointers”. Well…my friend, you will be trying hard in the next five minutes to actually point to functions, I think to myself and fire another question – “if I give you a function, can you write me a delegate that can call the function?” and there you see myriads of delegate usages some of which can even stump the mighty compiler . Very few can do it right. If you are getting an unusually uncomfortable feeling, it’s time to revisit this old friend .
Assuming the reader is familiar with fundamental delegate concepts, let me introduce two extremely helpful delegates in the BCL - Action & Func . They have been used heavily in the BCL and as of .Net 4.0 each can represent functions taking up to 16 parameters (1, 2). Let’s look at the usage of each.
Func: Let’s see how Where extension method is defined on the IEnumerable class
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
foreach (TSource element in source)
{
if (predicate(element))
yield return element;
}
}
The above says you can pass your own method which returns true/false based on your logic to the Where method on any class that implements IEnumerable and you will get a filtered collection back. Sample usage: we have a list of names and we want to get names starting with character ‘a’
List<string> names = new List<string> { "Amit", "Raghu", "Piyush", "Ashok" };
Our helper method would look like:
public static bool StartsWithA(string name)
{
return name.ToLower().StartsWith("a");
}
Here is how we could achieve the result:
var namesStartingWithA = names.Where(StartsWithA);
The above could be done more elegantly with the lambda expression as:
var namesStartingWithA = names.Where(name => name.ToLower().StartsWith("a"));
Action: I’ve long stopped writing foreach loops on collections whenever I want to get a new set of elements from the collection with some action being performed on each element. I use the ForEach extension method now, which is defined as below:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (T element in source)
action(element);
}
The above basically performs an Action (supplied by the developer) on each element of a collection. Here is how we can use this in the above example for names:
List<string> namesAppendedWithZ = new List<string>();
names.ForEach(name => namesAppendedWithZ.Add(string.Format("{0}z", name)));
Lambda expression syntax is used for brevity. We can have a helper method as well to do the same job.
Using Action delegate with events
If you are fond of event based programming like me (observer is my favorite pattern), Action delegate can save you a lot of key strokes. Let’s consider a scenario in which we have a user control on which we can enter Employee information and create a new employee in database. We want to expose an event that can be raised on Employee successful creation and an entity (separate from the user control, e.g. the container form) interested can subscribe to the event and have access to the newly created Employee info. Below is how we can define the event leveraging the Action delegate:
public event Action<Employee> employeeCreatedEvent;
If we are to do this in the traditional sense, we will have to define the event like this:
public event EventHandler<EmployeeEventArgs> employeeCreatedEvent;
With an extra overhead of creating a new EventArgs derived class (data carrier) as below:
public class EmployeeEventArgs : EventArgs
{
public Employee EmployeeInfo { get; set; }
}
I’m a lazy programmer and Action delegate is a god send for guys like me . Here is how the event can be raised from the user control:
private void Create()
{
//Read info from UI and fill employee dto
Employee emp = new Employee {ID=null, Name=??};
db.CreateEmployee(emp);
if(employeeCreatedEvent != null)
employeeCreatedEvent(emp);
}
And here is how it can be subscribed to on the interested component:
ucEmployee.employeeCreatedEvent += new Action<Employee>(ucEmployee_employeeCreatedEvent);
That’s all, hope this is useful.
Happy Programming!!
- Pushp
Thursday, May 7, 2009
Comparing two objects for equality [Value Equality]
There could be numerous implementations for comparing two objects for equality. Here is the generic implementation of the comparer I have been using:
namespace Utilities
{
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class ComparerUtil
{
public static bool ValueEquals<T>(T lhs, T rhs)
where T : class
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream lhsStream = new MemoryStream();
MemoryStream rhsStream = new MemoryStream();
try
{
if ((lhs == null) && (rhs == null))
return true;
if ((lhs == null) || (rhs == null))
return false;
formatter.Serialize(lhsStream, lhs);
formatter.Serialize(rhsStream, rhs);
byte[] lhsByteArray = lhsStream.ToArray();
byte[] rhsByteArray = rhsStream.ToArray();
return ArrayValueEquals(lhsByteArray, rhsByteArray);
}
finally
{
lhsStream.Close();
rhsStream.Close();
}
}
public static bool ArrayValueEquals<T>(T[] lhsArray, T[] rhsArray)
{
if (lhsArray.Length != rhsArray.Length)
return false;
for (int index = 0; index < lhsArray.Length; ++index)
if (!lhsArray[index].Equals(rhsArray[index]))
return false;
return true;
}
}
}
The above implementation does a byte-by-byte comparison after serializing the two objects in question to binary format. This means that the two objects being compared must be serializable. Note the usage of generics which are available only .Net 2.0 upwards. If you are using .Net 3.5 (which is cool ;)), consider writing the implementation using Extension Methods.
Cheers,
Pushp
Sunday, September 7, 2008
Two nifty tools to increase your productivity on windows
While there are a number of tools to make your life hassle free on windows, the two I found very useful are below:
- Launchy: No more searching through your all programs to find that program whose location you d0n't exactly remember or don't care to remember. Just type first few letters of the program name and you have it, right from your desktop.
- USB Disk Ejector: If you keep most of your data on portable drives or happen to do a lot of plug-in and plug-out on your USB drive, this one could save you a lot of time. No more right-clicking that pathetic windows system tray icon and going through all that "Safe Eject" thing. Here is a nice tutorial to get max out of this nice little utility.
Enjoy!!
Tuesday, May 20, 2008
Leveraging Asp.Net WebForms Client Library
<%@ Page Language="C#" MaintainScrollPositionOnPostBack="true"
AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
or appliying it sitewide thru web.config as:
<system.web>
<pages maintainScrollPositionOnPostBack="true">
</pages>
</system.web>
The script file is included in my page as:
<script type="text/javascript" src="/TestWebsite/WebResource.axd?d=X2ApKqYNd-qiVRFcah5bwg2&t=633437918395970000">
Following is the list of some of the commonly used functions present in the library:
WebForm_GetScrollX
WebForm_GetScrollY
WebForm_SetElementX
WebForm_SetElementY
WebForm_GetElementById
WebForm_SetElementWidth
WebForm_SetElementHeight
WebForm_RemoveClassName
WebForm_AppendToClassName
WebForm_GetParentByTagName
WebForm_GetElementByTagName
WebForm_GetElementsByTagName
WebForm_GetElementPosition - another version here
Hope this is helpful.
pushp
Thursday, April 3, 2008
AJAX Issues With WATIN
I had a master dropdownlist and a child dropdownlist (this is disabled until something is selected in the master DDL). On the selection of an item in the master DDL there is an AJAX postback that would get data for the child DDL and then an item in the child DDL will be selected. To automate this scenario I wrote the following code:
IE ie = new IE("http://localhost/MySite/Default.aspx");
SelectList ddlMaster = ie.SelectList("ddlMaster");
ddlMaster.Option(Find.ByValue("India")).Select();
SelectList ddlChild = ie.SelectList("ddlChild");
ddlChild.Option(Find.ByValue("Hyderabad")).Select();
The Problem: The first DDL gets selected perfectly and an asynchronous postback happens but I get an exception in the fourth line (which tries to select a value in the child DDL) saying "Could not find OPTION element tag matching criteria: Attribute 'value' with value 'Hyderabad'". The problem was clear - we are trying to select a value in the child DDL before asynchronous postback is over and the child DDL is populated with values.
The first thought that came into my mind was to put a Thread.Sleep but I know it wasn't a good solution since I can never be sure of how long the asynchronous request is going to take. So I looked for something that could tell me if page is still in async postback. Enter the PageRequestManager Class in asp.net ajax. It has a property called isInAsyncPostback that you can query to know if page is in async postback. So all I needed was a way to run some javascript from the code and thank god, there is Eval in Watin to do just that.
The Solution:
1)Updated the aspx page with a method to return true if page is in async postback as below:
<asp:ScriptManager ID="scrptMgr" runat="server" EnablePartialRendering="true">
</asp:ScriptManager> <!-- script manager shown for completeness -->
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
function IsPageInAsyncPostback(){
return prm.get_isInAsyncPostBack();
}
</script>
2) Wrote a helper method to wait until async postback is complete:
private static void WaitForAsyncPostBackToComplete(IE ie)
{
bool isInPostback = true;
while (isInPostback)
{
isInPostback = Convert.ToBoolean(ie.Eval("IsPageInAsyncPostback();"));
if (isInPostback)
Thread.Sleep(200); //sleep for 200ms and query again
}
}
3) Updated the test scenario code as below:
IE ie = new IE("http://localhost/MySite/Default.aspx");
SelectList ddlMaster = ie.SelectList("ddlMaster");
ddlMaster.Option(Find.ByValue("India")).Select();
WaitForAsyncPostBackToComplete(ie);
SelectList ddlChild = ie.SelectList("ddlChild");
ddlChild.Option(Find.ByValue("Hyderabad")).Select();
and all was merry!!!
Hope this is helpful.
pushp
Wednesday, June 20, 2007
Asp.Net Viewstate
The other day i stumbled upon an excellent article that tells you everything you need to know about asp.net viewstate. Check it out here: http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx
Happy Programming!!
Monday, June 18, 2007
Firefox is the way to go..
Few of my favourite ones are:
Cooliris Previews: This add-on allows you to preview links on a page, i.e., you can view pages pointed to by the links on the current page, directly inside your current page without leaving it.
IE Tab: Some sites render properly only in IE and they would have imperfect appearance in Firefox(experienced this with MSDN site a lot). Now we have a great add-on called IE Tab that embeds IE directly in the firefox tabs. In effect IE's rendering engine is used for the sites you would like to open in IE.
FoxMarks: Take your bookmarks wherever you go.
Finally, if you are a web developer Firebug is indispensable.
Folks, don't miss this great experience anymore...go and install Firefox.
Wednesday, June 13, 2007
Getting TreeNode values on the client side with javascript
href="javascript:__doPostBack('TreeView1','sRoot\\firstChild\\...\\nodeValue')"
All we have to do is to extract that bold part from what the href property gives us.
Whereas there may be various scenarios where we may need the node value on the client, I would demonstrate it for the case of the node click itself - you want the value when you click a treenode. Try this:
1) Add an attribute to the treeview in code behind as:
if (!IsPostBack) |
2) Put the below code in head tag of .aspx page
Oops!! The current security settings of your browser do not allow the scripts on the page to access your clipboard.If you are using mozilla firefox, you may change security settings as follows: Type about:config in the url bar and set signed.applets.codebase_principal_support to true. For more info, check here or contact blog author. |
<script type="text/javascript"> |
Another scenario i can think of is when you have check boxes in the treeview and you want to get the nodevalue for the node that is checked. In that case you can just get the checkbox ( rendered as input tag) element first and then you can get the reference to the node via the nextSibling property for the checkbox.
That's all. Hope this is helpful.
pushp
Tuesday, June 5, 2007
Client Side Expand/Collapse All Nodes For ASP.NET 2.0 Treeview
Oops!! The current security settings of your browser do not allow the scripts on the page to access your clipboard.If you are using mozilla firefox, you may change security settings as follows: Type about:config in the url bar and set signed.applets.codebase_principal_support to true. For more info, check here or contact blog author. |
function TreeviewExpandCollapseAll(treeViewId, expandAll)
{
var displayState = (expandAll == true ? "none" : "block");
var treeView = document.getElementById(treeViewId);
if(treeView)
{
var treeLinks = treeView.getElementsByTagName("a");
var nodeCount = treeLinks.length;
for(i=0;i<nodeCount;i++)
{
if(treeLinks[i].firstChild.tagName)
{
if(treeLinks[i].firstChild.tagName.toLowerCase() == "img")
{
var currentToggleLink = treeLinks[i];
var childContainer = GetParentByTagName("table", currentToggleLink).nextSibling;
if (childContainer.style.display == displayState)
{
eval(currentToggleLink.href);
}
}
}
}//for loop ends
}
}
//utility function to get the container of an element by tagname
function GetParentByTagName(parentTagName, childElementObj)
{
var parent = childElementObj.parentNode;
while(parent.tagName.toLowerCase() != parentTagName.toLowerCase())
{
parent = parent.parentNode;
}
return parent;
}
Get Formatted Version Of Above Script
The above script could be used as:
<a href="javascript:TreeviewExpandCollapseAll('<%=TreeView1.ClientID%>', true)">Expand All</a>
<a href="javascript:TreeviewExpandCollapseAll('<%=TreeView1.ClientID%>', false)">Collapse All</a>
<asp:TreeView ID="TreeView1" .....................
That's all there is to it.
Hope this is helpful.
Update (7/25/2008): The script has been updated to fix a minor bug concerning the toggle images being screwed up if ShowLines is false for the treeview. Thanks to comments from users, particularly to ryan.
pushp
Monday, June 4, 2007
Asp.Net 2.0 Treeview Checkbox Check/Uncheck All script
1)Check all the child nodes if the parent is checked and uncheck all child nodes if parent is unchecked ( well, this part is simple).
2)If a node at any level is checked and all its siblings are already checked then the parent node should be checked and the same should apply for the parent node(i.e., if its siblings are checked....), this should happen till the root node.
3)If a node at any level is unchecked then the parents( ma, grand ma, grand grand ma....) up to the root node must be unchecked.
Well there have been scripts on the net that only half accomplished the task(check footnotes). So I wrote the script that solves the problem completely, upto best of my knowledge. I've tested in IE 7 and Firefox 2.0, hope it works fine for you all.
Here's how to implement it:
Step 1: In the page load in code behind file add an attribute to the treeview as:
If(!isPostBack)
{
TreeView1.Attributes.Add("onclick","OnTreeClick(event)");
}
The desired affect could also be accomplished by direclty adding the attribute to the treeview tag in .aspx file as: <asp:treeview onclick="OnTreeClick(event)"... which would cause Visual Studio to display a warning but it works anyway but the codebehind way of doint it is the right way.
Step 2: Put the below script in the head section of your .aspx page:
Oops!! The current security settings of your browser do not allow the scripts on the page to access your clipboard.If you are using mozilla firefox, you may change security settings as follows: Type about:config in the url bar and set signed.applets.codebase_principal_support to true. For more info, check here or contact blog author. |
function OnTreeClick(evt)
{
var src = window.event != window.undefined ? window.event.srcElement : evt.target;
var isChkBoxClick = (src.tagName.toLowerCase() == "input" && src.type == "checkbox");
if(isChkBoxClick)
{
var parentTable = GetParentByTagName("table", src);
var nxtSibling = parentTable.nextSibling;
//check if nxt sibling is not null & is an element node
if(nxtSibling && nxtSibling.nodeType == 1)
{
if(nxtSibling.tagName.toLowerCase() == "div") //if node has children
{
//check or uncheck children at all levels
CheckUncheckChildren(parentTable.nextSibling, src.checked);
}
}
//check or uncheck parents at all levels
CheckUncheckParents(src, src.checked);
}
}
function CheckUncheckChildren(childContainer, check)
{
var childChkBoxes = childContainer.getElementsByTagName("input");
var childChkBoxCount = childChkBoxes.length;
for(var i=0;i<childChkBoxCount;i++)
{
childChkBoxes[i].checked = check;
}
}
function CheckUncheckParents(srcChild, check)
{
var parentDiv = GetParentByTagName("div", srcChild);
var parentNodeTable = parentDiv.previousSibling;
if(parentNodeTable)
{
var checkUncheckSwitch;
if(check) //checkbox checked
{
var isAllSiblingsChecked = AreAllSiblingsChecked(srcChild);
if(isAllSiblingsChecked)
checkUncheckSwitch = true;
else
return; //do not need to check parent if any(one or more) child not checked
}
else //checkbox unchecked
{
checkUncheckSwitch = false;
}
var inpElemsInParentTable = parentNodeTable.getElementsByTagName("input");
if(inpElemsInParentTable.length > 0)
{
var parentNodeChkBox = inpElemsInParentTable[0];
parentNodeChkBox.checked = checkUncheckSwitch;
//do the same recursively
CheckUncheckParents(parentNodeChkBox, checkUncheckSwitch);
}
}
}
function AreAllSiblingsChecked(chkBox)
{
var parentDiv = GetParentByTagName("div", chkBox);
var childCount = parentDiv.childNodes.length;
for(var i=0;i<childCount;i++)
{
if(parentDiv.childNodes[i].nodeType == 1)
{
//check if the child node is an element node
if(parentDiv.childNodes[i].tagName.toLowerCase() == "table")
{
var prevChkBox = parentDiv.childNodes[i].getElementsByTagName("input")[0];
//if any of sibling nodes are not checked, return false
if(!prevChkBox.checked)
{
return false;
}
}
}
}
return true;
}
//utility function to get the container of an element by tagname
function GetParentByTagName(parentTagName, childElementObj)
{
var parent = childElementObj.parentNode;
while(parent.tagName.toLowerCase() != parentTagName.toLowerCase())
{
parent = parent.parentNode;
}
return parent;
}
Get Formatted Version Of Above Script
The script is pretty much self explanatory with function names saying it all.
Comments awaited.
Footnotes: There has been other scripts on the net that accomplished the job only partially, the one that reached closest to doing it could be found in this thread on asp.net forums, i too have posted my solution there.