Me Myself & C#

Manoj Garg’s Tech Bytes – What I learned Today

Archive for the ‘C#’ Category

Encrypting entries in ASP.NET Web.Config

Posted by Manoj Garg on December 9, 2009

One of the best practices suggested while working with ASP.NET application is keeping values you want to make plug and play (changing them without changing the implementation) in web.config file. These configurable values can be anything ranging from some string constants to connection strings. Almost all the developers(at least those I know) follow this suggestion religiously. We keep these values in a readable format in web.config. Sometimes these values can have sensitive information like if we are storing connection string to our production database and if SQL server credentials are used to login to database server, then connection string will have username and password for the production database. Keeping credentials for database server unguarded can be a huge risk. Though IIS does a good job by blocking access to any resource with .config extension by default. But certainly there are many ways (leaving FTP open :)) by which someone with not so good intensions gets access to this config file containing credentials to database server. So, if one has this kind of sensitive data in config file then that data should be stored in encrypted way to mitigate risk of credentials falling under wrong hands.

This topic popped up while having a discussion with a colleague. He mentioned that .NET has some way of encrypting the values in config files. Which prompted me to search about this feature and Yes, .NET provides a very simple but effective way to encrypt values in config files. As you might already know, configuration settings in .NET work in provider model i.e. these settings can be replaced with another values without impacting the implementation.

.NET framework provides 2 encryption providers for encrypting the config file values.

  1. DataProtectionConfigurationProvider : It uses Windows DPAPIs(Data Protection API) to encrypt the data in config file and the key used to decrypt the encrypted values in stored in windows Local Security Authority (LSA).
  2. RSAProtectedConfigurationProvider : This provider uses public key encryption approach provided by RSACryptoProvider in .NET. This public key is stored in the config file itself.

To encrypt a configuration section use ConfigurationSection.SectionInformation.ProtectSection(providername) method and to decrypt the values use ConfigurationSection. SectionInformation.UnProtectSection() method.

Once you have encrypted the configuration sections, config file will no longer show the actual values instead it will be showing some cipher text. But at the time of accessing these values in code (C# or inline in aspx page) you don’t have to do anything like decrypting the config file or something, .NET will do it for you. But just take precaution while encrypting the config file values as this auto decryption done by .NET has some performance implications as well. So one should take a wise decision about which data to encrypt and which data can be written in plain text.

There are plethora of resources on this topic on web and my this post will also add to crowd, but following few link I found very informative and to the point.

  1. Encrypting Configuration Information in ASP.NET 2.0 Applications
  2. Encrypting Connection Strings in Web.config
Advertisements

Posted in .Net 2.0, ASP.Net, C# | Tagged: , , , , | Leave a Comment »

ViewState Compression in ASP.NET 2.0

Posted by Manoj Garg on September 16, 2009

STATE as a noun can be described as “the condition of a person or thing, as with respect to circumstances or attributes“.  In ASP.NET world, State of a control or a page is what it looks like, what its value is and what its value was before the page was posted back.

Since HTTP is stateless, to maintain state across postbacks in ASP.NET, some state management techniques are used. In ASP.NET state management can be categorized in two types depending on the location where state is being kept:

  1. Client Side: Client side state management involves keeping the state data on the client end, either on client machine or the browser. There are various mechanisms to maintain state on client side like Cookies, ViewState, Hidden Fields, Control State, Query strings etc.
  2. Server Side: Server side management is keeping state on a different machine be it database or file system on a different computer. Server side state management can be done using Application State, Session state etc. this data can be  stored in the server process or in a database or server file system.

For detailed information about different option available for state management in ASP.NET, please refer this link for MSDN. This link also gives a good comparison of various state management techniques with  their pros n cons.

ViewState is the first thing that come to mind when dealing with postbacks in ASP.NET.

ViewState

In simple terms, ViewState is keeping information about page in a non-readable i.e. serialized way with the page itself. In ASP.NET, view state is kept in a hidden field name _VIEWSTATE on the page. So every time the page loads after the postback this serialized data is read and appropriate state is loaded into the controls.

To understand how viewstate is saved and loaded, one should know the page life cycle i.e. the steps a request, for loading a page, goes through before a page is fully rendered into the browser. This link on MSDN explains Page life cycle along with a good overview of what view state is. This post by Dave Reed gets under the hood of view state and explains the nuances of view state very well. I would recommend reading the above mention post to every one. That post has been the best link I have come across on view state.

As mentioned above, View state is kept in a hidden field _VIEWSTATE on the page. So every time the page is posted back to the server or retrieved from server, the content of View state also travel along with page content. In turn contributing to usage of network resources. Generally, developers have tendency to keep view state enabled for controls on their page. which unknowingly keeps growing the page size. This means as page size grows, it would take longer for the page to completely render itself.

Problem comes when the page size grows inordinately and waiting time for the end user to see the completely rendered page is too high. There are recommendation that one should use viewstate as minimally as possible to ensure the page size is with in limits. But sometime scenario enforces the developer to use viewstate in his/her page. In such cases following are some of the guideline/approaches to keep view state size in check.

  1. Enable view state for a control only when absolutely necessary: Set the EnableViewState attribute for the control to false explicitly, when you are sure that you do not require to keep state for that control.
  2. Don’t save large datasets into view state: Whenever possible keep the datasets and big data tables in cache or say session so that view state is small.
  3. Use IIS Compression: Internet Information Services(IIS) has the feature to provide compression for the pages it serves as response to the requests received. You can configure the IIS on your server to compress the appropriate websites or pages in the website. For detailed information about how to configure the IIS configuration on your server, please read this post by Scott Forsyth.  There is one another post by Shivprasad koirala, which is an extension of the post by Scott Forsyth, it also explains IIS compression in great details along with it also provides some comparison statistics data about what level of compression is good and for what type of pages one should avail this
  4. Using old ASP.NET 1.1 approach for storing the view state on server: In Page life cycle there are two steps available which do the job of fetching the view state from the hidden field and putting the view state content back into the hidden field it was stored. These methods are LoadPageStateFromPersistenceMedium and SavePageStateToPersistenceMedium. These methods are virtual methods from the Page class. A simplest approach would be to store the viewstate in session itself. Following code snippet shows how this could be done by overriding the two above mentioned methods and storing the viewstate in session after serializing and loading the viewstate from session again after desterilizing it. Serialization and deserialization is done using LosFormatter class. One can use any of the available formatters, BinaryFormatter, SOAPFormatter etc., for serializing the viewstate content. Content is stored in session with SessionID being the key.
protected override object LoadPageStateFromPersistenceMedium ()
{
    return (new LosFormatter().Deserialize ((string)Session[Session.SessionID]));
}
protected override void SavePageStateToPersistenceMedium (object state)
{
    LosFormatter los = new LosFormatter();
    los.Serialize (sw, state);
    string vs = sw.ToString ();
    Session[Session.SessionID] = vs;
}

An improvement in above mentioned approach could be to apply the compression on the viewstate content before storing them in session and decompressing the session content before restoring the viewstate. Following code does exactly this. This code introduces one more step, between storing and retrieving the view state from session, by compressing and decompressing the content. This approach again leads to save some more bandwidth.

Following class contains method for compression and decompression. Source code from http://www.dreamincode.net/code/snippet1717.htm

                                                                    

using System.IO;
using System.IO.Compression;

public static class Compressor
{
/// <summary>
/// Method for compressing the ViewState data
/// </summary>
/// <param name="data">ViewState data to compress</param>
/// <returns></returns>
public static byte[] Compress(byte[] data)
{
    //create a new MemoryStream for holding and
    //returning the compressed ViewState
    MemoryStream output = new MemoryStream();
    //create a new GZipStream object for compressing
    //the ViewState
    GZipStream gzip = new GZipStream(output,CompressionMode.Compress, true);
    //write the compressed bytes to the underlying stream
    gzip.Write(data, 0, data.Length);
    //close the object
    gzip.Close();
    //convert the MemoryStream to an array and return
    //it to the calling method
    return output.ToArray();
}

/// <summary>
/// Method for decompressing the ViewState data
/// </summary>
/// <param name="data">Compressed ViewState to decompress</param>
/// <returns></returns>
public static byte[] Decompress(byte[] data)
{
    //create a MemoryStream for holding the incoming data
    MemoryStream input = new MemoryStream();
    //write the incoming bytes to the MemoryStream
    input.Write(data, 0, data.Length);
    //set our position to the start of the Stream
    input.Position = 0;
    //create an instance of the GZipStream to decompress
    //the incoming byte array (the compressed ViewState)
    GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true);
    //create a new MemoryStream for holding
    //the output
    MemoryStream output = new MemoryStream();
    //create a byte array
    byte[] buff = new byte[64];
    int read = -1;
    //read the decompressed ViewState into
    //our byte array, set that value to our
    //read variable (int data type)
    read = gzip.Read(buff, 0, buff.Length);
    //make sure we have something to read
    while (read > 0)
    {
        //write the decompressed bytes to our
        //out going MemoryStream
        output.Write(buff, 0, read);
        //get the rest of the buffer
        read = gzip.Read(buff, 0, buff.Length);
    }
    gzip.Close();
    //return our out going MemoryStream
    //in an array
    return output.ToArray();
}
}


protected override object LoadPageStateFromPersistenceMedium()

 

 

{

 

 

string viewState = (string)Session[Session.SessionID];

 

 

byte[] bytes = Convert.FromBase64String(viewState);

 

 

bytes = Compressor.Decompress(bytes);

 

 

LosFormatter formatter = new LosFormatter();

 

 

return formatter.Deserialize(Convert.ToBase64String(bytes));

 

 

}

 

protected override void SavePageStateToPersistenceMedium(object state)

 

 

{

 

 

LosFormatter formatter = new LosFormatter();

 

 

StringWriter writer = new StringWriter();

 

 

formatter.Serialize(writer, state);

 

 

string viewStateString = writer.ToString();

 

 

byte[] bytes = Convert.FromBase64String(viewStateString);

 

 

bytes = Compressor.Compress(bytes);

 

 

Session[Session.SessionID] = Convert.ToBase64String(bytes);

}

5. ASP.NET 2.0 approach for saving viewstate on server:

In ASP.NET 2.0, ViewState is saved by a descendant of PageStatePersister class. This class is an abstract class for saving and loading ViewsState and there are two implemented descendants of this class in .Net Framework, named HiddenFieldPageStatePersister and SessionPageStatePersister. By default HiddenFieldPageStatePersister is used to save/load ViewState information, but we can easily get the SessionPageStatePersister to work and save ViewState in Session object. The only thing to do this is to override PageStatePersister property of Page class and ask it to return an instance of SessionPageStatePersister class:

protected override PageStatePersister PageStatePersister

 

{

 

get

 

 

{

 

return new SessionPageStatePersister(Page);

 

}

 

}

 

The PageStatePersister class can be inherited to also created custom storage mediums for session state. The PageStatePersister class has two methods Load() and Save() which can be used to provide custom loading and saving media for ViewState.

public class StreamPageStatePersister : PageStatePersister

 

 

{

 

 

public StreamPageStatePersister(Page page)

 

: base(page)

 

{

 

}

 

public override void Load()

 

{

 

Stream stateStream = GetSecureStream();

 

// Read the state string, using the StateFormatter.

 

 

StreamReader reader = new StreamReader(stateStream);

 

IStateFormatter formatter = this.StateFormatter;

 

string fileContents = reader.ReadToEnd();

 

// Deserilize returns the Pair object that is serialized in

 

 

// the Save method.

 

 

Pair statePair = (Pair)formatter.Deserialize(fileContents);

 

ViewState = statePair.First;

 

ControlState = statePair.Second;

 

reader.Close();

 

stateStream.Close();

 

}

 

 

 

public override void Save()

 

{

 

 

if (ViewState != null || ControlState != null)

 

{

 

if (Page.Session != null)

 

{

 

Stream stateStream = GetSecureStream();

 

 

StreamWriter writer = new StreamWriter(stateStream);

 

 

IStateFormatter formatter = this.StateFormatter;

 

Pair statePair = new Pair(ViewState, ControlState);

 

 

// Serialize the statePair object to a string.

 

 

string serializedState = formatter.Serialize(statePair);

 

 

writer.Write(serializedState);

 

writer.Close();

 

stateStream.Close();

 

}

 

else

 

 

throw new InvalidOperationException(“Session needed for StreamPageStatePersister.”);

 

}

 

}

 

}

 

Then a PageAdapter can be used to use this persister

public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter

 

{

 

public override PageStatePersister GetStatePersister() {

 

return new Samples.AspNet.CS.StreamPageStatePersister(Page);

 

}

 

}

 

 

This adapter can be configured via a .browser file placed in App_Browsers folder locally with the web site directory.

<browsers>
    <browser refid="Default" >
        <controlAdapters>
            <adapter
                controlType="System.Web.UI.Page"
                adapterType="MyPageAdapter" />
        </controlAdapters>
    </browser>
</browsers>

 

This all above content was related to removing/reducing the Viewstate getting transferred over network. But there is still one more type of state “ControlState”. In layman’s terms, Its the minimal information that a control needs to render and function itself properly after a postback. A more apt definition from MSDN is:

Control state, introduced in ASP.NET version 2.0, is similar to view state but functionally independent of view state. A page developer can disable view state for the page or for an individual control for performance. However, control state cannot be disabled. Control state is designed for storing a control’s essential data (such as a pager control’s page number) that must be available on postback to enable the control to function even when view state has been disabled. By default, the ASP.NET page framework stores control state in the page in the same hidden element in which it stores view state. Even if view state is disabled, or when state is managed using Session, control state travels to the client and back to the server in the page. On postback, ASP.NET deserializes the contents of the hidden element and loads control state into each control that is registered for control state.

As it is mentioned in the above description, that ControlState will be traveling with the page all the time. There may come a requirement where we want to have it stored somewhere else other then the page hidden fields. While searching for methods to reduce the viewstate size, i stumbled across this post by SZOKELIZER, which describes a way to store the ControlState in session as well. ASP.NET provides a switch “RequiresControlStateInSession ” which allows to store the control state in session rather then the page itself. So for the sake of completeness I am putting the code that needs to be put to enable storing the control state in session from the above mentioned post.

<system.web>
    <browserCaps>
      <case>
        RequiresControlStateInSession=true
      </case>
    </browserCaps>
  </system.web>

 

 

Conclusion

In this post I have written about different mechanisms to reduce size of viewstate that travels along with an asp/aspx page every time. I have tried to covered few of the approaches that can be used but I am sure there can be many more. One such approach suggested by a friend of mine is using HttpHandlers to cut the viewstate from the request and restore it back. I am working on a poc for this. I will post it once it is complete. Please do post a comment, if you have come across any other way to tackle this or if there is some correction in approaches I have described above.

Posted in .Net 2.0, ASP.Net, C#, ViewState | Tagged: , , , , , , , , , , | 3 Comments »

Request.ValidateInput() : A common misconception

Posted by Manoj Garg on September 7, 2009

Attackers try to exploit smallest possible hole into the security of a website. A common and widely used method is script injection attack or cross site scripting where attacker tries to put some script as input to the website and tries to damage the system. A simplest example could be passing a java script function that redirects every request to a page to some other site next time onwards or passing a SQL DML statement which deletes/updates record into the database.

ASP.Net provide some measure to mitigate this risk of script injection. One of such technique is validating each and every input entered by the user before passing it on the server automatically. In this approach IIS parses the input before it is sent to the worker process and checks it for potential dangerous characters lie <, > etc. If any of such character is found in the input request, an exception is thrown, thus saving the site from a possible attack.

The exception thrown is

“A potentially dangerous Request.Form value was detected from the client”

In ASP.NET this feature can be applied per page basis or for the entire site depending on the requirement. To enable input request validation for the entire site, set validateRequest attribute of page section in web.config to true.

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

Similarly, to override the request validation or enable/disable request validation on a page ValidateRequest attribute of Page directive can be set to true/false respectively. Setting this attribute to true instructs the IIS to check the sanity of the incoming request before passing it on.

So this approach won’t let any script to pass through. But there are situations where you need to take a script or the prohibited characters like <,> as input from user, at the same time preventing a misuse of this opportunity of script injection.

A commonly used approach in ASP.NET for this scenario is:

  1. Set ValidateRequest to false for that page.
  2. Encode the input entered by the end user using Server.HtmlEncode(): Encoding ensures that all the stop words(potentially harmful characters) are converted to an equivalent HTML character encoding e.g. “<” is converted to “&lt;” etc.

I had a similar requirement, few days back, when in our application on “contact us” page, We wanted to allow user to enter html scripts into a text box. So we disabled the ValidateRequest attribute to false and used Server.HtmlEncode() method to encode the entered input. But at the same time we didn’t wanted the user to pass something malicious through the query string or the cookies. ASP.NET also provides a method on the Request object named ValidateInput(), which validates the request input passed by the client to the server. And if something fishy is found in the request an HttpRequestValidationException exception is thrown. And this is where the confusion gets in.

As per MSDN, Request.ValidateInput() method ….

The HttpRequest class uses input validation flags to track whether to perform validation on the request collections accessed through the Cookies, Form, and QueryString properties. The ValidateInput method sets these flags so that when the get accessors for the Cookies, Form, or QueryString property are invoked, input validation is performed. Validation works by checking all input data against a hard-coded list of potentially dangerous data.

If the validation feature is enabled by page directive or configuration, this method is called during the page’s ProcessRequest processing phase. The ValidateInput method can be called by your code if the validation feature is not enabled.

As this definition says that ValidateInput method does nothing but sets some flags indicating that all access to user input must be validated before using it. But normally developer tend to call Request.ValidateInput() method and then expect it to throw the HttpRequestValidationException exception, which will not happen since this method doesn’t throw any exception, rather any access now onwards to input will throw the above mentioned exception.

Lets disassemble the Request.ValidateInput method.

public void ValidateInput()
{
    this._flags.Set(1);
    this._flags.Set(2);
    this._flags.Set(4);
    this._flags.Set(0x40);
    this._flags.Set(0x80);
}

As shown in the above code snippet, this method has just some set methods calls. Actually these method set a flag for one of the input approach that can be used by the client. Like querystring, form input , cookie etc.

So what does this setter method do?? This method is merely an indicator for the getters methods of each of the request fields to check the sanitation of the value before returning the value to the requestor and if there is some invalid input then throw the HttpRequestValidationException.

So to check for invalid input in Form values, we need to access form values collection of the request as Request.Form after the call to Request.ValidateInput(). Following is a sample code for validating Form values,

String firstName = string.Empty;
try
{
    Request.ValidateInput();
    //Access the Form value collection. So if there is any non complient input entered by user.. It will throw an exception
    System.Collections.Specialized.NameValueCollection nvc = Request.Form;

    firstName = txtName.Text.Trim();
}
catch(HttpRequestValidationException)
{
    firstName = HttpUtility.HtmlEncode(txtName.Text.Trim());
}

here line in yellow color will throw an exception if at all there is some bad data in the input. Then in catch we can use HtmlEncode() to encode the user input.

Similar approach can be used while accessing cookies or QueryString.

Posted in .Net 2.0, ASP.Net, C# | Tagged: , , , | 3 Comments »

Null-coalescing operator in C#

Posted by Manoj Garg on May 12, 2009

While surfing around I can across a term called “null-coalescing operator”. After searching about it, I came to know that C# has an operator ?? . well I didn’t new about it before so thought of writing about it.

MSDN says

The ?? operator is called the null-coalescing operator and is used to define a default value for a nullable value types as well as reference types. It returns the left-hand operand if it is not null; otherwise it returns the right operand.

Example:

int? x = null;
string str = "Hello World !!"; 

int y = x ?? -99; // Here Y will be -99 since X is null
string newStr = str ?? "Default Hello World !!"; // here newStr will be "Hello World !!"

PS: This operator reminded me of similar functions available in SQL Server like ISNULL, COALESCE

Posted in C# | Tagged: , | Leave a Comment »

Passing an object by REF inside a foreach loop

Posted by Manoj Garg on April 22, 2009

Its summer time in India and its hard to resist drowsiness in the afternoon specially when you had a heavy lunch. So this afternoon while I was trying to take a nap, no one was watching :P, a friend of mine pinged me on IM, and says “dude, can’t I pass an object as ref inside a foreach loop?”, well my first reaction was “of course you can!!! “ but then I realized that its an iterator  and I can’t modify an object I am iterating on.

I opened a new instance of Visual Studio and create a new console application. In this application created a new class named testref with just two fields, one string and another one an int. In the main method created a generic list of type testref and filled it with five testref object. Then tried to loop through it and pass the loop variable as ref in a function. He was right, C# compiler throws an error “Cannot pass ‘xxyzobj’ as a ref or out argument because it is a ‘foreach iteration variable’”. following snippet shows the initial set of code

 class Program
    {
        class testref
        {
            public string val { get; set; }
            public int a {get;set;}

            public testref(string s)
            {
                val = s;
                a = 0;
            }
        }

        static void Main(string[] args)
        {
            List<testref> testcol = new List<testref>();

            testcol.Add(new testref("One"));
            testcol.Add(new testref("two"));
            testcol.Add(new testref("three"));
            testcol.Add(new testref("four"));
            testcol.Add(new testref("five"));

            foreach (testref s in testcol)
            {            
               MethodWithRef(ref s);
            }

            Console.ReadLine();
            
        }

        static void MethodWithRef(ref testref str)
        {
            str.val = str.val + " not";
            str.a = (new Random()).Next();
        }

}

In above code snippet, line in yellow will give the compilation error. Since this is a C# complier restriction there are couple of workaround to this situation.

  • Have a temporary variable and then pass this variable as the ref parameter in the method:
testref tempObj;
foreach (testref s in testcol)
{
    tempObj = s;
    MethodWithRef(ref tempObj);
}
  • Use List.ForEach() method to apply an action on all the objects in the list:
// Inside the main method pass the function name 
// you want to apply on each object
testcol.ForEach(MethodWithoutRef);

//Method to be applied on all the objects
static void MethodWithoutRef(testref str)
{
   str.val = str.val + " not";
   str.a = (new Random()).Next();
}

So that was it.. problem was solved…

PS: If you have some more ways this can be solved, Please do share.

Manoj

Posted in C#, Collections & Generics | Tagged: | Leave a Comment »

WPF 101 : Custom Expander Control to show a popup on mouse over

Posted by Manoj Garg on March 29, 2009

This is the second post in this WPF learning series. In this post I will be writing about creating your own custom controls in WPF. I am going to write a custom expander which has similar features as of the WPF expander control plus it will have a feature of showing a Popup on mouse over event of this expander. Content of this popup will be the content of the expander itself. This is the kind of feature where a user wants to see the content of expander while hovering the mouse over the expander header, just like IE8 tab quick preview where it shows a preview of tab content without even opening the tab. So below are our set of requirements:

Requirements

  • It should be an expandable control with a header and content property.
  • It should show a popup when mouse is over the header and control is in collapsed state.
  • Should have an option for showing/hiding the popup.
  • Popup properties like position, size, transparency etc should be configurable.

Choosing the Proper base class

While writing a custom control one must choose the base control which he/she wants to extend with little care with having all the features in mind. For our requirements, we need a base class which provides me a header, a content property. In WPF we have some choices like HeaderedContentControl class and we have an Expander class which itself drives from HeaderedContentControl class. we can use any of them. I decided to use Expander class (well while coding I wasn’t sure what all I wanted to have 😉 ).

Implementation

Visual studio 2008 provides a project of type “WPF Custom Control Library” which can be used as a starting point for writing your first custom control. Following figure shows the selection of new project type.

newcustomcontrol

When adding this project type to your visual studio solution, it will add a new project with following items to your solution structure:

  1. CustomControl1.cs: This file contains your custom control class.
  2. Themes Folder with Generic.xaml: This folder will contain the styles for all your custom controls. By default a new style for the customcontrol1 is added to the generic.xaml. One needs to change this style to work with this custom control.

Lets start implementing the new expander with popup. As we have decided we will be using Expander class as the base class for our control. I will be naming this control as CustomExpander.

  1: namespace CustomControls
  2: {
  3:     /// <summary>
  4:     /// This class is an extention to Expander Control. 
  5:     /// This provides a feature for shouwing a popup with the content of the expander on MouseOver
  6:     /// </summary>
  7:     public class CustomExpander : Expander
  8:     {
  9:         #region // .ctor(s)
 10:         static CustomExpander()
 11:         {
 12:             DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomExpander), new FrameworkPropertyMetadata(typeof(CustomExpander)));
 13:         }
 14:         public CustomExpander()
 15:         {
 16:         }
 17:         #endregion
 18:     }
 19: }

The above class definition has a static ctor and a normal default ctor for the CustomExpander class. The static ctor is used to initialize the static properties of the class as well as changing the default style for the control. As highlighted in the above code snippet in line 12, DefaultStyleKeyProperty is used to change the default style for the control by passing the type of the new control.

Now we have to decide upon what all configurable properties we want to expose to the end user of this control. As mentioned in the requirement section above, we will have following dependency properties in our control:

  1. PopUpPlacementModeProperty: This property will allow user to configure the placement of popup in the screen. This is of type PlacementMode.
  2. StaysOpenProperty: This property defines whether the popup will stay open when the popup looses focus. This is of type Boolean.
  3. AllowsTransparencyProperty: This property allows user to set the transparency for the popup. This is a Boolean value.
  4. PopUpWidthProperty: Width of the popup. This is of type Double
  5. PopUpHeightProperty: Height of the popup. This is of type Double

Now lets us decide what controls we will be using to give this control a look of an Expander. For Expander functionality I will use ToggleButton control and a ContentPresenter control. since toggle button has the notion of being in two state (clicked and non clicked), so these state we can use to denote expanded and collapsed state of the expander. For popup functionality we will use wpf PopUp control.

So here is our task, on mouse hover on the togglebutton, set content of the expander as the child of  popup. and on click of the expander show the contentpresenter . 🙂  simple enough .. hmmmmmm

But here comes the issue. As we are talking about setting the content of popup same as the content of the expander but any object/ control can be child of only one parent. So we need make sure that while we show the popup or expand the expander only one of them have their content property set and the other one has this as null. To accomplish this we need one more dependency property which will store the content of the expander and we will use this property as the child for popup as well expander but only one at a time.

  1: public static readonly DependencyProperty OldContentProperty =
  2:                    DependencyProperty.Register("OldContent", typeof(object), typeof(CustomExpander));
  3:
  4: private object OldContent
  5: {
  6:      get { return GetValue(OldContentProperty); }
  7:      set { SetValue(OldContentProperty, value); }
  8: }
  9:

Now lets create the style for Expander. First lets design the header for the Expander. So we need a circle with an arrow indicating the expand/collapse direction and a content presenter showing the text of the header. Following code shows the style for the toggle button header.

  1: <!-- Style for the toggle button which wil be used as expander header -->
  2: <Style TargetType="{x:Type ToggleButton}" x:Key="toggleButtonKey">
  3:      <Setter Property="Template">
  4:           <Setter.Value>
  5:                 <ControlTemplate TargetType="{x:Type ToggleButton}">
  6:                        <StackPanel Orientation="Horizontal"
  7:                                  Margin="{TemplateBinding Padding}">
  8:                               <Grid Background="Transparent">
  9:                                    <!-- Circles for the expander header containg the expand direction arrow -->
 10:                                    <Ellipse x:Name="circle"
 11:                                             HorizontalAlignment="Center" VerticalAlignment="Center"
 12:                                             Width="20" Height="20"
 13:                                             Stroke="DarkGray"/>
 14:                                    <Ellipse x:Name="shadow" Visibility="Hidden"
 15:                                             HorizontalAlignment="Center" VerticalAlignment="Center"
 16:                                             Width="17" Height="17" />
 17:
 18:                                    <!-- Expand direction Arrow -->
 19:                                    <Path x:Name="arrow"
 20:                                             VerticalAlignment="Center" HorizontalAlignment="Center"
 21:                                             Stroke="#666" StrokeThickness="2"
 22:                                             Data="M1,1 L4,4 7,1" />
 23:                               </Grid>
 24:
 25:                               <!-- Expander Header Content -->
 26:                               <ContentPresenter ContentSource="{TemplateBinding Content}" Grid.Column="1" Margin="5"/>
 27:                        </StackPanel>
 28:
 29:                        <ControlTemplate.Triggers>
 30:                              <!-- Trigger to change the arrow direction when expanded -->
 31:                              <Trigger Property="IsChecked" Value="true">
 32:                                     <Setter TargetName="arrow"
 33:                                             Property="Data" Value="M 1,4  L 4,1  L 7,4"/>
 34:                              </Trigger>
 35:
 36:                              <!-- Trigger to give a mouse over effect on the circle containing direction arrow -->
 37:                              <Trigger Property="IsMouseOver" Value="true">
 38:                                     <Setter TargetName="circle"
 39:                                             Property="Stroke" Value="#666"/>
 40:                                     <Setter TargetName="arrow"
 41:                                             Property="Stroke" Value="#222"/>
 42:                                     <Setter TargetName="shadow"
 43:                                             Property="Visibility" Value="Visible"/>
 44:                               </Trigger>
 45:                       </ControlTemplate.Triggers>
 46:               </ControlTemplate>
 47:         </Setter.Value>
 48:    </Setter>
 49: </Style>

Now the expander content and popup.

  1: <!-- Expander -->
  2:                             <StackPanel>
  3:                                     <!-- Expander Header -->
  4:                                     <ToggleButton x:Name="expanderHeader"
  5:                                               Style="{StaticResource toggleButtonKey}"
  6:                                               Content="{TemplateBinding Header}"
  7:                                               Padding="{TemplateBinding Padding}"
  8:                                               IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded,Mode=TwoWay}"/>
  9:
 10:                                     <!-- Expander Content -->
 11:                                     <ContentPresenter x:Name="expanderContent"/>
 12:                             </StackPanel>
 13:
 14:                             <!-- PopUp control which will be showing the content of expander on mouse over -->
 15:                             <Popup x:Name="contentPopUp"
 16:                                    IsOpen="False"
 17:                                    Placement="{TemplateBinding PopUpPlacementMode}"
 18:                                    AllowsTransparency = "{TemplateBinding AllowsTransparency}"
 19:                                    StaysOpen = "{TemplateBinding StaysOpen}"
 20:                                    Width="{TemplateBinding PopUpWidth}"
 21:                                    Height="{TemplateBinding PopUpHeight}">
 22:                             </Popup>

Finally the triggers which would show the popup on mouse over and set the content.

  1: <ControlTemplate.Triggers>
  2:                         <!-- Trigger for showing the popup when Expander control is not expanded and IsMouseOver is true  -->
  3:                         <MultiTrigger>
  4:                             <MultiTrigger.Conditions>
  5:                                 <Condition SourceName="expanderHeader" Property="IsMouseOver" Value="True"></Condition>
  6:                                 <Condition SourceName="expanderHeader" Property="IsChecked" Value="False"></Condition>
  7:                             </MultiTrigger.Conditions>
  8:                             <Setter TargetName="expanderContent"
  9:                                     Property="Content" Value="{x:Null}"></Setter>
 10:                             <Setter TargetName="contentPopUp"
 11:                                     Property="Child" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=OldContent,Mode=OneWay,Converter={StaticResource localConverter}}"></Setter>
 12:                             <Setter TargetName="contentPopUp"
 13:                                     Property="BitmapEffect" Value="{StaticResource outerGlow}"></Setter>
 14:                             <Setter TargetName="contentPopUp"
 15:                                     Property="IsOpen" Value="True"></Setter>
 16:                         </MultiTrigger>
 17:
 18:                         <!-- Trigger for clearing the content of PopUp control when mouse is not over the expander control -->
 19:                         <Trigger SourceName="expanderHeader" Property="IsMouseOver" Value="False">
 20:                             <Setter TargetName="contentPopUp"
 21:                                     Property="Child" Value="{x:Null}"></Setter>
 22:                         </Trigger>
 23:
 24:                         <!-- Trigger for setting the content of expander when IsExpanded is true -->
 25:                         <Trigger SourceName="expanderHeader" Property="IsChecked" Value="True">
 26:                             <Setter TargetName="contentPopUp"
 27:                                     Property="Child" Value="{x:Null}"></Setter>
 28:                             <Setter TargetName="expanderContent"
 29:                                     Property="Content" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=OldContent,Mode=OneWay}"></Setter>
 30:                         </Trigger>
 31:                     </ControlTemplate.Triggers>

So this makes our code complete. But now as we have an option to configure the width and height of the popup. So the behavior of the popup should be something like this, It should zoom in / zoom out it self depending on the size of the content and the dimensions declared by the control user. Here comes the ViewBox wpf control. This control is made to do this. It adjusts its content according to the width/height of the viewbox. So what I will do is, I will make the content of expander as the content of a viewbox and will store this viewbox as the value of OldContent property. This will be done when the template is being applied to the control in OnApplyTemplate method. So I will override this method in our control class and store the content value.

  1: public override void OnApplyTemplate()
  2:         {
  3:             base.OnApplyTemplate();
  4:             object tmpContent = this.Content;
  5:             this.Content = null;
  6:
  7:             Viewbox containerViewBox = new Viewbox();
  8:             containerViewBox.Child = (UIElement)tmpContent;
  9:             OldContent = containerViewBox;
 10:         }

Complete source code is available here.

[PS: Please change the extension of file from .DOC to .ZIP]

Ha-P Coding 🙂

Posted in C#, WPF, XAML | Tagged: , , , | 2 Comments »

Extension Methods in .Net 3.5

Posted by Manoj Garg on October 20, 2008

Extension methods are the method which are kinda plugged to a type be it System type or any Custom type. Microsoft added this feature in .Net 3.5 version, where some static methods can be added to a type. A simple but nice discussion of Extension methods can be found @ http://dotnetslackers.com/articles/net/Dot-NET-Classes-Now-Can-Have-Extensions.aspx

 

Ha-P Extending 🙂

Posted in .Net 3.5, C# | Tagged: | Leave a Comment »

Reading Description of Enum values using Reflection in .Net 2.0

Posted by Manoj Garg on August 7, 2008

Suppose we have a situation where we want to bind an DropDown List with the values from an Enum. But we want to show different text for each enum member. for example we have following enum containing various actions a user can perform in a source control tool like check in, check out etc.

   1: public enum Actions
   2:     {
   3:         [Description("Check in")]
   4:         Checkin,
   5:         [Description("Check out")]
   6:         Checkout,
   7:         [Description("Undo Check out")]
   8:         UndoCheckOut,
   9:         [Description("View File")]
  10:         ViewFile,
  11:     }

Now on our page we want to show the text specified in Description attribute and the actual enum member name as its value. Following is an elegant way to do it in DotNet 2.0 using reflection.

   1: class ActionItems
   2: {
   3:     public string Text;
   4:     public string Value;
   5:
   6:     public ActionItems(string _text, string _value)
   7:     {
   8:         Text = _text;
   9:         Value = _value;
  10:     }
  11: }
  12:
  13: public List<ActionItems> GetActionListItems(Type EnumType)
  14: {
  15:     List<ActionItems> items = new List<ActionItems>();
  16:     foreach (string value in Enum.GetNames(EnumType))
  17:     {
  18:         /// Get field info
  19:         FieldInfo fi = EnumType.GetField(value);
  20:
  21:         /// Get description attribute
  22:         object[] descriptionAttrs = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
  23:         DescriptionAttribute description = (DescriptionAttribute)descriptionAttrs[0];
  24:
  25:         ActionItems item = new ActionItems(description.Description, value);
  26:         items.Add(item);
  27:     }
  28:     return items;
  29: }

The method above GetActionListItems returns a list of type ActionItems which contains two fields Text and Value. This method uses Enum.GetNames method to get all the members in a given enum type. GetField method of type is used to get the information about that member. This method return an object of type FieldInfo. Using this FieldInfo object we can get the values of various custom attributes defined for that enum using GetCustomAttributes method.

   1: List<ActionItems> comboItems = GetActionListItems(typeof(Actions));

The above code can be used to call GetActionListItems method.

Hope it helps.

Ha-P Coding 🙂

Posted in C# | Tagged: , , | 5 Comments »

Writing a MemoryStream to Response Object for opening a Open / Save / Cancel Dialogue in ASP.NET 2.0

Posted by Manoj Garg on July 17, 2008

Following code block can be used to show user on Open/Save/Cancel dialogue box in browser for a memory stream.

             if (ms != null)
               {
                    Byte[] byteArray = ms.ToArray();
                    ms.Flush();
                    ms.Close();
                    Response.BufferOutput = true;
                    // Clear all content output from the buffer stream
                    Response.Clear();
                    //to fix the “file not found” error when opening excel file
                    //See
http://www.aspose.com/Community/forums/ShowThread.aspx?PostID=61444
                    Response.ClearHeaders();
                    // Add a HTTP header to the output stream that specifies the default filename
                    // for the browser’s download dialog
                    string timeStamp = Convert.ToString(DateTime.Now.ToString(“MMddyyyy_HHmmss”));
                    Response.AddHeader(“Content-Disposition”,
                                       “attachment; filename=testFileName_” + timeStamp + “.fileextention”);
                    // Set the HTTP MIME type of the output stream
                    Response.ContentType = “application/octet-stream”;
                    // Write the data
                    Response.BinaryWrite(byteArray);
                    Response.End();
                }

Ha-P Coding lightbulb

Posted in ASP.Net, C# | Tagged: , , | 8 Comments »

XML documentation parse error: Whitespace is not allowed at this location. XML comment will be ignored.

Posted by Manoj Garg on July 4, 2008

Today while writing comment in a code file I got following error

XML documentation parse error: Whitespace is not allowed at this location. XML comment will be ignored.

After some searching on Google found the following link describing the reason behind the error..thumbs_up

Actually the problem was xml comments don’t allow special characters like &, >, < etc in them.. so either don’t use them or Use & < etc.

Ha-P Coding .. smile_regular

Posted in ASP.Net, C# | Tagged: | 6 Comments »