Swami goes Techie

Here i would share my insights on technologies.

Wednesday, October 21, 2009

Expression Trees in .Net 3.5 Framework (Basics)

 

Expression Trees  - What's this ?

Will begin the post by trying to explain whats Expression Tree is all about and at the end of the post will try to explain why we need this.

In general, Expression Trees are basic tree structure which helps to represent any algebraic expression(Binary expressions – x < y). Usually with single root node with clusters of sub-nodes and ending with leaf nodes.

.Net 3.5 framework introduced this Expression Trees (Visual Studio 2008), helps translating executable code {or} Represent language-level( c# )code in the form of data, and visualize in a tree-like format.

Expression Trees – A Data Structure

Yes, in simple words Expression Trees are Data structure, which helps to store executable code blocks. An executable code could be any code  block containing expressions of type delegate.

for ex.)   Func<int, int, int> function = (a,b) => a + b;

here (a,b) => a + b is the executable code (an lambda expression) which is of a delegate type Func.

Creating an Expression Tree

Expression is an abstract  class present in System.Linq.Expressions namespace.

a simple expression object initialization will look as below,

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

in the above code, we have created an expression instance of delegate type and refers to an executable code block( in this case a lambda expression “ (a,b) => a + b” )

Viewing an Expression Tree

Once we have created an expression instance as above, it can be visualized using a ExpressionTreeVisualizer( a free add-on available in MSDN –Linq samples). After the installation of this add on, in the debug mode while we perform a mouse hover on the expression instance variable we get an magnifier icon similar to the one shown below,

clip_image002[6]

on clicking the image, we can view the complete executable code that we mapped in the form of a tree.

clip_image004[6]

Body: Retrieve the body of the expression.

Parameters: Retrieve the parameters of the lambda expression.

NodeType: Gets the Expression Type for some node in the tree. Like (<), (>), those that add values together (+), Lambda etc.

Type: Gets the static type of the expression. In this case, the expression is of type Func<int, int, int>.

What’s the need for Expression Trees ?

Yes, i am able to sense the restless in each one of you, as to why we need such a data structure and what i am trying to demonstrate in this post. I hope the following advantages i am listing will do some justice to the need for Expression trees.

Advantages

1.  Expression Tree –DOM:-  it has its own DOM, with which we can traverse any of the tree node and retrieve data that we require.

BinaryExpression body = (BinaryExpression)expression.Body;

ParameterExpression left = (ParameterExpression)body.Left;

2.  Expression Tree – Compilation:- converting data back into code, (i.e) once we have mapped the executable code block to an Expression instance,  then we can just make use of the Compile method of the Expression class to execute the code block. below code we are compiling the same expression that we created above initially in the post.

int result = expression.Compile()(3, 5);

Console.WriteLine(result);

3.  Expression Trees in LINQ:- Language Integrated Query, with the introduction of LINQ, the need for Expression Trees data structure became inevitable. To understand this, we should get back to the basics of LINQ to SQL.

Consider the following LINQ query,

var query = from c in db.Customers

                    where c.City == "Nantes" select new { c.City, c.CompanyName };

though the query is written in c# editor, the linq query is not directly complied into binaries by the c# compiler and sent to the SQL Server process to retrieve the data (because for the sql server to interpret the binaries and respond with result is non-sense).

So, the ideal think to do, is to convert the above linq into its equivalent string query and send across the wire to the SQL server process, so that it can interpret and respond with the desired result.

If so, then how to generate the best, efficient and equivalent string query ? this question lead to the invention of the Expression Tree Data structure, along with the effective built-in algo to convert the data structure into its equivalent string representations (in case of Linq to SQL).

If you drill into the type definition  of the above linq query, you will notice that the query returns a IQueryable  type and whose definition in turn looks as below,

public interface IQueryable : IEnumerable

{

Type ElementType { get; }

Expression Expression { get; }

IQueryProvider Provider { get; }

}

So now its apparent that whatever Linq to SQL query we write, it gets stored in the Expression data member of the IQueryable  type, then the in-built algo of Linq to SQL is intelligent enough to generate the best equivalent sql query string by parsing through the data structure and send it across to the sql server process.

Hence with the above advantage what i have explained (one of the in-built implementation of Expression Trees), i am sure we developers have the freedom to improvise and make use of Expression Trees in best possible ways as demanded by our application.

Labels: ,

Saturday, October 03, 2009

Extension Methods in .Net

A New Feature of .Net:

As we all know, every release of .Net framework carries with it, a greater list of new features and functionalities which makes coding easier and impressive though. Here in this post i would like to brief about the  feature, popularly known as Extension methods.

Extension Methods:

Earlier when we wanted to add some new features to an existing class, we usually end up creating custom classes and then write custom methods to achieve the desired functionality. Though in many places implementing custom classes is inevitable and unavoidable, there are scenarios where we can avoid them by simple using this new feature called Extension methods.

Short and Simple:

KISS, As one of the famous  mantras of coding -Keep It Short and Simple, extension methods of .Net  does the same. Yes, they are very simple to implement and very clean to use.

For ex..) we are all familiar with the DateTime structure of c# –(Represents an instant in time, typically expressed as a date and time of day). Assume that we have a requirement where, we need to show up date in English(Culture – en-US)at many places in the application. If so, we can create a extension method to the DateTime object and use it as similar to any other method of the  DateTime object.

Implementation:

Rules-

1. Extension methods are to be part of a static class.

2. Extension methods are defined as static methods but are called by using instance method syntax.

3. The first parameter of the method, specifies, on which type the method operates on (in our case its the DateTime type) and the parameter holds this keyword as its successor /modifier.

4. There could be additional parameters provided based on the functionality required for the implementation.

Pseudo code- creating Extension methods

public static class DateFormatter
    {
        public static string ToEnglishDate(this DateTime obj)
        {
            CultureInfo culture = new CultureInfo("en-US");
            return obj.ToString("dd MMMM yyyy", culture);
        }
    }

Pseudo code- calling Extension methods

DateTime time = DateTime.Now;
           Console.WriteLine(time.ToEnglishDate());
           Console.ReadLine();

Note:

Extensions

In the above pseudo code block if you observe carefully, the extension method ToEnglishDate is being added to the DateTime type and is accessed as natively as we access the other methods and properties of the DateTime structure.

I hope this post added some value in introducing a simple but a very impressive feature of .Net framework, so lets start using them extensively and enjoy – Happy Coding.

Labels: ,

Thursday, September 17, 2009

Friendly RESTful urls, using Http Modules

REST follows

As mentioned in my earlier post(RESTful implementation using .Net) i would like to share further lights on RESTful implementation using .net, this time on implementing friendly RESTful urls using HTTP Modules. On my way to this accomplishment, i was initially doing POCs on HTTP handlers to get the job done and if readers could recollect my questions /doubts that i raised in my previous post(URL Rewriting/Redirecting for Web Service(s) – But How?) regarding the same. At last i found that HTTP modules is the perfect candidate for url redirections and not HTTP handlers.

Friendly REST urls

As an example , for a url, (the below shown url is the same RESTful url, that i had implemented in my earlier post(RESTful implementation using .Net) to get employee details).

http://domain.com/employeeprofile.asmx/GetInfo?empid=1

we can make it user friendly as below,

http://domain.com/employeeprofile/GetInfo/1

i am going take this simple scenario and show how such friendly url rewriting can be implemented using HTTP Modules. Once we get the concept, we can go ahead in developing robust url rewriting engines.

HTTP Module

HTTP Module is one of the extensibility feature and advantage provide in .Net Framework. This helps in intercepting and manipulating each of the http requests that comes  from the client to the server application. Now in order to provide meaningful RESTFul urls, i am going to make use of this advantage provided by the HTTP pipeline. Below diagram describes the HTTP pipeline and the components involved in a typical client server architecture involving .net.

clip_image002

In order to tap the incoming request using http module in our application (Web, Web service, etc) following things are to be performed.

Implementation

1. Creating Http Module class :

Add a normal class file to the application which implements  IHttpModule and its members,

System.Web.IHttpModule.Init(System.Web.HttpApplication)  &

System.Web.IHttpModule.Dispose().

The Init method can be made use to perform  initializations that are required and which also holds the handle to the HttpApplication object which  in turn has control over the request, response objects.

Here in the Init method, i am adding a event handler which processes the application’s begin request event.

public void Init(System.Web.HttpApplication app)
        {
            app.BeginRequest += new EventHandler(Rewrite_BeginRequest);

        }

then in my Rewrite_BeginRequest custom method,  i am adding a simple piece of code,which intercepts the incoming request url, checks for the user-friendly format ( these formats are to be predefined and shared to the consumers of the webs service as some manuals / guidelines, so that they get an idea on how to query for a particular data), if valid,  rewrites the url  to the original page with the desired & required parameters as query strings.

Pseudo code of the Rewrite_BeginRequest(object sender, System.EventArgs args) implementation,

1. Typecast the incoming sender object to the http application object in order to get the handle of request, response, context and other asp.net objects.

System.Web.HttpApplication Appl = (System.Web.HttpApplication)sender;

2. Tap the incoming request url, look for the friendly url pattern "/employeeprofile/GetInfo/”, if valid , crop , validate and store the id part which follows the pattern.(the valid employee id number like 1, 10, etc which comes as part of the ur after the pattern -  "/employeeprofile/GetInfo/1 ) .

3. Now, once the id is retrieved, rewrite the url to the original page by using,

Appl.Context.RewritePath("employeeprofile.asmx/GetInfo?empid=1");

That's it, now the coding for the url rewriting is done. as this is a simple demonstration i have hard-code the urls, but when it comes to real-time implementation we can define the friendly url patterns and their respective redirection urls in some configuration file and create  a url redirection module / library /engine which performs the above pseudo logic.

2. Web Config entry:

Once the coding part is over, we need to configure the custom http module in the web config, hence forth ASP.Net engine recognizes the module and invokes it,

<httpModules> 
<add type="RESTFulService.RESTfulHandlerModule,RESTFulService"      name="RESTFulRewriter" />

</httpModules>

the type attribute, takes in classname, assemblyname as input.

the name attribute is any meaningful name.

I hope this post would be a starter point in the future implementation of a robust URL rewriter engine.

Labels: , , , ,

Thursday, September 10, 2009

URL Rewriting/Redirecting for Web Service(s) – But How?

Getting Started:

I am trying out with a simple URL redirection technique; if I am successful in this approach I will go ahead in implementing friendly RESTful urls for my application. But it’s not happening the way I desired though.

Problem Definition:

I am facing problem in URL redirection while using HTTP handler technique;

I have created a VisualStudio2008 web service application.

Added 2 services, Service1.asmx and Service2.asmx.

Scenario 1:

Added an HTTP handler (GenericHandler) class in the same hierarchy. 

Added the below code in ProcessRequest method,

if (context.Request.PhysicalPath.IndexOf("Service1.asmx") > -1)

                    context.RewritePath("~/Service2.asmx");

Registered the Handler in the HTTP handler section of the webconfig, the bold one

<remove verb="*" path="*.asmx"/>

<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>

<add verb="*" type="RESTWS.RESTHandler,RESTWS" path="*.asmx"/>

Now, I run my application by making Service1.asmx as the start page, the process hits my handler code, executes it with out any exception, but at last I see a blank screen in the browser.

For crossing my code I also did the following,

Scenario 2:

Added a Global.asax file in the in the same hierarchy.

Added same code in Application_BeginRequest

if (Context.Request.PhysicalPath.IndexOf("Service1.asmx") > -1)

                Context.RewritePath("~/Service2.asmx");

Commented out the Handler registry part what I added in the webconfig.

Again ran the application, the redirection from Service1.asmx to Service2.asmx happened successfully as expected.

Scenario 3:

When I have both the Global.asax and the http handler enabled, again I get a blank page.

Scenario 4:

I felt that HTTP handler does not support url redirection in the case of asmx(web services), so I tried the same above procedures and scenarios with VisualStudio2008 Web application with 2 aspx pages (Default1.aspx and Default2.aspx) instead of Web service application. But the results were same as the above scenarios.

My Questions:

What is the mistake I am doing in my above scenarios?

How to perform url redirection for web services using Http Handlers?

Looking fwd:

Some help and suggestions extended in this regard will be greatly appreciated.

Labels: , , , ,

Sunday, August 30, 2009

RESTful implementation using .Net

Need REST from SOAP

Yes, we are tried of using SOAP and badly in need of REST;  Till date we would have mostly come across web services being implemented using SOAP (Simple Object Access Protocol) as messaging protocol for exchanging structured information (XML was chosen as the standard message structure) over HTTP (transporting medium). Though it has its own advantages, may get cumbersome due to its verbose XML format by adding soap headers and other meta-datas, thereby making it slower and also failing to utilize the power of HTTP to the fullest.

Lets REST

REST (Representational State Transfer Protocol) on the other hand defines identifiable resources (URIs - uniform Resource Identifiers), and methods for accessing and manipulating the state of those resources (HTTP verbs). Resources are like objects, they clearly differentiate each state very similar as in OOPs where each real-world entity is identified as an object having their own state (method) and attributes (properties).Resources can be identified using a single identifier scheme, typically a URL or URI. Once you have a handle/access to the resource, you can invoke methods (any http verb) and interact with it.

Few HTTP verbs,

  • GET: retrieve resource
  • POST: process resource
  • PUT: update resource representation
  • DELETE: delete resource

REST requests are modeled after the way a web browser (client) sends requests to a web server, typically a request for the REST services mostly goes in through url with query strings or in POST data block.

Typical REST request

A typical REST request for calling a web method GetInfo which takes integer ‘empid’ as the parameter will look similar to

http://domain.com/employeeprofile/GetInfo?empid=1

Each request starts with the hostname

http://domain.com

After the hostname is the service name

/employeeprofile/

Next is the method name followed by a question mark (?), followed by the actual query parameters, which take the form argument=value, where the arguments and values can be URL encoded if required. Multiple parameters are separated by an ampersand (&).

GetInfo?empid=1

Note:  

1. Method name is case sensitive

2. The order of method parameters is irrelevant and names are case insensitive.

3. If a web method takes some complex parameters, for e.g.) like array,

Public void SetNames(String [] empNames)

Then at the client program while calling the method, we pass the values as

http://localhost:3578/Service1.asmx/GetEmpInfo?empNames=Sethu&empNames=Ram&empNames=Kumar.

The REST service is intelligent enough to group up the query string params with name empNames into a string[] of empNames.

REST Implementation

In order make the .Net web service application to work as Restful services,

1. We need to configure web config file to add the required HTTP verbs.

<system.web>

    <webServices>

      <protocols>

        <add name="HttpGet"/>

        <add name="HttpPost"/>

      </protocols>

    </webServices>

</system.web>

2. Then we can go ahead and create normal web methods using c# .Net web service application as we do earlier.

[WebMethod]

public EmployeeList GetEmpInfo(int empid)

Input:

            empid: required integer paramter.

            If  empid = 0, then it will return the details of all the employees of domain(some x company).

            If  empid is any valid id number of the employee it would return his/her corresponding details.

Output schema:

EmployeeList: It’s basically a serialized list of employee object. (NAME and ID)

<Employees>

<Employee>

  <NAME>Anand</NAME>

  <ID>1</ID>

</Employee>

<Employee>

  <NAME>Abhishek</NAME>

  <ID>2</ID>

</Employee>

<Employee>

  <NAME>Jyothi</NAME>

  <ID>3</ID>

</Employee>

<Employee>

  <NAME>Sethuram</NAME>

  <ID>4</ID>

</Employee>

<Employees>

3. When it comes to accessing these web methods, its not require to create a proxy or stub at the consuming client. We can invoke the web methods using simple HttpWebRequest and HttpWebResponse objects and call the required service url along with parameters as below,

< http://localhost:3578/Service1.asmx/GetEmpInfo?empid=4>

string result = string.Empty;

string url = "http://localhost:3578/Service1.asmx/GetEmpInfo?empid=4";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

request.Method = "GET";

using(HttpWebResponse response = HttpWebResponse)request.GetResponse())

{

using (Stream responseStream = response.GetResponseStream())

                  {

using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))

                        {

                        XmlDocument xmlDocument = new XmlDocument();

                        xmlDocument.LoadXml(readStream.ReadToEnd());

                        }

                  }

}

Once we get the response output xml schema, we can load it either in XML DOM or parse it through a reader object.

REST Advantages

  • Human readable formats and results.
  • They are stateless.
  • Light weight as purely http.
  • No security issues with firewalls
  • Relative ease and quick to develop.

Companies using REST

  • Yahoo! - All Yahoo API's Web Services uses REST including Flickr etc
  • Google - Google Adsense Search and Google Maps are two good examples for RESTful services implemented by Google
  • Amazon
  • EBay
  • del.ico.us

I am sure this list to going to grow exponentially due to its simplicity to develop and ease of use.

Rest of REST in Rest

I hope I have thrown a bit of light on the RESTful design concepts. (I am sure REST will have a greater impact on the future of the World Wide Web). Here in this post, I have just briefed on the fundamentals of RESTful service, may be I can elaborate on the rest of RESTful design concepts in the rest of my blog posts to follow.

Labels: , ,

Friday, July 24, 2009

M-Commerce Unleashed


WIKI’s Definition: Mobile Commerce is any transaction, involving the transfer of ownership or rights to use goods and services, which is initiated and/or completed by using mobile access to computer-mediated networks with the help of an electronic device.
Layman’s terms: M-Commerce is an act of buying and selling goods, services or information without any location restrictions, by any mobile device which uses a wireless connection to establish communication between all the necessary parties to complete the transaction.

M-Commerce Transaction (Transaction from a Buyer’s point of view)
Transaction Actors
Buyer (User)
Seller (Content Provider)
Network (Internet / Mobile Service Provider)
Transaction from a Buyer’s point of view.
Transaction Legend
Data Communication layer: Internet / Service Provider Network / Any unique system to complete trading successfully.
Point of Sale (POS): Place / Instance at which the goods / service is traded (purchased successfully)
Proof of Purchase (M-Ticket): Received at POS, as acknowledge/receipt for the trading.
Point of Entry (POE): Place where the M-Ticket is redeemed to avail the service (time of delivery).

M-Commerce Technical Aspects
The idea line behind any m-commerce application is the ability to make commerce transaction through mobile. To be more specific, uniquely identifying & authentication the commerce transaction based on the user’s MSISDN. Technically the billing system which involves a seamless transaction back and forth between the mobile and the payment gateway is the key. Different ways to accomplish M-Commerce are
1> SMS channel: This is commerce between consumer and supplier over SMS. SMS channel is used as a medium for interaction to place order & for payment.
2> WAP channel: This is commerce between consumer and supplier over WAP medium. WAP channel is used as a medium for interaction; the mobile user interacts with supplier’s WAP site and place order and makes the payment.
3> Internet channel: This is the commerce between consumer and supplier over the Web. Mobile user interacts with supplier’s website over Internet using a PC, his mobile number is used as identifier for the transaction and it might need SMS or WAP channel to complete the transaction.
All three channels have their limitations as well as benefits:
Though SMS channel(PUSH marketing) has larger coverage area, same time it difficult to place order as the user have to remember keywords & item code for placing orders.
WAP channel (PULL marketing) need active GRPS connection on mobile, same time its more user friendly.
Internet channel cannot be used everywhere as user need active internet connection, same time it’s more user friendly and has better UX (User Experience).

Real-time Scenario
Just think how exciting it will be if you can place order for a cup of cappuccino using your mobile device on our drive back home and by the time we reach, hot cappuccino awaits at the door steps.
Mr. Swami decides the same and sends an SMS to 9898 with text “CAPCINO 1” to the coffee pub to which he has enrolled thereat. After few seconds he receives an acknowledgement SMS with text “Order for 1 cappuccino will be delivered in 15 mins and you are charged Rs. 50”. On his arrival to his residence, a delivery man offers Mr. Swami a hot cup of cappuccino to drink, taste, enjoy and refresh.

Labels:

Saturday, July 18, 2009

RADTreeView –Print Utility


Utility Overview:

RADTreeView control is a popular product of Telerik which I have used in my sample .Net WinForm application. Though there were a plenty of print tree utilities available on the net there was not much for printing RADTreeView controls. The snippets that are available were either making use of the Win APIs or printing a simple .Net treeview control, neither of them was of my interest. At the dieing moment’s of my depth first search, thanks to Mark Pitman blog for giving insight on capturing and preparing a tree image for printing. With this I went ahead in writing my own pseudo code to print RADTreeView .

Printer Utility:
I would like to split this pseudo code explanation into 2 segments,

1. Preparing the treeview for print
This step is crucial though for the reason, to capture the complete snapshot of the data or content within a treeview or any control for that matter which has the nature to grow and expand using horizontal and vertical scrollbars is not a cakewalk. It’s tricky and needs a bit of work around. In order to capture a snapshot of the complete node collection of the treeview, first we need to get hold of the virtual width and height of the tree in its expanded state; the Width and Height or the ClientSize.Width and ClientSize.Height properties of the treeview just gets the size of the treeview that is visible or rendered on the UI, they are completely ignorant of the virtual width and height of the expanded tree. Thanks to RADTreeView control which has a ready to use property as such as VirtualWidth and VirtualHeight for this purpose.

Work around Algorithm:
a) Get the Handle / Reference of the RADTreeView .
b) Store the current settings (original width, height and docking styles) in some temp variables.
c) Draw a virtual snapshot of the tree to a bitmap image, by resizing it to its virtual width and height.
d) Reset the tree to its default original settings for to be rendered as similar as it was rendered initially.

Code Snippet:
// storing the original tree settings in temp variables.
int tempHeight = tree.Height;
int tempWidth = tree.Width;
DockStyle tempDockStyle = tree.Dock;

// creating a virtual tree to capture all node details.

int scrollOffset = 10; // an offset to capture the entire tree image eradicating scrollbar mishaps.
tree.Dock = DockStyle.None; // helps to resize the tree to its virtual width and height.
tree.Width = tree.VirtualWidth;
tree.Height = tree.VirtualHeight + scrollOffset;

// Capturing the complete tree’s snapshot into a bitmap
memoryImage = new Bitmap(tree.Width, tree.Height);
tree.DrawToBitmap(memoryImage, new Rectangle(0, 0, tree.Width, tree.Height - scrollOffset));

// setting back the default settings of the original tree.
tree.Width = tempWidth;
tree.Height = tempHeight;
tree.Dock = tempDockStyle;

Above snippet is self explanatory though, there are 3 key things to watch out for,

a) Dock Style: It’s a very important property that needs to be attended. When we try to expand the tree view to its virtual width and height, and if the tree control is docked to its parent container, we should ensure that tree view’s dock property is set to DockStyle.None. Only after undocking, the tree view can be resized to its virtual width and height for the snapshot.

b) scrollOffset: Its any arbitrary integer, not required though, but I had to use it in order to
Eliminate scroll bar mishaps. Ideally the virtual width and height should get the complete tree nodes, eliminating the scrollbars but was not happening in my case. I had to do some work around like, add this scrollOffset to the virtual height during tree expansion in order to capture the missed out fragment of data at the bottom end of the tree and also subtracting the same from virtual height during bitmap generation for cropping out the visible horizontal scrolls from the print document.

c) DrawToBitmap: Performs rendering of the specified control to a bitmap object of specified size into the rectangle boundary specified.

Bitmap treeImage = new Bitmap(tree.Width, tree.Height);
tree.DrawToBitmap(treeImage, new Rectangle(0, 0, tree.Width, tree.Height - scrollOffset));

2. Printing the treeview image
Now, we are ready to print the prepared snapshot. For this I am sticking to the .Net books by making use of the PrintDocument and PrintPreviewDialog classes of System.Drawing.Printing assembly. PrintPreviewDialog class helps to show a preview of the document that is to be printed; we can also programmatically make printer configurations and other custom settings using PrintDialog class which are out of box stuffs pertaining to our context.

PrintDialog printd = new PrintDialog();
DialogResult res = printd.ShowDialog();
if (res == DialogResult.OK)
{
PrintPreviewDialog pp = new PrintPreviewDialog();
pp.Document = this._printDoc;
pp.Document.PrinterSettings = printd.PrinterSettings;
pp.Show();
}

PrintDocument class does the actually printing business; three important events that are to be handled are,
a) BeginPrint: Any initialization code required for printing, like document Page numbers can be set here.
b) PrintPage: The document printing operation takes place here.
Draws the specified portion of the specific image in the specified location with the specified size.

Graphics g = e.Graphics; // System.Drawing.Printing.PrintPageEventArgs e
g.DrawImage(treeImage, destinationRect, sourceRect, GraphicsUnit.Pixel);

c) EndPrint: Memory flush out operations can be performed here.
Hope this article along with pseudo code throws a bit of light in creating utility class for printing RADTreeView control.

Labels: , ,