Archive for the Category ◊ .Net ◊

Author:
Friday, July 04th, 2014
Exporting DataSet to Excel using NetOffice

Goal of this blog is to export dataset to microsoft excel using NetOffice.

You can read more about NetOffice here

As a first step, include nuget package “NetOffice.Excel”,
type “netoffice” in nuget package manager from visual studio and the first one in the list will be
“NetOffice.Excel”

We have a dataset which includes datatable named “Users”

Complete code is listed below.

References to include

 
               
            using System.Data;
            using System.Reflection;
            using NetOffice.ExcelApi.Enums;
            using Excel = NetOffice.ExcelApi;
                
                
            
        public void GetExcel()
	    {
		//Create excel application
		var application = new Excel.Application();

		//Add workbook
		application.Workbooks.Add();

		application.DisplayAlerts = false;

		//Get all data into an array
		var tempArray = new object[dataset.Tables["Users"].Rows.Count,                                                     dataset.Tables["Users"].Columns.Count];
		for (var r = 0; r < dataset.Tables["Users"].Rows.Count; r++)
		{
			for (var c = 0; c < dataset.Tables["Users"].Columns.Count; c++)
				tempArray[r, c] = dataset.Tables["Users"].Rows[r][c];
		}

		//Get column names into an array
		var tempHeadingArray = new object[dataset.Tables["Users"].Columns.Count];
		for (var i = 0; i < dataset.Tables["Users"].Columns.Count; i++)
		{
			tempHeadingArray[i] = dataset.Tables["Users"].Columns[i].ColumnName;
		}

		//Create style used for displaying column names
		var style = application.ActiveWorkbook.Styles.Add("NewStyle");
		style.Font.Name = "Verdana";
		style.Font.Size = 10;
		style.Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Black);
		style.Font.Bold = true;

		//Get active worksheet
		var sheet = (Excel.Worksheet)application.ActiveSheet;

		AddColumnNames(sheet, tempHeadingArray);

		AddExcelHeadingText(sheet);

		AddDataRows(sheet, dataset, tempArray);

		sheet.Columns.AutoFit();

		application.ActiveWorkbook.SaveAs("E:\\Sampledocument",  Missing.Value, Missing.Value,                                 Missing.Value, false,
										  false, XlSaveAsAccessMode.xlExclusive);

		//CleanUp
		application.ActiveWorkbook.Close();
		application.Quit();
		application.Dispose();
	}

                

Helper methods are listed below

                
            
	 private static void AddDataRows(Excel.Worksheet sheet, DataSet dataset, object[,] tempArray)
	 {
		var range = sheet.Range(sheet.Cells[4, 1],
						sheet.Cells[(dataset.Tables["Users"].Rows.Count), (dataset.Tables["Users"].Columns.Count)]);
		sheet.Name = "Sample excel....";
		range.Value = tempArray;
	 }

	private static void AddColumnNames(Excel.Worksheet sheet, object[] tempHeadingArray)
	{
		var columnNameRange = sheet.get_Range(sheet.Cells[3, 3], sheet.Cells[3, tempHeadingArray.Length + 2]);
		columnNameRange.Style = "NewStyle";
		columnNameRange.Value = tempHeadingArray;
		columnNameRange.UseStandardWidth = true;
	}

	private static void AddExcelHeadingText(Excel.Worksheet sheet)
	{
		//Apply styling to heading text
		sheet.Cells[1, 1].Value = "Excel heading text";
		sheet.Cells[1, 1].Font.Name = "Verdana";
		sheet.Cells[1, 1].Font.Italic = true;
		sheet.Cells[1, 1].Font.Underline = true;
		sheet.Cells[1, 1].Font.Size = 14;
		sheet.Cells[1, 1].Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.DarkRed);
	}

     

When you are deploying this to IIS, make sure you give sufficient permission for the IIS user for DCOM object(Microsoft Excel Application)

Steps to follow to achieve this:

1. Go to component services

2. Expand DCOM Config

3. Right click on ‘Microsoft Excel Application’

4. Select properties

5. Go to security tab

6. Select Customize and click on Edit(for all three permission types)

7. Add respective user and give sufficient permission

Thals all Folks! Happy Exporting!!

 

Category: .Net  | Leave a Comment
Author:
Friday, July 04th, 2014

 

Exporting DataSet to Excel using OpenXML with out physically saving it

In this blog we are trying to stream dataset to excel with out having to save it physically on the server.
We will create the excel in memory using openXML and stream it to output.

More about open xml here

As a first step, include nuget package “DocumentFormat.OpenXml 2.5.0″,
type “OpenXML” in nuget package manager from visual studio and the first one in the list will be “DocumentFormat.OpenXml 2.5.0″

Don’t forget to add reference to “WindowsBase” assembly, OpenXML internally uses it.

We have a dataset which includes datatable named “Users”

Complete code is listed below.

                
        public MemoryStream GetExcelStream()
        {
            using (var ms = new MemoryStream())
            {
                //Create workbook in memory
                var document = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook);

                //Add workbook
                var workbookpart = document.AddWorkbookPart();
                workbookpart.Workbook = new Workbook();

                //Add worksheet to workbook
                var worksheet = workbookpart.AddNewPart();
                worksheet.Worksheet = new Worksheet(new SheetData());

                //Add styles to workbook(ExcelStyleSheet is a separate class 
                    //- refer end of the blog for more details on how to add styles)
                var stylesPart = workbookpart.AddNewPart();
                stylesPart.Stylesheet = ExcelStyleSheet.GenerateStyleSheet();
                stylesPart.Stylesheet.Save();

                var sheets = document.WorkbookPart.Workbook.
                                            AppendChild(new Sheets());

                // Add a new worksheet and associate it with the workbook.
                var mainSheet = new Sheet()
                    {
                        Id = document.WorkbookPart.GetIdOfPart(worksheet),
                        SheetId = 1,
                        Name = "mySheet"
                    };
                sheets.Append(mainSheet);

                uint rowIndex = 0;

                //Get sheet data
                var sheetData = worksheet.Worksheet.GetFirstChild();

                var row = new Row {RowIndex = ++rowIndex};

                AddColumnHeaderRow(dataset, row, sheetData);

                AddDataRows(dataset, rowIndex, sheetData);

                workbookpart.Workbook.Save();
                document.Close();

                return ms;
            }
        }
             

We have to loop through the columns and get column names to create header row in excel

                
        private static void AddColumnHeaderRow(DataSet dataset, Row row, SheetData sheetData)
        {
            for (var i = 0; i < dataset.Tables["Users"].Columns.Count; i++)
            {
                var cell = new Cell {DataType = CellValues.InlineString, StyleIndex = 1};
                var inlineCell = new InlineString();
                var cellText = new Text {Text = dataset.Tables["Users"].Columns[i].ColumnName};
                inlineCell.AppendChild(cellText);
                cell.AppendChild(inlineCell);

                row.AppendChild(cell);
            }

            //Append new row to the sheet data
            sheetData.AppendChild(row);
        }

Loop through all the data rows, create and append excel rows to data sheet

                
        private static void AddDataRows(DataSet dataset, uint rowIndex, SheetData sheetData)
        {
            for (var r = 0; r < dataset.Tables["Users"].Rows.Count; r++)
            {
                var row = new Row {RowIndex = ++rowIndex};

                for (var c = 0; c < dataset.Tables["Users"].Columns.Count; c++)
                {
                    var cell = new Cell {DataType = CellValues.InlineString};
                    var istring = new InlineString();
                    var t = new Text {Text = dataset.Tables["Users"].Rows[r][c].ToString()};
                    istring.AppendChild(t);
                    cell.AppendChild(istring);
                    row.AppendChild(cell);
                }

                //Append each data row to sheet data
                sheetData.AppendChild(row);
            }
        }

This returns us the memory stream, now we just have to write it to response stream and the code is listed below

                
        void btnExport_Click(object sender, EventArgs e)
        {
            var excelLibrary = new ExcelLibrary();

            var byteArray = excelLibrary.GetExcelStream();

            HttpResponse response = HttpContext.Current.Response;
            response.Clear();
            response.Buffer = false;
            response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            response.AddHeader("Content-Disposition: ",
                "attachment; filename=sample.xlsx");

            response.BinaryWrite(byteArray.ToArray());
            response.Flush();
            response.Close();
        }

“ExcelStyleSheet” in this example(first code block) is a separate class which contains styles for our workbook.
Code for that class is listed below(Reference – http://blogs.msdn.com/b/chrisquon/archive/2009/11/30/stylizing-your-excel-worksheets-with-open-xml-2-0.aspx).


    internal class ExcelStyleSheet
    {
        public static Stylesheet GenerateStyleSheet()
        {
            return new Stylesheet(
                new Fonts(
                    new Font( // Index 0 - The default font.
                        new FontSize() {Val = 11},
                        new Color() {Rgb = new HexBinaryValue() {Value = "000000"}},
                        new FontName() {Val = "Calibri"}),
                    new Font( // Index 1 - The bold font.
                        new Bold(),
                        new FontSize() {Val = 11},
                        new Color() {Rgb = new HexBinaryValue() {Value = "000000"}},
                        new FontName() {Val = "Calibri"})
                    ),
                new Fills(
                    new Fill( // Index 0 - The default fill.
                        new PatternFill() {PatternType = PatternValues.None}),
                    new Fill( //Index
                        new PatternFill() {PatternType = PatternValues.DarkGray})                    
                    ),
                new Borders(
                    new Border( // Index 0 - The default border.
                        new LeftBorder(),
                        new RightBorder(),
                        new TopBorder(),
                        new BottomBorder(),
                        new DiagonalBorder()),
                    new Border( // Index 1 - Applies a Left, Right, Top, Bottom border to a cell
                        new LeftBorder(
                            new Color() {Auto = true}
                            ) {Style = BorderStyleValues.Thin},
                        new RightBorder(
                            new Color() {Auto = true}
                            ) {Style = BorderStyleValues.Thin},
                        new TopBorder(
                            new Color() {Auto = true}
                            ) {Style = BorderStyleValues.Thin},
                        new BottomBorder(
                            new Color() {Auto = true}
                            ) {Style = BorderStyleValues.Thin},
                        new DiagonalBorder())
                    ),
                new CellFormats(
                    new CellFormat() {FontId = 0, FillId = 0, BorderId = 0},
                    // Index 0 - The default cell style.  
                    new CellFormat() {FontId = 1, FillId = 0, BorderId = 1, ApplyFont = true}, // Index 1 - Bold 
                    new CellFormat( // Index 5 - Alignment
                        new Alignment()
                            {
                                Horizontal = HorizontalAlignmentValues.Center,
                                Vertical = VerticalAlignmentValues.Center
                            }
                        ) {FontId = 0, FillId = 0, BorderId = 0, ApplyAlignment = true},
                    new CellFormat() {FontId = 0, FillId = 0, BorderId = 1, ApplyBorder = true} // Index 6 - Border
                    )
                ); 
        }
    }

     
Category: .Net  | Leave a Comment
Tuesday, July 01st, 2014

Below I will explain how to fail MS Build if functional test coverage drops from previous value.

I have used

NCover as the functional coverage tool
NUnit for writing functional test cases

To get coverage information in MS Build we need to do some changes in the build definition.

1. Generate Ncover report

Add an invoke process in build definition to run a batch file which uses command

NCover.exe report --project="MyProject" --file="C:\Reports\NCoverReport.html

2. Read branch coverage from the generated HTML report

Create a new code activity.

This code activity should be responsible for reading NCover generated HTML report and retrieve branch coverage information and store in a build definition variable. For ex: PreviousFunctionalCoverage.

Add this code activity before execution of functional test cases.
This will make sure that before running functional test cases, we get previous coverage info.

Next step is to run functional test cases.
This part needs a little tweaking.

For ex:

Currently, If below is the command to run functional test cases

Start nunit-console-x86.exe "C:\Projects\MyProject.dll" "/result:C:\Reports\Result.xml"

This needs to be changed as shown below

NCover.exe Enable --MyProject
NCover.exe Run --project="MyProject" -- "C:\Program Files (x86)\NUnit 2.6.3\bin\nunit-console-x86" C:\Projects\MyProject.dll" "/result:C:\Reports\Result.xml"
NCover.exe Disable –-MyProject

The above change does few things

1. It will enable NCover to start module collection on MyProject.
2. NCover will execute NUnit command which in turn execute functional cases.
3. Disable module collection on my project

Finally, Generate NCover report. This would overwrite the old report.
Execute the code activity task again

Since NCover report is overwritten this time code activity returns new coverage value.
Store in another build definition variable. For ex: NewFunctionalCoverage

We have both previous and new coverage values. It’s very simple to fail the build.
Compare both values in an if block. If new value is less than previous value, set build status as BuildStatus.Failed.

Author:
Monday, June 30th, 2014

There was a Login page, that did some sort of authorization check beyond authenticating the user, and displayed an Access Denied page for those who weren’t lucky enough. This was all done by the ASP.NET MVC with ASPX view engine. So there’s things like Views, Partial Views, RenderPartial, and so on. The application also was heavily ajax enabled, so partial views really seemed to fit in at many places that did not want to include a master page content in the response text. There was a view file called AccessDenied.aspx that barked at unauthorized users. Things were working fine, and one day something broke, IIS was crashing without any meaningful error message. I lied, actually it did give a meaningful error message that was like – An unhandled exception of type ‘System.StackOverflowException’ occurred in mscorlib.dll. And the Call Stack showed some recursive function call. That is all there was to it.

Let’s look at a POC sample application below. Download the source from github – https://github.com/gmaran23/ASPXViewEngineCrash, Hit F5.

 

clip_image002[11]

 

When you click the AccessDeniedForCrash page, the below is what you see. An unhandled exception of type ‘System.StackOverflowException’ occurred in mscorlib.dll. If you look at the Call Stack window, there would be a lot of repeated method calling method.

 

clip_image002[13]

 

Let’s look at what happens when a view is requested, as in how the view engine probes the known locations to find the view definition. Click ViewDoesNotExist, and you would see an error page, that actually tells you the file locations that ASPX view engine probed to find a matching view. Pay attention to the search order where a .aspx file is searched first, and then the .ascx file.

clip_image002[15]

Now, if you go back to the StackOverflowExceptionInASPXViewEngine solution, there are two files called AccessDeniedForCrash.ascx and AccessDeniedForCrash.aspx under ~/Views/Home.

 

clip_image002[19]

 

The following code inside AccessDeniedForCrash.aspx calls the partial view AccessDeniedForCrash.ascx.

 

<asp:Content ID="Content3" ContentPlaceHolderID="FeaturedContent" runat="server">
            <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <% Html.RenderPartial("AccessDeniedForCrash"); %>
            </hgroup>
        </div>
    </section>
</asp:Content>

 

A typical programming practice right? You define sub routines, and you keep calling them as and when required. Reusability! You have created a partial view here (AccessDeniedForCrash.ascx), and kept calling the partial view inside the main view (AccessDeniedForCrash.aspx). But it was the ASPX view engine’s probing method that caused the recursive method call. The view engine reached AccessDeniedForCrash.aspx, as it came through the HomeController’s action method AccessDeniedForCrash. It tried to find a partial view AccessDeniedForCrash.ascx,  but always ended up with AccessDeniedForCrash.aspx because of the file search order; you know the rest of the story about recursion without an exit condition.

So, is this a programming error? or the framework error? or the ‘programmer did not understand the framework well’ error?

Author:
Sunday, June 22nd, 2014

In part 1 we looked at some extension methods for the BrowserWindow class. In this post, we’ll look at some useful extension methods for dealing with Html controls.

The extension methods in part 1 returned the HtmlControl object. We can extend to add an action like Click:

public static class HtmlControlExtension
    {
        public static void Click(this HtmlControl control)
        {
            try
            {
                Mouse.Click(control);
            }
            catch (FailedToPerformActionOnBlockedControlException)
            {
                // backup mechanism if CodedUI fails to click an item
                var htmlHtmlElement = control.NativeElement as HTMLHtmlElement;
                if (htmlHtmlElement != null)
                    htmlHtmlElement.click();
            }
        }
    }

You’ll notice that I’m using the NativeElement to retry the click if the normal method fails. In one of our pages, we were adding controls dynamically to the page through javascript. And the normal Click kept throwing FailedToPerformActionOnBlockedControlException. We tried using the NativeElement and it worked!

You will have to add a reference to Microsoft.mshtml to get the HTMLHtmlElement class referred in the code.

Here’s one of the ways to check for visibility:

        public static bool IsVisible(this HtmlControl control)
        {
            try
            {
                var ele = ((IHTMLElement2) control.NativeElement);
                return ele.currentStyle.display == null || ele.currentStyle.display != "none";
            }
            catch (UITestControlNotVisibleException)
            {
                return false;
            }
        }

It’s hard to do much with HtmlControl class cos it’s just a base class with simple properties and methods. For example, if you want to enter text into a textbox, you’ll need an instance of HtmlEdit class. If you want to work with dropdowns, you’ll need an instance of HtmlComboBox. Which means your search queries will have to use those classes.

It would be great if we can just perform these actions on HtmlControl instance. Fortunately, there is way to get and HtmlEdit or an HtmlComboBox (or any HtmXXXXX class for that matter) from an instance of HtmlControl class. It’s not very intuitive, but it works. We can use the CopyFrom method as below:

        public static void SetText(this HtmlControl control, string text)
        {
            control.SetFocus();
            var edit = new HtmlEdit();
            edit.CopyFrom(control);
            edit.Text = text;
        }

        public static void SelectFromDropdown(this HtmlControl control, int index)
        {
            var combo = new HtmlComboBox();
            combo.CopyFrom(control);
            combo.SelectedIndex = index;
        }

        public static string GetSelectedItem(this HtmlComboBox control)
        {
            var combo = new HtmlComboBox();
            combo.CopyFrom(control);
            return combo.SelectedItem;
        }

        public static bool SelectTextFromListBox(this HtmlControl control, string value)
        {
            var combo = new HtmlList();
            combo.CopyFrom(control);

            var contentList = combo.GetContent();
            if (contentList.Any(x => x.Contains(value)))
            {
                combo.SelectedItemsAsString = value;
                return true;
            }

            return false;
        }

I hope the methods and techniques mentioned above make it a bit easier for you to work with CodedUI.

-Anand

Category: .Net | Tags:  | Leave a Comment
Sunday, June 22nd, 2014

Quite often it happens that we have logic of sending mails in .Net applications which we are unable to test correctly during development due to following reasons.

  1. We don’t want to actually send mails to the concerned person
  2. We dont have smtp server running on our development / testing machines

In such cases we usually have two options , either comment out the logic or install some third party fake smtp  server / emulator.

While going through MSDN I stumbled upon a very nice inbuilt feature which can be of great help in above scenarios.

Usually  our mail sending logic looks more  or less like below code

Class File:


MailMessage mail = new MailMessage();
            SmtpClient SmtpServer = new SmtpClient(); 

            mail.From = new MailAddress("<FromEmailAddress>@gmail.com");
            mail.To.Add("<ToEmailAddress>@yahoo.co.in");
            mail.Subject = "Demo Subject";
            mail.Body = "Testing send mail through Gmail"; 

            SmtpServer.Send(mail);


Config:


 <system.net>
 <mailSettings>
      <smtp from="<FromEmailAddress>@gmail.com">
        <network host="smtp.gmail.com" port="587" userName="<UserName>" password="<Password>" enableSsl="true" />
      </smtp>
    </mailSettings>
    </system.net>

Now by using “specifiedPickupDirectory” element  in config you can choose a directory on the local machine where all the emails will be created (but will not be sent).Change the above config snippet as shown below and you are done.


<system.net>
     <mailSettings>
    <smtp deliveryMethod="SpecifiedPickupDirectory" from="<FromEmailAddress>@Gmail.com">
        <specifiedPickupDirectory pickupDirectoryLocation="c:\email"/>
    </smtp>
    </mailSettings>
  </system.net>

On executing the code with above configuration you will see the email message file generated in the pickup directory which can be opened by outlook or a free eml file reader (in some cases you should even be able to open it through Notepad).

image

Category: .Net | Tags: , , ,  | Leave a Comment
Author:
Friday, May 09th, 2014

 

 

 

 
 
 

Agenda:

 

·         XML today

·         XML/XPath injection – Demo

·         Compiled XPath queries

·         DTD use and abuse

-          document validations

-          entity expansions

-          denial of service – Demo

-          arbitrary uri access (egress)

-          parameters

-          file enumeration and theft – Demo

-          CSRF on internal systems – Demo?

·         Framework defaults limits/restrictions

·         Mitigations

·         Lessons learned

·         Verifying your XML systems for potential threats

 

 

Note:

1.       All of them inclusive of sample code for exploits and prevention. Language(C#, Java, php)/Platform(Windows/Linux) agnostic wherever possible.

2.       It is imperative at this juncture, that you are aware of most attack scenarios against XML, because the framework defaults may not protect you, hence you may be vulnerable, you might have not found it yet.

3.       The session is a bit biased towards DTD abuse in XML systems, as the Injection concepts and remediation remain common in XML when compared to Sql injection.

Author:
Friday, May 09th, 2014

 

 

This video is for anyone that likes to know how to test an application for Sql Injection. The content and presentation was focussed on Quality Assurance personnel who are not penetration testers.

Agenda:
Context setting
Quick introduction –
GET/POST/PUT/DELETE
XML/SOAP/JSON
Browser addons for easy proxy switching
Intercepting proxies – Fiddler, OWASP ZAP, BurpSuite, ..?
Fuzzing and identifying vulnerable parameters
Code review pointers for Buddy testing
Demonstration Fiddler, ZAP, sqlmap, Sql Inject Me
Firsthand experience with Sqli tools (Vijay/Shashank)
Feedback

 

Related Blogs/Videos/Downloads:

Devouring Security – Sql Injection Part 2  | http://vimeo.com/85256464
Devouring Security – Sql Injection Part 1  | http://vimeo.com/83658524

Foxy Proxy

Chrome extension (open from chrome browser) – https://chrome.google.com/webstore/detail/foxyproxy-standard/gcknhkkoolaabfmlnjonogaaifnjlfnp?hl=en

Firefox Extenstion (open from Firefox) – https://addons.mozilla.org/en-US/firefox/addon/foxyproxy-standard/

fiddler

http://www.telerik.com/download/fiddler

OWASP zap

https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project

sqlmap

http://sqlmap.org/

active python

http://www.activestate.com/activepython/downloads

Mantra browser

http://www.getmantra.com/download.html

Author:
Sunday, May 04th, 2014

 

Skip the story

I have always wanted to build tools supporting the command like switches like the classic CONVERT command with switches like /FS:, /CvtArea:, and so on.  Couple of years back when I had to build one, I was in a hurry and my options for command line switch parsing (regex, or string splitting), didn’t look bright, back then; I went ahead with the regular string[] args array with no switches. For instance mine was like myprogram.exe ‘filename’ ‘30’, instead of the classic switch style command invoke myprogram.exe /filename:foo.file  /iterations:30. Yeah I know it was the past, and we wouldn’t want to retrospect always. Besides, nobody would have even noticed the work that would have gone behind such an effort because we all seem to like the GUI most of the time, but hey what about self content.

This time, while I was playing with the command line options of CAT.Net and FxCop, and I thought why not just disassemble and study their command line switch parser. These programs must have been written on .Net. So, I opened up CatNetCmd.exe in JustDecompile, created a project  out of it. Arguments.cs was the file I was after. Very neat command line switch parsing with SwitchHandler delegate. Well, so I had my first console application with switch enabled command line arguments. Ildasm.exe was the widely known option during the days of Inside C#, then came along .Net reflector (freeware then, commercial now). I seem to be biased to JustDecompile though, because of the Search, Ctrl+Click for Find Usages, Click to Go to Definition, on demand dll load prompt, and the Create Project… option that I present here.

 

Download the Free. For everyone. Forever JustDecompile from Telerik – http://www.telerik.com/products/decompiler.aspx. I am going to show you, how to create a Project out of CAT.Net, which is by default installed to C:\Program Files (x86)\Microsoft\CAT.NET\.

 

1. Right click CATNetCmd.exe and select Open with JustDecompile.

image

 

2. Once the assembly is loaded in JustDecompile, just right click and just click Create Project…

image

image

image

Well, Well, Well, Open the solution file, and start debugging already!

image

Btw, if you are up against command line parsing, and looking for a ready made solution, try https://commandline.codeplex.com/.

Tuesday, April 15th, 2014

Let us look at the formal definition of the builder pattern:

Separate the construction of a complex object from its representation so that the same construction process can be used to create different representations.

What this means is, if we have to create different versions of a complex object and there are many ways in which it can be created, then the applicability of the builder pattern in this scenario creates the complex object in a structured and maintainable way.

Let us take an example. The object/product which we want to build is Kurkure. This product has many versions like the Masala Munch, Chilly Chatka, Green Chutney and so on.

clip_image001[12]

So, let’s start putting few things in code.

The Product Kurkure has the following attributes.

public class Kurkure

        {

            public bool PotatoCleaned { get; set; }

            public bool PotatoPealed { get; set; }

            public SnackShape SnackShape{get;set;}

            public SnackSize SnackSize { get; set; }

            public Spice Spice { get; set; }

            public PackageType Package { get; set; }

            public BrandType BrandType { get; set; }

            public void Display()

            {

                Console.WriteLine("Kurkure :{0} | Spice: {1} | Package: {2}", BrandType.ToString(),Spice,Package);

            }

        }

 

        public enum SnackSize

        {

            Big,

            Small,

            Medium

        }

 

        public enum BrandType

        {

            MasalaMunch,

            ChilliChatka,

            GreenChutney,

            Hyderabadi,

            GreenChilli

        }

 

        public enum SnackShape

        {

            Diagonal,

            Straight,

            Triangle,

            Random

        }

 

        public enum Spice

        {

            Masala,

            GreenChilli,

            GreenChutney,

            Hyderabadi,

            Tomato

        }

If we look at it closely, all the versions of Kurkure are just different versions of potato chips. It’s just potato chips cut in different shapes and sizes and different spices applied. The way to prepare each of them is similar. 

 

·         Clean the potatoes

·         Peel and cut them into the required shape and size.

·         Add spices

·         Package them

 

Let us prepare Kurkure using the builder pattern. We will start putting all the common behavior in a base class.

public abstract class KurkureBuilder

        {

            protected Kurkure kurkure;

            public Kurkure GetKurkure()

            {

                return kurkure;

            }

 

            public void CreateKurkure()

            {

                kurkure = new Kurkure();

            }

 

            public void PreparePotatos()

            {

                kurkure.PotatoCleaned = true;

                kurkure.PotatoPealed = true;

            }

            public abstract void CutPotatoes();

            public abstract void ApplySpices();

            public abstract void Package();

        }

 

 

Let us create the Masala munch and Chilli Chatka kurkure!

public class MasalaMunchBuilder:KurkureBuilder

        {

            public override void CutPotatoes()

            {

                kurkure.SnackSize = SnackSize.Medium;

                kurkure.SnackShape = SnackShape.Random;

            }

 

            public override void ApplySpices()

            {

                kurkure.Spice = Spice.Masala;

            }

 

            public override void Package()

            {

                kurkure.BrandType = BrandType.MasalaMunch;

                kurkure.Package = PackageType.LightOrange;

            }

        }

 

        public class ChilliChatkaBuilder : KurkureBuilder

        {

            public override void CutPotatoes()

            {

                kurkure.SnackSize = SnackSize.Small;

                kurkure.SnackShape = SnackShape.Straight;

            }

 

            public override void ApplySpices()

            {

                kurkure.Spice = Spice.GreenChilli;

            }

 

            public override void Package()

            {

                kurkure.BrandType = BrandType.ChilliChatka;

                kurkure.Package = PackageType.DarkGreen;

            }

        }

 

With all this in place, let us now create a Kurkure maker which actually creates the Kurkure. The maker knows the sequence in which the product has to be created.

 

public class KurkureMaker

        {

            private readonly KurkureBuilder builder;

 

            public KurkureMaker(KurkureBuilder builder)

            {

                this.builder = builder;

            }

 

            public void CreateKurkure()

            {

                builder.CreateKurkure();

                builder.PreparePotatos();

                builder.CutPotatoes();

                builder.ApplySpices();

                builder.Package();

            }

 

            public Kurkure GetKurkure()

            {

                return builder.GetKurkure();

            }

        }

 

 

Now, let us use the Kurkure maker to create some kurkures!

 

        static void Main(string[] args)

        {

            var kurkureMaker = new KurkureMaker(new MasalaMunchBuilder());

            kurkureMaker.CreateKurkure();

            var masalaMunchKurkure = kurkureMaker.GetKurkure();

            masalaMunchKurkure.Display();

 

            kurkureMaker = new KurkureMaker(new ChilliChatkaBuilder());

            kurkureMaker.CreateKurkure();

            var chilliChatkaKurkure = kurkureMaker.GetKurkure();

            chilliChatkaKurkure.Display();

           

            Console.ReadKey();

        }

       

Given below are the formal representation of players in the builder pattern.

clip_image002

 

Product:

What is being build. In our case Kurkure

 

Director:

The director in our case is the KurkureMaker. The directory uses the concrete builder(MasalaMunchBuilderut and ChilliChatkaBuilder in our example. The director also knows the sequence or order about how to build

Used directly by client.

Builder

Abstract class or interface. The KurkureBuilder in our case.

Defines steps.

Holds instance of the end product.

 

Concrete Builders

Implements the interface defined by the builder. MasalaMunchBuilder and ChilliChatkaBuilder are the concrete builders in our example.