Jun 12 2010

cancel all event handlers on postback

Published by Raja Nadar under asp.net, c#

recently i had an interesting problem in my project.. which is an asp.net 3.5 web application. it consists of a monster page, which nests close to million user controls within it. these user controls post back at will, and sometimes whimsically too… the page itself had a RAD Navigation control, the wizard king.

now the one common object these user controls and the page itself, was working was my Entity object from Entity Framework. Now the page is basically a wizard, which keeps filling this object, and there are options to save this object explicitly, or create templated items out of it.

This same object (Business Entity) could also be worked by multiple users across different browser sessions/work stations. sort of a disconnected data set. Any persistent action done on this object updates the ‘Last Modified’ date time of this object. (locally and in the database)

My requirement was that, during every page load, i needed to check if this local object was the latest copy, and if stale, redirect the user to a “no donuts for you” page…

Now, in the normal scenario, i would write a simple method in the page load of my monster page, which checks if the object is latest, and if not, just do a

Response.Redirect(donutUrl, true);

But Murphy being who he is, never gives normal scenarios to developers. I had to pop up a Modal window to the user to inform that, “you are working on a stale entity and need to refresh your view.” And on the click of a confirmation, redirect the user.

So i used an AJAX Modal popup, and popped up the message. On the OK click, the user was redirected as i had wished for.

Now as much as it looks hunky-dory, a weird thing was happening… if the user clicked on the “Save My Object So Far” button, the page load did its task, of popping up the popup properly (tongue twisty?) but the event handler for the “Save” button continued to happen behind, and it saved the entity… that is not what i wish for on a Monday morning, and then the next morning, and then the next…

now i had to prevent any further operation after the popup… so i began to put the stuff between by ears into effect… as lame as they were, i thought of the following ideas: (if they are that)

  • have a boolean flag, and chain it across the event handlers, so that if the entity was modified, do not proceed with the event handling code. (lame…. if there are too many event handlers.. and there were)
  • end the page response, after the popup.. so that no further code gets executed after the page load method. but next to grabbing a candy from my 2 year old cousin quietly, i have not been able to do this.. either a blank page is rendered, or everything happens as unexpected… there are no half-measures with the asp.net page life cycle.. (i cannot use document.Write())
  • how about if i manage to suppress all the event handlers on the page, once i detect that the entity is stale.

the 3rd idea seemed to make sense, and i proceeded with a dummy page.. which rendered a label on page load. and then, a button click modified this label. then in the page load, i tried to do a

protected void Page_Load(object sender, EventArgs e)
{
    this.LabelMessage.Text = "Page Load";
    this.ButtonAction.Click -= this.ButtonAction_Click;
}
 
protected void ButtonAction_Click(object sender, EventArgs e)
{
    this.LabelMessage.Text = "Clicked Me, overwrote Page Load";
}

and holy guacamole… it worked.. the event handler was not executed…

now another problem i noticed, is that i don’t know which control posted back.. also, which event of the control caused the postback.. so i had to solve 2 problems..

  • identify the control that posted back
  • remove all event handlers for that control..

and the doors of a solution seem to open up… finding the postback control was a standard snippet i use, and reflection rocks, when i have to dig out the protected “Events” property of any Control. i also realized that, the event handler delegates are stored in a linked list format for every event… which also need to be retrieved using reflection..

so i wrote a utility method, which, if given a page, finds the control that posted back, and removes all the event handlers of the control.

this way, you have a central generic method, which can suppress any further event handling in your code.

now that i have typed close to two pages of a newspaper, time to post the snippet, which you’ll scroll through, in the first place, in any case.. so here goes nothing…

// Cancels all the event handling code for the control that posted back.
public static void CancelPostbackEvent(Page page)
{
    if (page.IsPostBack)
    {
        var postBackControl = Utility.GetPostBackControl(page);
 
        if (postBackControl != null)
        {
            var controlType = typeof(Control);
 
            var postBackControlEventHandlerList = controlType.InvokeMember("Events", System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
            null, postBackControl, null) as EventHandlerList;
 
            if (postBackControlEventHandlerList != null)
            {
                var eventHandlerListType = typeof(EventHandlerList);
                object headEventHandlerListEntry = eventHandlerListType.InvokeMember("head", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
                null, postBackControlEventHandlerList, null);
 
                if (headEventHandlerListEntry != null)
                {
                    var delegatesDictionary = new Dictionary<object, Delegate[]>();
                    Utility.GetEventHandlersRecursively(delegatesDictionary, headEventHandlerListEntry);
 
                    foreach (var delegateContainer in delegatesDictionary)
                    {
                        for (var index = delegateContainer.Value.Length - 1; index &gt;= 0; --index)
                        {
                            postBackControlEventHandlerList.RemoveHandler(delegateContainer.Key, delegateContainer.Value[index]);
                        }
                    }
                }
            }
        }
    }
}
 
private static Control GetPostBackControl(Page page)
{
    Control postBackControl = null;
 
    var postBackControlName = page.Request.Params.Get("__EVENTTARGET");
 
    if (!String.IsNullOrEmpty(postBackControlName))
    {
        postBackControl = page.FindControl(postBackControlName);
    }
    else
    {
        foreach (string controlName in page.Request.Form)
        {
            var control = page.FindControl(controlName);
 
            if (control is System.Web.UI.WebControls.Button)
            {
                postBackControl = control;
                break;
            }
        }
    }
 
    return postBackControl;
}
 
private static void GetEventHandlersRecursively(Dictionary<object, Delegate[]> delegatesDictionary, object currentEventHandlerListEntry)
{
    if (currentEventHandlerListEntry != null)
    {
        var eventHandlerListEntryType = currentEventHandlerListEntry.GetType();
 
        var eventHandler = (Delegate)eventHandlerListEntryType.InvokeMember("handler", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,
        null, currentEventHandlerListEntry, null);
 
        object key = eventHandlerListEntryType.InvokeMember("key", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,
        null, currentEventHandlerListEntry, null);
 
        var nextEventHandlerListEntry = eventHandlerListEntryType.InvokeMember("next", System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,
        null, currentEventHandlerListEntry, null);
 
        if (eventHandler != null)
        {
            var eventDelegates = eventHandler.GetInvocationList();
 
            if (eventDelegates != null &amp;&amp; eventDelegates.Length &gt; 0)
            {
                delegatesDictionary.Add(key, eventDelegates);
            }
        }
 
        if (nextEventHandlerListEntry != null)
        {
            Utility.GetEventHandlersRecursively(delegatesDictionary, nextEventHandlerListEntry);
        }
    }
}

do let me know, if you have a better solution, or if the above code upsets your chihuahua…

my lack of conscience really pricks me, when i write new code..

2 responses so far

Feb 07 2009

C#.NET and MySql

Published by Raja Nadar under .net, c#, mysql

with the use of LINQ and Entity Framework, I haven’t been writing much ADO.NET code to for the Data Access layer. Until recently, when one of my projects in the solution is still .NET 2.0 based, with the standard ADO.NET Data Access. its been some time, since I saw the SqlConnection and SqlCommand classses.

 

offline, I was working with a pastime application of mine, demonstrating Data Source independence. It is a provider architecture, where the specific data source is easily pluggable.

 

The base interface (IDataProvider) is used by the application. I already had the SqlDataProvider defined for SQL Databases. I tried switiching the provider to a MySql data source. At the end of it, just wanted to publish a couple of snippets to do data access tasks using C# and MySql.

 

  • You can use the ADO.NET Driver provided by MySql. Download the latest MySql Connector for .NET from: http://dev.mysql.com/downloads/connector/net. This is a free developer version of the component.
  • You can download the appropriate connector based on the .NET version.
  • You can also use the Odbc Driver, but my snippet is for the MySql connector.
  • Add a reference to the MySqlData.DLL to your project. Do not forget to ship this DLL.

 

Add the following namespace:

using System.Data;
using MySql.Data.MySqlClient;

 

C# and MySql Data Access without a Transaction.

using (MySqlConnection connection = new MySqlConnection(mySqlConnectionString))
{
    using (MySqlCommand command = new MySqlCommand())
    {
        command.Connection = connection;
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "SELNewRecord";
 
        command.Parameters.AddWithValue("Param1", value1);
 
        connection.Open();
 
        using (MySqlDataReader reader = command.ExecuteReader())
        {
            // read the contents.
        }
    }
}

 

C# and MySql Data Access with a Transaction.

using (MySqlConnection connection = new MySqlConnection(mySqlConnectionString))
{
    using (MySqlCommand command = new MySqlCommand())
    {
        command.Connection = connection;
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "INSNewRecord";
 
        connection.Open();
 
        using (command.Transaction = connection.BeginTransaction())
        {
            command.ExecuteNonQuery();
            // Execute additional SQL Queries.
 
            command.Transaction.Commit();
        }
    }
}

 

after all the latest ORM technologies and ease of code writing, it feels nice to write a good old data access snippet. though only once every 12 months… 

2 responses so far

Dec 16 2008

rss and atom api in .NET 3.5

Published by Raja Nadar under .net 3.5, syndication

i love the features which creep into an API. and the .NET framework classes grow richer and richer. my latest random activity has been to develop User controls (blog rolls, rss widgets) in .NET 3.5.

to think of it, one can easily write an RSS reader control, with inline commenting feature for blog posts, searching by category, authors etc. all that, by just using the Syndication API in .NET 3.5.

 

here are the classes that i am talking about:

  • SyndicationFeed: this is the top-level class representing the RSS or ATOM feed
  • SyndicationItem: this represents a blog post
  • SyndicationCategory: a category defined in a blog, applied to posts
  • SyndicationLink: a link associated with a blog post. (self, edit, comments etc)
  • SyndicationPerson: author of the blog post (name, email, profile Url etc)

 

without further ado, here is a quick snippet to get you started on the RSS/Atom APIs..

firstly, a reference needs to be added:

System.ServiceModel.Web

the namespaces required are:

using System.ServiceModel.Syndication;
using System.Xml;

Code Snippet:

string atomOrRssUrl = "http://rajanadar.blogspot.com/atom.xml";
 
SyndicationFeed rssOrAtomFeed = null;
 
using (XmlReader feedXmlReader = XmlReader.Create(atomOrRssUrl))
{
    // Top-level feed in (Atom 1.0) or Rss 2.0
    rssOrAtomFeed = SyndicationFeed.Load(feedXmlReader);
 
    // Read the blog posts in this blog.
    foreach (SyndicationItem blogItem in rssOrAtomFeed.Items)
    {
        // Important Blog Post attributes.
        blogItem.Id;
        blogItem.Title.Text;
        blogItem.PublishDate;
        blogItem.LastUpdatedTime;
        blogItem.Copyright;
 
        // Contents
        if (blogItem.Content is TextSyndicationContent)
        {
            // typically, this will be HTML.
            (blogItem.Content as TextSyndicationContent).Text;
        }
 
        // Categories of this blog post.
        foreach (SyndicationCategory category in blogItem.Categories)
        {
            category.Name;
            category.Scheme;
            category.Label;
        }
 
        // Get the Links associated with this blog post.
        // e.g. Comments (replies), self, alternate, edit links etc
        foreach (SyndicationLink link in blogItem.Links)
        {
            link.Title;
            link.Uri;
            link.RelationshipType;
        }
 
        // Get the Authors associated with the blog post.
        foreach (SyndicationPerson author in blogItem.Authors)
        {
            author.Name;  // Raja Nadar
            author.Email; // noreply@blogger.com
            author.Uri;   // Profile Url for blogger
        }
    }
}

obviously, the code won’t compile :), not because i wrote it, but that i have just highlighted the relevant fields I used. not assigned or used them anywhere..

 

so explore the Syndication APIs and code happily ever after.

2 responses so far

Jul 24 2008

WCF, certificates, event logs and silly security exceptions

Published by Raja Nadar under security, wcf

my friend was working on certificate based WCF transport messages. she prototyped a demo, and was testing it out. she kept on hitting the following exception:

Found multiple X.509 certificates using the following search criteria: StoreName ‘My’, StoreLocation ‘LocalMachine’, FindType ‘FindBySubjectName’, FindValue ”. Provide a more specific find value.

the error message could not have been more concise.. I had a look at the code, and there was nothing programmatic to verify. it was all WCF configuration driven [that I like so much J].

the configuration for binding was as follows:

<bindings>

  <wsHttpBinding>

    <binding name=wsHttpEndpointBinding>

      <security mode=Message>

        <message clientCredentialType=Certificate />

      </security>

    </binding>

  </wsHttpBinding>

</bindings>

the configuration for service credentials was as follows:

<serviceCredentials>

  <clientCertificate>

    <certificate storeLocation=LocalMachine storeName=My

                 x509FindType=FindBySubjectName />

    <authentication revocationMode=Online trustedStoreLocation=CurrentUser />

  </clientCertificate>

  <serviceCertificate findValue=rajanadar.com storeName=My

                      storeLocation=LocalMachine

    x509FindType=FindBySubjectName />

</serviceCredentials>

I thought, the search ‘rajanadar.com’ may be returning more than one certificate from the store. (may be due to root certificates etc.., I don’t know)

I checked my certificate store, and gave a specific (unique) Subject Name and tried different things.

no luck, still the same issue.

after a little observation, I read the error message a little more carefully.. (why didn’t I do this the first time?)

Found multiple X.509 certificates using the following search criteria: StoreName ‘My’, StoreLocation ‘LocalMachine’, FindType ‘FindBySubjectName’, FindValue ”. Provide a more specific find value.

it complained of a blank ‘FindValue’

then it struck me that we missed the FindValue for the client certificate, not the service certificate.

The corrected configuration was:

<serviceCredentials>

  <clientCertificate>

    <certificate storeLocation=LocalMachine storeName=My

        x509FindType=FindBySubjectName findValue=uniqueclient.rajanadar.com />

    <authentication revocationMode=Online trustedStoreLocation=CurrentUser />

  </clientCertificate>

  <serviceCertificate findValue=server.rajanadar.com storeName=My

             storeLocation=LocalMachine x509FindType=FindBySubjectName />

</serviceCredentials>

that solved the issue. it was a simple silly mistake. (obviously only after it was caught)

 

the next error I encountered, sounded something like:

Unhandled Exception: System.Net.WebException: The underlying connection was closed: Could not establish secure channel for SSL/TLS.

 

Fortunately, my past sleight of hand on WSE and SSL certificates, quickly reminded me that, when dealing with Web Applications, I need to give sufficient access permissions to the aspnet user account, to the PFX files of the certificates.

I modified the access permissions of the PFX file in question, (yeah the \AppData\Microsoft\Crypto\RSA\MachineKeys path) and the application seemed to work without any more issues. silly things, nonetheless there’s a first time..

 

p.s. the aspnet user account permission issue reminds me of one more classic issue that I encountered most of the times..

[SecurityException: Requested registry access is not allowed.] 

Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)

System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly)

System.Diagnostics.EventLog.SourceExists(String source, String machineName) +79

System.Diagnostics.EventLog.SourceExists(String source)

 

this is again because, creating a new event log or event source, needs registry write permissions, typically not possessed by the aspnet account.

 

Solution: initially, I used to grant write permissions to the registry keys

(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\NewLog or HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\Source)
 

But then, this is not a good security approach. during the lifetime of the application, it just needs to write to the event logs and never create new ones. Hence I created the new registry keys (effectively new event logs/sources) using my Installers, and granted read permissions to the web application accounts. this sounded good.

 

there’s a solution to every problem; given enough time and sometimes, well, just time…

3 responses so far

Jun 30 2008

Linq compiled queries (2 of 2)

Published by Raja Nadar under c# 3.0, linq

so in my last post, I wrote about the Linq compiled queries syntax, before diving into its use. this post is about the usage of compiled queries.

every time, a Linq Query is executed (accessed), the expressions tree/Linq query is translated into its equivalent SQL/data source query and the results are fetched. for static data and data, changing on parameter values, the repeated translation is redundant.

Assume we have the following methods:

GetAllProductsAuthorizedToBeSoldInIndia()
{
 // Linq query to join Products and Country table on key for 
 // India and return the expected products.
}

now if we access this method N times, the LINQ query will have N SQL translations, for the same result that it will fetch. clearly this is a performance bottleneck.

also consider a parameterized method:

GetAllProductsAuthorizedToBeSoldInACountry(int countryId)
{
 // Linq query to join Products and Country table on 
 // CountryId and return the expected products.
}

Except for the parameter value, the generated SQL query has to be re-generated every time.

To solve this, we use Linq Compiled Queries. They facilitate one time translation of the Linq query, and re-use of the translated query across multiple calls.

public class MyCompiledQueries
{
  private static 
  Func<MyDatabaseContext, IQueryable<Product>> 
  ProductsAuthorizedToBeSoldInACountry 
  = CompiledQuery.Compile(
  (MyDatabaseContext db, int countryId) => 
  db.Products(p=>p.CountryId=countryId)); 
 
  public static List<Product>  
  GetAllProductsAuthorizedToBeSoldInACountry
  (MyDatabaseContext db, int countryId)
  {
    return MyCompiledQueries. ProductsAuthorizedToBeSoldInACountry(
    db, countryId).ToList<Product>();
  }
}

the queries are translated once, and the parameter values are substituted at runtime.

  1. The CompileQuery.Compile method returns us a delegate, which can be invoked repeatedly.
  2. The appropriate parameters need to be passed to the delegate during the invocation. (data context + query parameters)
  3. Because we need to reuse the delegate to actually have any performance benefit, static variables/method wrappers are preferred.
  4. It is a good practice to put all of your Compiled Queries into a separate class, at one place, and possibly have wrapper methods which make more business sense than entity names.
  5. on my box, performance increased by 220%, when I changed my queries to Compiled Queries. I was working on a test domain data application using Linq. this was just slightly less than the data reader performance, we get.

the syntax for compiled queries makes it a little tough to maintain, but the benefits are sweet n totally worth the effort.

6 responses so far

Jun 19 2008

Linq compiled queries (1 of 2)

Published by Raja Nadar under c# 3.0, linq

I wanted to blog about Compiled queries in LINQ in this post. However, before doing that, I realized it would be good if I wrote something about the foundation on which the Compiled Query syntax is built.

This is because the call to a Compiled Linq Query involves calling the Compile() method:

public static Func<TArg0, TArg1, TResult> 
 
CompiledQuery.Compile<TArg0, TArg1,  TResult>
 
(Expression<Func<TArg0, TArg1, TResult>> query)
 
 where TArg0 : DataContext;

Now if the above syntax makes total sense to you, then you are probably over the following words. Else, you could read on to make sense of the above syntax.

Assume we have a delegate type defined as follows:

delegate int MyDelegateType(int a, int b)

this delegate can contain (thinking of code container) all methods which return ‘int’ and take 2 integer parameters.
E.g.

public int AddMethod(int a, int b)
 
MyDelegateType myDelegateObject = new MyDelegateType(AddMethod);

As you know, C# 2.0, simplifies this synax. we can now do:

MyDelegateType myDelegateObject = AddMethod;

looks good so far..

Now suppose, we make the delegate deal with generic types.

delegate T MyGenericDelegateType<T> (T a, T b)

this delegate can contain all methods which return ‘T’ type and take 2 T type parameters.

MyGenericDelegateType<int> myGenericDelegateObject = AddMethod;

Now, this is the AddMethod

public int AddMethod(int a, int b)
{
  return a + b;
}

As you know using C# 2.0 anonymous methods, we could write:

MyGenericDelegateType<int> myGenericDelegateObject =
delegate (int a, int b) { return a + b };

C# 3.0, further simplifies this anonymous method syntax, by eliminating even the delegate keyword, and getting the => operator. (Lambda Expressions coming in..)

Hence in C# 3.0, we can write:

MyGenericDelegateType<int> myGenericDelegateObject =
(int a, int b) => return a + b;

A further simplification to the above syntax is removing the types declared. This is because C# 3.0 is equipped with the type inference feature.

MyGenericDelegateType<int> myGenericDelegateObject = (a,b) => a + b;

Notice how we removed even the return keyword. This is perfectly valid, if the method contains only a single return statement.

Now the System.Linq namespace already defines some generic delegates for us. e.g. One of them is:

public delegate TResult Func<A0, A1, TResult> (A0 arg0, A1 arg1);

What this means is we don’t need to define our own delegate types, every time we want to use one with a similar signature.

we could directly say:

Func<int, int, int> myLinqDelegateObject = AddMethod;

Here TResult, A0 and A1 are int types. Replacing by lambda expressions,

Func<int, int, int> myLinqDelegateObject = (a,b) => a+b;

We can use this delegate object as

int sum = myLinqDelegateObject(3, 4);  // sum = 7;

Here myLinqDelegateObject is nothing but a delegate object (instance), of a delegate type already defined by the System.Linq namespace.

An Expression Tree is nothing but an object of type

System.Linq.Expressions.Expression<TDelegateType>

, where TDelegateType is the delegate the tree represents.

e.g.

Expression<Func<int, int, int>> myExpressionTreeObject = (a,b) => a+b;

Expression trees are nothing but an in memory representation of code. sort of a mini code segment, which can be evaluated later on demand, and can be built upon.

Based on all the points above, if we see the syntax now:

public static Func<TArg0, TArg1, TResult> 
 
CompiledQuery.Compile<TArg0, TArg1,  TResult>
 
(Expression<Func<TArg0, TArg1, TResult>> query)
 
 where TArg0 : DataContext;

It should look clear that, the Compile method takes in an Expression Tree object (query), of which the first parameter should be of type DataContext (Generic Contraint), and the return type is a Delegate object. Func

So the use of the Compile method would be as follows:

var queryDelegate =  CompiledQuery.Compile(
 
  (MyDataContext db, string param1, string param2) =>
 
  db.MyEntity
     .Where(v => v.Column1.Trim().ToLower() == param1.Trim().ToLower())
     .Where(v => v.Column2.Trim().ToLower() == param2.Trim().ToLower()));

Here queryDelegate is of type:

Func<MyDataContext, string, string, IQueryable<MyEntity>>

and can be used as follows:

var MyEnitities = queryDelegate(db, param1value, param2value);

As you can see, concise delegate syntax ( => ), generics (T), anonymous methods/types (var), type inference (var), lambda expressions (=>) etc, work under the hood for the Compile method. C# 3.0 is cool.

As for the exact use of Linq compiled queries, their advantages and disadvantages, I’ll be writing about it in part 2 of this post..

5 responses so far

Jun 10 2008

software life cycle stages

Published by Raja Nadar under software engineering

 When I started with the terms, I was a bit confused on the order/meaning of the following in the software release life cycle: alpha, beta, gamma, CTP, RTM, RTW, RC, GA, Gold, Box Copy etc…

I decided to get clear on these terms with the help of my friend, Wiki. So completely based on it, here is the quick summary of the release cycle stages, their order and meaning..

  1. Pre-Alpha: Not feature complete, refers to all activities prior to Software Testing. e.g. Milestone versions, Nightly builds etc
  2. Alpha: Build delivered to the internal Software Testers for testing.
  3. Beta: (also known as Preview, Prototype, Technical Preview or Community Technical Preview Release stage): Build which has passed alpha testing and has been released to external customers/prospective customers (acting as free beta testers) for external feedback/improvements.
  4. Release Candidate (RC): (also known as Golden Master, Gamma, Delta, Omega, Zenith etc): A code complete version with potential to be a final product, with no fatal bugs/showstoppers.
  5. Gold (also known as General Availability Release GA): Production or Live version of a particular product. ready for distribution.
  6. Release To Manufacturing (RTM): Used when the Gold version is sent to a product manufacturer for physical distribution (CDs, DVDs etc) Box Copy is the term used for this physically created version of the product.
  7. Release To Web (RTW): If the RTM distribution is online, RTM is called as RTW.

Always good to know the terms once, and be clear forever.

Source: http://en.wikipedia.org/wiki/Software_release_life_cycle

3 responses so far

Jun 06 2008

VSTS Testing Private Members and Methods using Accessors

Published by Raja Nadar under unit testing

as explained in my previous post, we can easily test the public methods of a class. At the end of that blog, I mentioned about private accessors. this post explains that cool feature.

assume we have a class as follows:

 

public class BusinessObject
{
    private const int MagicFactor = 18;
 
    private int CalculateConfidentialValue(int baseAmount)
    {
        return baseAmount * BusinessObject.MagicFactor;
    }
}

obviously, the method and magic factor are not super-confidential or anything. but let us pretend, they are.

here both the constant and the method are private. needless to say, the following Test Method won’t compile.

 

[TestMethod()]
public void WontCompileCalculateConfidentialValueTestMethod()
{
    BusinessObject myObject = new BusinessObject();
 
    int magicFactor = BusinessObject.MagicFactor;
 
    Assert.AreEqual(18, magicFactor);
    Assert.AreEqual(magicFactor * 2, myObject.CalculateConfidentialValue(2));
}

this is where private accessors help us. Private Accessors help us to access the Private members and Methods of an object, so that we can unit test them.

  1. go to the BusinessObjects class file
  2. Right Click >> Create Private Accessor >> Test project..

something similar is created behind the scenes:

 

[Shadowing("PrivateAccessorDemo.BusinessObject")]
public class BusinessObject_Accessor : BaseShadow
{
    protected static PrivateType m_privateType;
 
    [Shadowing(".ctor@0")]
    public BusinessObject_Accessor();
    public BusinessObject_Accessor(PrivateObject __p1);
 
    [Shadowing("MagicFactor")]
    public static int MagicFactor { get; }
    public static PrivateType ShadowedType { get; }
 
    public static BusinessObject_Accessor AttachShadow(object __p1);
    [Shadowing("CalculateConfidentialValue@1")]
    public int CalculateConfidentialValue(int baseAmount);
}

you don’t need to try and understand that. all you need is how to use the created code, and here it is:

 

[TestMethod()]
public void CalculateConfidentialValueTestMethod()
{
    BusinessObject_Accessor target = new BusinessObject_Accessor();
 
    int magicFactor = BusinessObject_Accessor.MagicFactor;
 
    Assert.AreEqual(18, magicFactor);
    Assert.AreEqual(magicFactor * 2, target.CalculateConfidentialValue(2));
}

As we can see, we could now test the Private Member and the Private Method using the accessor.

Another good thing about the private accessors now, is the way we can test for exceptions thrown by the method.

Assume we modify our source method to:

 

public class BusinessObject
{
    private const int MagicFactor = 18;
 
    private int CalculateConfidentialValue(int baseAmount)
    {
        if (baseAmount == 0)
        {
            throw new ArgumentException("argument cannot be zero.", "baseAmount");
        }
 
        return baseAmount * BusinessObject.MagicFactor;
    }
}

To test, if an argument exception is indeed thrown, we could write an unit test case as follows:

 

[TestMethod()]
[ExpectedException(typeof(System.ArgumentException))]
public void CalculateConfidentialValueWithZeroParameterTestMethod()
{
    BusinessObject_Accessor target = new BusinessObject_Accessor();
    target.CalculateConfidentialValue(0);
}
  1. I believe this is possible, because of the Shadowing attribute which is now used for private accessors changing the way exceptions are returned by the target object.
  2. Before the Shadow based reflection, the accessor always threw a System.Reflection.TargetInvocationException and the inner exception needed to be evaluated.
  3. The concise attribute based exception check for ArgumentException could not be checked.

 

Private Accessors are very useful, when you are testing the Business Layer or OM.

there’s a solution to every problem; given enough time and money..

2 responses so far

Jun 03 2008

plead the friendly dev 5th

Published by Raja Nadar under fun

No dev shall be held to answer for a bug, or otherwise infamous defect, unless on a triage or request of a VP, except in cases arising in the penultimate or ultimate releases, or in a Red Alert, when in actual service in time of Bug War or Job Security; nor shall any dev be subject for the same code defect to be twice put in jeopardy of mind or fingers; nor shall be compelled in any bug fix to be a code defect against himself, nor be deprived of snacks, games, or soda, without due process of triage; nor shall private work items be taken for public bug fixing, without just compensation.

– intended for reading/laughing/forgetting purposes only

3 responses so far

May 24 2008

VS unit testing suite

Published by Raja Nadar under unit testing

as you know, VS introduced its own unit testing framework, inbuilt for TDD. there are some very good things I like about it.

  1. it removes the dependency from any external unit testing libraries like NUnit. (though NUnit was worth all its bits)
  2. it is part of the build process and we can use the VSTS test runner (MSTest.exe), if the test cases need to be run separately, rather than from the IDE.
  3. Code coverage can be done using the test config file.
  4. it also provides support for deploying the required support files for the test cases to run successfully. (xml files, config files etc) explained later.
  5. the code can be debugged using the test cases.
  6. regression testing is very reliable, when features change in your application.
  7. The test cases can be organized using the ‘Test Manager’

 Let us take a small and simple example. I have a sample ‘Add’ method which I want to test:

 

public int Add(int a, int b)
{
    return a + b;
}

To create a Unit test for this method/project, you could just right click inside the file containing this method >> Create Unit Tests and you can have the whole test project template within seconds.

The Unit Test is as follows:

 

[TestMethod()]
public void AddTest()
{
    Calculator target = new Calculator();
 
    int a = 8;
 
    int b = 16;
 
    int expected = 24;
    int actual;
 
    actual = target.Add(a, b);
 
    Assert.AreEqual(expected, actual);
}

 

  • The Test class is attributed with the [TestClass()]attribute.
  • The Test method is attributed with the [TestMethod()]attribute.
  • There are also some other interesting attributes at the Test Method level:
  • ExpectedException(typeof(Exception))] >> This attribute makes the unit case, expect the type of exception provided, and does not fail the test case when that exception occurs. This is usefule if there are -ve test cases. (E.g FileNotFoundException, Business Exceptions etc)
  • [Description("Test Case Id: 2.34 Add two valid numbers.")] >> This attribute makes it easier to name a test case according to your test case list. Whenever the test case fails, you can see the Description and identify the exact test case which failed.
  • [WorkItem(9999)] >> This attribute is helpful in associating the test case with a work item in your scrum/tfs/project management tool.
  • [Ignore()] >> If there are some test cases, which need not be executed at this point of time, this attribute can be used.

 TestSolution.vsmdi

  • This file is basically what the test manager controls. It is used to group all the test cases in the solution.
  • As you notice, this file is a solution level item and hence common to all the project unit cases in your application.
  • You can create ‘New Test Lists’ and arrange your test cases as per Projects/Business Objects/Layers etc.
  • Once arranged, the specific test cases can be executed.

localtestrun.testrunconfig

  • This is the common configuration file for all the test cases in your application.
  • It controls the naming scheme for the output folder it creates, where the test run results are stored.
  • Code Coverage can be enabled for the assemblies.
  • The Deployment option provides the support files, which you may want to deploy for the test cases to run successfully.
  • It also provides a ‘Startup’ and ‘Cleanup’ script option to be run, before and after the test case run.

there are other cool features of the Unit Testing framework like, reading test data from data sources, private accessors, web tests, load testing, linking it to external test controllers and agents etc..

 there’s a solution to every problem; given enough time and money..

 

One response so far

Next »