Thursday, January 16, 2014

JQuery UI AutoComplete TextBox from Database using PageMethod in ASP.Net

In this post we’ll see how to user Jquery UI Autocomplete with asp.net pagemethod.

For database, we’ll be using Northwind database.

PageMethod:
[ScriptMethod(ResponseFormat= ResponseFormat.Json)]
    [WebMethod]
    public static List<AutoCompleteHelper> GetEmployee(string searchText)
    {
        using (SqlConnection conn = new SqlConnection())
        {
            conn.ConnectionString = ConfigurationManager
                    .ConnectionStrings["NorthwindConnectionString"].ConnectionString;
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.CommandText = "select CustomerID,ContactName from Customers where " +
                "ContactName like @SearchText + '%'";
                cmd.Parameters.AddWithValue("@SearchText", searchText);
                cmd.Connection = conn;
                List<AutoCompleteHelper> listAutoCompleteHelper = new List<AutoCompleteHelper>();
                conn.Open();
                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    while (sdr.Read())
                    {
                        AutoCompleteHelper objCompleteHelper = new AutoCompleteHelper();
                        objCompleteHelper.displayText = Convert.ToString(sdr["ContactName"]);
                        objCompleteHelper.displayValue = Convert.ToString(sdr["CustomerID"]);
                        listAutoCompleteHelper.Add(objCompleteHelper);
                        
                    }
                }
                conn.Close();
                Thread.Sleep(3000);
                return listAutoCompleteHelper;
            }
        }
    }
In above code, we’re fetching data from customer table from northwind database based on text entered by user. You may want to have this code in separate (data access) layer and must use stored procedure rather than inline query, I’ve included this code just for demonstration purpose.

Select query will fetch CustomerId and CustomerName based on user input.

You may want to omit Thread.Sleep(3000), here it is used to delay response so that loading image can be displayed in textbox.

Pagemethod returns list of AutocompleteHelper class which is as below:
public class AutoCompleteHelper
{
    public string displayText { get; set; }
    public string displayValue { get; set; }
}
JavaScript:
$(document).ready(function () {
            $('#<%=txtEmployeeSearch.ClientID %>').autocomplete({
                source: function (request, response) {
                    $.ajax({
                        type: "POST",
                        url: '<%=ResolveUrl("~/JqueryAutocomplete.aspx/GetEmployee")%>',
                        data: "{'searchText': '" + request.term + "'}",
                        contentType: "application/json; charset=utf-8",
                        dataType: "json",
                        success: function (dataJson) {
                            var data = dataJson.hasOwnProperty("d") ? dataJson.d : dataJson;
                            response(
                                    $.map(data, function (item) {
                                        return {
                                            label: item.displayText,
                                            value: item.displayValue

                                        }
                                    }));
                        },
                        failure: function (data) {
                            alert(data);
                        }
                    });
                },
                minLength: 1,
                search: function (e, u) {
                    $(this).addClass('ajaxprocessing');
                },
                response: function( event, ui ) {
                    $(this).removeClass('ajaxprocessing');
                },
                select: function (event, ui) {
                    event.preventDefault();
                    $('#<%= hdnEmployeeId.ClientID %>').val(ui.item.value);
                    this.value = ui.item.label;
                    return false;
                },
                focus: function (event, ui) {
                    event.preventDefault();
                    this.value = ui.item.label;
                }
            });
        });
We’re using search and response events of Jquery UI to add and remove ajaxprocessing class respectively to show loading image. In select event we’re storing value(customer Id) in hiddenfield.
In success callback function, we’ve below line:
 var data = dataJson.hasOwnProperty("d") ? dataJson.d : dataJson;
Which checks whether response is surrounded by d attribute. (Ajax response contains .d attribute, if you’re using .net 3.5+, but in asp.net 2.0, it simply returns response. For more info, check this post of Dave Ward.)

HTML:
 <asp:TextBox ID="txtEmployeeSearch" runat="server"></asp:TextBox>
 <asp:HiddenField ID="hdnEmployeeId" runat="server" />
CSS:
 .ajaxprocessing
    {
        background: url('Content/Images/ajax-loader.gif');
        background-repeat: no-repeat;
        background-position: right;
    }
Now run your page, and it should be working as shown in below image:

Jquery UI Autocomplete using pagemethods

Notes:

  • If your pagemethod is not being hit and your ajax response contains whole page, then make sure you’ve added necessary configuration entries to make pagemethod work. Please add settings mentioned here.
  • IE10 may not pass parameter for Ajax Post, and hence it may throw “Invalid web service call, missing value for parameter” error. To solve the error, you need to add below meta tag in page head:

<meta http-equiv="x-ua-compatible" content="IE=9" >

I hope it helps!

Wednesday, January 15, 2014

Jquery DataTables : Add column filter and remove global filter

Jquery DataTables plugin allows you to search through all the columns and it works pretty well. Now if you wan to add column wise filter, you need to use JQuery DataTables Column Filter plugin.

To extend Jquery DataTables with Column Filter plugin, you need to have code like below:
     <asp:Repeater ID="repUserTempAssignment" runat="server" DataSourceID="SqlDataSource1"
            EnableViewState="false">
            <HeaderTemplate>
                <table class="table-data" id="tblEmployee" style="width: 100%px;">
                    <thead>
                        <tr>
                            <th>
                                First Name
                            </th>
                            <th>
                                Last Name
                            </th>
                            <th>
                                City
                            </th>
                            <th>
                                Country
                            </th>
                        </tr>
                        <tr>
                            <th>
                                First Name
                            </th>
                            <th>
                                Last Name
                            </th>
                            <th>
                                City
                            </th>
                            <th>
                                Country
                            </th>
                        </tr>
                    </thead>
                    <tbody>
            </HeaderTemplate>
            <ItemTemplate>
                <tr>
                    <td>
                        <%# Eval("FirstName") %>
                    </td>
                    <td>
                        <%# Eval("LastName") %>
                    </td>
                    <td>
                        <%# Eval("City") %>
                    </td>
                    <td>
                        <%# Eval("Country") %>
                    </td>
                </tr>
            </ItemTemplate>
            <FooterTemplate>
                </tbody><tfoot>
                </tfoot>
                </table>
            </FooterTemplate>
        </asp:Repeater>
I’m using asp.net repeater control to bind employee list. If you notice in above code table has two rows in header. One will work as table header and one will be replaced with textboxes at runtime which will work as column filter. For that you need below script:
$('#tblEmployee').dataTable(
            {
                "bSortCellsTop": true
            }).columnFilter(
            {
                sPlaceHolder: "head:after"
            });
bSortCellsTop: This will apply sorting on first row of header.
sPlaceHolder: It will add textboxes in second row of header for every column. If you omit this, there won’t be any filters applied to columns.

After adding above code, table will look like below:

image

Now to get rid of global search filter you need to add below code in dataTable settings:

"sDom": '<"top"l>rt<"bottom"ip><"clear">'

sDom: It allow you to specify exactly where in the DOM you want DataTables to inject the various controls it adds to the page.

If you’ve not looked into documentation and if you google for quick solution, you might find may solutions stating to use bFilter, but it simply enable/disable filtering capability of dataTable. If one doesn’t want to use default styling of dataTable and want to apply his own classes, bSortClasses needs to be used. Final code would be:

$(document).ready(function () {
            $('#tblEmployee').dataTable(
            {
                "bSortCellsTop": true,
                "sDom": '<"top"l>rt<"bottom"ip><"clear">',
                "bFilter": false,
                "bSortClasses": false
            }).columnFilter(
            {
                sPlaceHolder: "head:after"
            });
        });

Using above code, global filter won’t be added to page as shown below:

image

I hope it helps!

Tuesday, December 31, 2013

iTextSharp–Add watermark to PDF

In last post iTextSharp–Add header/footer to PDF we saw how to create pdf with header/footer. To add watermark to pdf, you need to create a class that implement IPdfPageEvent as shown in below code:
 public class PdfWriterEvents : IPdfPageEvent
    {
        string watermarkText = string.Empty;

        public PdfWriterEvents(string watermark)
        {
            watermarkText = watermark;
        }
        public void OnStartPage(PdfWriter writer, Document document)
        {
            float fontSize = 80;
            float xPosition = iTextSharp.text.PageSize.A4.Width / 2;
            float yPosition = (iTextSharp.text.PageSize.A4.Height - 140f) / 2;
            float angle = 45;
            try
            {
                PdfContentByte under = writer.DirectContentUnder;
                BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
                under.BeginText();
                under.SetColorFill(BaseColor.LIGHT_GRAY);
                under.SetFontAndSize(baseFont, fontSize);
                under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
                under.EndText();
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
            }
        }
        public void OnEndPage(PdfWriter writer, Document document) { }
        public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { }
        public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) { }
        public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { }
        public void OnOpenDocument(PdfWriter writer, Document document) { }
        public void OnCloseDocument(PdfWriter writer, Document document) { }
    }
Now let’s see how to add watermark using above class:
PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, msReport);
pdfWriter.PageEvent = new PdfWriterEvents("Testing");

After using code above, it adds watermark as shown below:

clip_image001
I hope it helps!

Saturday, November 30, 2013

iTextSharp–Add header/footer to PDF

It’s a common requirement to have header/footer on PDF and it could be achieved using PageEvents in iTextSharp. It depends on the requirement, but in general header may contain:
  • Header Title
  • Header Subtitle
  • Logo
  • Page Number/Datetime
And footer may contain:
  • Page Number
  • Copyright information
Check out below function that creates sample PDF having five pages with header and footer:
private void CreatePDF()
{
    string fileName = string.Empty;

    DateTime fileCreationDatetime = DateTime.Now;

    fileName = string.Format("{0}.pdf", fileCreationDatetime.ToString(@"yyyyMMdd") + "_" + fileCreationDatetime.ToString(@"HHmmss"));

    string pdfPath = Server.MapPath(@"~\PDF\") +   fileName;

    using (FileStream msReport = new FileStream(pdfPath, FileMode.Create))
    {
        //step 1
        using (Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 140f, 10f))
        {
            try
            {
                // step 2
                PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, msReport);
                pdfWriter.PageEvent = new Common.ITextEvents();

                //open the stream 
                pdfDoc.Open();

                for (int i = 0; i < 5; i++)
                {
                    Paragraph para = new Paragraph("Hello world. Checking Header Footer", new Font(Font.FontFamily.HELVETICA, 22));

                    para.Alignment = Element.ALIGN_CENTER;

                    pdfDoc.Add(para);

                    pdfDoc.NewPage();
                }

                pdfDoc.Close();

            }
            catch (Exception ex)
            {
                //handle exception
            }

            finally
            {


            }

        }

    }
}
Below line assigns object of ItextEvent class that extends PdfPageEventHelper, which contains various methods as shown below that you can override to do various thing like add header/footer, watermark etc. In next post we’ll add watermark using similar class that extends PdfPageEventHelper.

pdfpageeventhelper

Check out the ITextEvents class that extends PdfPageEventHelper to add header/footer.

public class ITextEvents : PdfPageEventHelper
    {

        // This is the contentbyte object of the writer
        PdfContentByte cb;

        // we will put the final number of pages in a template
        PdfTemplate headerTemplate, footerTemplate;

        // this is the BaseFont we are going to use for the header / footer
        BaseFont bf = null;

        // This keeps track of the creation time
        DateTime PrintTime = DateTime.Now;


        #region Fields
        private string _header;
        #endregion

        #region Properties
        public string Header
        {
            get { return _header; }
            set { _header = value; }
        }
        #endregion


        public override void OnOpenDocument(PdfWriter writer, Document document)
        {
            try
            {
                PrintTime = DateTime.Now;
                bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
                cb = writer.DirectContent;
                headerTemplate = cb.CreateTemplate(100, 100);
                footerTemplate = cb.CreateTemplate(50, 50);
            }
            catch (DocumentException de)
            {
                //handle exception here
            }
            catch (System.IO.IOException ioe)
            {
                //handle exception here
            }
        }

        public override void OnEndPage(iTextSharp.text.pdf.PdfWriter writer, iTextSharp.text.Document document)
        {
            base.OnEndPage(writer, document);

            iTextSharp.text.Font baseFontNormal = new iTextSharp.text.Font(iTextSharp.text.Font.FontFamily.HELVETICA, 12f, iTextSharp.text.Font.NORMAL, iTextSharp.text.BaseColor.BLACK);

            iTextSharp.text.Font baseFontBig = new iTextSharp.text.Font(iTextSharp.text.Font.FontFamily.HELVETICA, 12f, iTextSharp.text.Font.BOLD, iTextSharp.text.BaseColor.BLACK);

            Phrase p1Header = new Phrase("Sample Header Here", baseFontNormal);

            //Create PdfTable object
            PdfPTable pdfTab = new PdfPTable(3);

            //We will have to create separate cells to include image logo and 2 separate strings
            //Row 1
            PdfPCell pdfCell1 = new PdfPCell();
            PdfPCell pdfCell2 = new PdfPCell(p1Header);
            PdfPCell pdfCell3 = new PdfPCell();
            String text = "Page " + writer.PageNumber + " of ";


            //Add paging to header
            {
                cb.BeginText();
                cb.SetFontAndSize(bf, 12);
                cb.SetTextMatrix(document.PageSize.GetRight(200), document.PageSize.GetTop(45));
                cb.ShowText(text);
                cb.EndText();
                float len = bf.GetWidthPoint(text, 12);
                //Adds "12" in Page 1 of 12
                cb.AddTemplate(headerTemplate, document.PageSize.GetRight(200) + len, document.PageSize.GetTop(45));
            }
            //Add paging to footer
            {
                cb.BeginText();
                cb.SetFontAndSize(bf, 12);
                cb.SetTextMatrix(document.PageSize.GetRight(180), document.PageSize.GetBottom(30));
                cb.ShowText(text);
                cb.EndText();
                float len = bf.GetWidthPoint(text, 12);
                cb.AddTemplate(footerTemplate, document.PageSize.GetRight(180) + len, document.PageSize.GetBottom(30));
            }
            //Row 2
            PdfPCell pdfCell4 = new PdfPCell(new Phrase("Sub Header Description", baseFontNormal));
            //Row 3


            PdfPCell pdfCell5 = new PdfPCell(new Phrase("Date:" + PrintTime.ToShortDateString(), baseFontBig));
            PdfPCell pdfCell6 = new PdfPCell();
            PdfPCell pdfCell7 = new PdfPCell(new Phrase("TIME:" + string.Format("{0:t}", DateTime.Now), baseFontBig));


            //set the alignment of all three cells and set border to 0
            pdfCell1.HorizontalAlignment = Element.ALIGN_CENTER;
            pdfCell2.HorizontalAlignment = Element.ALIGN_CENTER;
            pdfCell3.HorizontalAlignment = Element.ALIGN_CENTER;
            pdfCell4.HorizontalAlignment = Element.ALIGN_CENTER;
            pdfCell5.HorizontalAlignment = Element.ALIGN_CENTER;
            pdfCell6.HorizontalAlignment = Element.ALIGN_CENTER;
            pdfCell7.HorizontalAlignment = Element.ALIGN_CENTER;


            pdfCell2.VerticalAlignment = Element.ALIGN_BOTTOM;
            pdfCell3.VerticalAlignment = Element.ALIGN_MIDDLE;
            pdfCell4.VerticalAlignment = Element.ALIGN_TOP;
            pdfCell5.VerticalAlignment = Element.ALIGN_MIDDLE;
            pdfCell6.VerticalAlignment = Element.ALIGN_MIDDLE;
            pdfCell7.VerticalAlignment = Element.ALIGN_MIDDLE;


            pdfCell4.Colspan = 3;



            pdfCell1.Border = 0;
            pdfCell2.Border = 0;
            pdfCell3.Border = 0;
            pdfCell4.Border = 0;
            pdfCell5.Border = 0;
            pdfCell6.Border = 0;
            pdfCell7.Border = 0;


            //add all three cells into PdfTable
            pdfTab.AddCell(pdfCell1);
            pdfTab.AddCell(pdfCell2);
            pdfTab.AddCell(pdfCell3);
            pdfTab.AddCell(pdfCell4);
            pdfTab.AddCell(pdfCell5);
            pdfTab.AddCell(pdfCell6);
            pdfTab.AddCell(pdfCell7);

            pdfTab.TotalWidth = document.PageSize.Width - 80f;
            pdfTab.WidthPercentage = 70;
            


            //call WriteSelectedRows of PdfTable. This writes rows from PdfWriter in PdfTable
            //first param is start row. -1 indicates there is no end row and all the rows to be included to write
            //Third and fourth param is x and y position to start writing
            pdfTab.WriteSelectedRows(0, -1, 40, document.PageSize.Height - 30, writer.DirectContent);
            
            //Move the pointer and draw line to separate header section from rest of page
            cb.MoveTo(40, document.PageSize.Height - 100);
            cb.LineTo(document.PageSize.Width - 40, document.PageSize.Height - 100);
            cb.Stroke();

            //Move the pointer and draw line to separate footer section from rest of page
            cb.MoveTo(40, document.PageSize.GetBottom(50));
            cb.LineTo(document.PageSize.Width - 40, document.PageSize.GetBottom(50));
            cb.Stroke();
        }

        public override void OnCloseDocument(PdfWriter writer, Document document)
        {
            base.OnCloseDocument(writer, document);

            headerTemplate.BeginText();
            headerTemplate.SetFontAndSize(bf, 12);
            headerTemplate.SetTextMatrix(0, 0);
            headerTemplate.ShowText((writer.PageNumber - 1).ToString());
            headerTemplate.EndText();

            footerTemplate.BeginText();
            footerTemplate.SetFontAndSize(bf, 12);
            footerTemplate.SetTextMatrix(0, 0);
            footerTemplate.ShowText((writer.PageNumber - 1).ToString());
            footerTemplate.EndText();


        }
    }

As you can see that above class has Header property that you might want to use if you want your header title to be assigned dynamic. Add as many properties as you want, to display dynamic values in your header/footer.

It will generate sample PDF that will look like below:

SamplePDF

I hope it helps!

Monday, September 30, 2013

iTextSharp–Print PDF

To print html page, we use
window.print();
but for PDF same can not be used as it won’t work. However iTextSharp provides a way to print PDF on client side with AddJavaScript method of PdfWriter.

Check out below code:

private void CreatePDF()
    {
        string fileName = string.Empty;

        DateTime fileCreationDatetime = DateTime.Now;

        fileName = string.Format("{0}.pdf", fileCreationDatetime.ToString(@"yyyyMMdd") + "_" + fileCreationDatetime.ToString(@"HHmmss"));

        string pdfPath = @"E:\PDFs\" + fileName;

        using (FileStream msReport = new FileStream(pdfPath, FileMode.Create))
        {
            //step 1
            using (Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 100f, 10f))
            {
                try
                {
                    // step 2
                    PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, msReport);

                    //open the stream 
                    pdfDoc.Open();

                    Phrase phrase1 = new Phrase("Hello world. Checking Print Functionality");

                    pdfDoc.Add(phrase1);

                    pdfWriter.AddJavaScript("this.print();");

                    pdfDoc.Close();

                }
                catch (Exception ex)
                {
                    //handle exception
                }

                finally
                {


                }

            }

        }
    }
It won’t print the PDF directly but will open print dialog as soon as you open the PDF. One can choose one of the listed printer and print it. There won’t be any print preview. On web page to simulate the print functionality, one can assign pdf path to Iframe which will be hidden on page.

<iframe id="pdfViewer"  runat="server" style="display:none;" />

As you can see there’s no path assigned to src attribute in HTML but in code behind as shown below:
pdfViewer.Attributes["src"]=  ResolveClientUrl(string.Format("~/PDF/{0}",fileName));
It won’t display the PDF in browser but will ask user to print the PDF (without preview). Both Firefox and Chrome use in built pdf viewer.

Known Issues:
  • It will not display PDF in IE and Opera but download it if no pdf viewer is installed on machine and respective add-on is not installed on both the browsers. For opera 15 onwards, you can install this add-on which is based on Mozilla’s pdf.js.

  • If pdf viewer has a setting to view pdf in secure mode and it is enabled, it will not run javascript and gives warning.
I hope it helps!

Sunday, September 22, 2013

Copy as path in Windows 7/8

Many times we want to copy complete file path and we do that in two steps:
  • Copy path of the folder/drive in which file resides
  • Copy Filename
and use combination of it to solve the purpose.

One simple solution exists from win 7 onwards is to select file and press Shift key + Right Mouse click. Context menu will have an option “Copy as path”, select it and you’re done.

Saturday, May 11, 2013

Jquery Multiselect plugin retain selection on postback in Asp.net

One can use Jquery Mutiselect plugin to allow user to select multiple items from the options available in dropdown. When we click on dropdown it looks something like below :

image
Check out the demo page of plugin here

The problem with the plugin is that it won’t remember the user selection and value will be lost on postback. For that you can store the selected valued delimited by comma in hidden field and restore the value on page load.

Now let’s look at the code to bind the dropdown with plugin and retaining value on postback.
Make sure you’ve necessary scripts and css files added in your page:
  <link href="CSS/Jquery.multiselect.css" rel="stylesheet" type="text/css" />
  <link href="CSS/Jquery.multiselect.filter.css" rel="stylesheet" type="text/css" />
  <link href="CSS/jquery-ui.css" rel="stylesheet" type="text/css" />
  <script src="http://code.jquery.com/jquery-1.9.1.min.js" type="text/javascript"></script>
  <script type="text/javascript" src="Js/jquery-ui.min.js"></script>
  <script type="text/javascript" src="Js/Jquery.multiselect.js"></script>
  <script src="JS/Jquery.multiselect.filter.js" type="text/javascript"></script>
HTML:
<asp:DropDownList ID="ddlUsers" runat="server" multiple="multiple">
 </asp:DropDownList>
 <asp:HiddenField ID="hdnUsers" runat="server" />
 <asp:Button ID="btnSearch" runat="server" Text="Search"  onclick="btnSearch_Click" />
Client Script:
<script type="text/javascript">
        $('#<%= ddlUsers.ClientID %>').multiselect({
            //to remove check/uncheck all option
            header: '',
            //store user selected value in hidden field
            close: function (event, ui) {
                var array_of_SalesGroup = $('#<%= ddlUsers.ClientID %>').multiselect("getChecked").map(function () {
                    return this.value;
                }).get();
                $('#<%= hdnUsers.ClientID %>').val(array_of_SalesGroup);
            }
        }).multiselectfilter(); //adds filter to dropdown
    </script>

Now to check checkboxes marked by user we need to add selected attribute to original select (dropdown) options and call refresh method of the plugin. You can do it as shown in below scripts:

        $(document).ready(function () {
            if ($('#<%= hdnUsers.ClientID %>').val() != '') {
                var selected = $('#<%= hdnUsers.ClientID %>').val().split(",");
                $("#<%=ddlUsers.ClientID%> > option").each(function () {
                    if ($.inArray(this.value, selected) > -1) {
                            $(this).attr("selected", "selected");
                    }
                });
               $("#<%=ddlUsers.ClientID%>").multiselect('refresh');
            }
        });

I hope it helps!

Sunday, April 14, 2013

Visual Studio Macros and Build Events

Visual studio has a nifty feature called Post/Pre Build events. These are used to include extra Dos commands and Macros and execute them before or after build.

You can open it using project properties and it will open dialog as shown below:

BuildEvent Dialog

For post-build events you can define when to run commands included as shown in below snap:

Post-build events

You can click the respective Edit build buttons and it will open popup as shown below:

Build Popup

By clicking the Macro button it will open macro listing and their respective value.

By using Macros and dos command you can copy files from one location to another and run batch files and so on. In my current project I do have below command to copy xml file and email templates from common code project to my solution directory:

RD "$(SolutionDir)WebAdmin\XML"
MD "$(SolutionDir)WebAdmin\XML"
COPY "$(ProjectDir)XML" "$(SolutionDir)WebAdmin\XML"

RD "$(SolutionDir)WebAdmin\EmailTemplates"
MD "$(SolutionDir)WebAdmin\EmailTemplates"
COPY "$(ProjectDir)EmailTemplates" "$(SolutionDir)WebAdmin\EmailTemplates"

In above code, $(SolutionDir) and $(ProjectDir) are macro names. Macros are non case-sensitive. Check out this link that shows macros along with their descriptions.

Use this nifty feature and automate your tasks Smile

Tuesday, April 2, 2013

Reset .net validation controls client side

On many occasions we provide form reset functionality and people handle it client side or server side. In general we validate input from the user and show proper validation message. But sometimes it happens that user has entered wrong input and thus it will display validation messages. Now if you have handled form reset functionality client side, you must reset all validation message as well. You can do it as shown in below code:

Javascript:
  function ResetForm() {
            $('input[type=text], textarea').val('');
            Page_ClientValidateReset();
            return false;
        }

        function Page_ClientValidateReset() {
            if (typeof (Page_Validators) != "undefined") {
                for (var i = 0; i < Page_Validators.length; i++) {
                    var validator = Page_Validators[i];
                    validator.isvalid = true;
                    ValidatorUpdateDisplay(validator);
                }
            }
        }

HTML:
 <asp:Button ID="btnReset" runat="server" Text="Reset" OnClientClick="return ResetForm();" />

Now let’s understand what JavaScript properties and functions are.

Page_Validators : This is an array containing all of the validators on the page.

isvalid: This is a property on each client validator indicating whether it is currently valid.

ValidatorUpdateDisplay: Inbuilt function which checks whether validation control’s display property is set to dynamic, if yes then it will set css style of that validator to none.

So basically it loops through all the validators, set isvalid property to true and set validators’s visibility to none. Here we're not using form reset funtction to clear form fields as Reset doesn't clear a form, it simply sets the form value to their default which may or may not be blank. 

I hope it helps!

Sunday, March 17, 2013

iTextSharp - Add Image from base64 string

Itexhsharp is one of the popular third party component to create PDF with .Net framework.

If you're using Itextsharp for the very first time, I would suggest you to go through Mike's series on Itextsharp that helps you to get started and here is the article from the series that shows different ways to add images to  Itextsharp.

To add image from base64 string, you first need to convert base64 string in to bytes array and then you can call GetInstance method of Itextsharp Image which accepts bytes array.

Let’s say we want to add below image to PDF:

Koala

If you’ve doubt whether base64string for any image is incomplete/corrupt, you can use imagetobase64 converter and verify generated string. Check out below sample code to convert base64string to bytes array and add it in to PDF.

private void CreatePDF()
    {
     //path you want to store PDF 
        string pdfPath = string.Format(@"E:\PDF\{0}.pdf", DateTime.Now.ToString("yyyy-MM-dd hhmmss"));

        using (FileStream msReport = new FileStream(pdfPath, FileMode.Create))
        {
            //step 1
            using (Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 140f, 30f))
            {

                // step 2
                PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, msReport);

                //open the stream 
                pdfDoc.Open();

                iTextSharp.text.Image gif = null;

                string base64string = "yourbase 64 string";
                try
                {
                    //  Convert base64string to bytes array
                    Byte[] bytes = Convert.FromBase64String(base64string);
                    gif = iTextSharp.text.Image.GetInstance(bytes);

                }
                catch (DocumentException dex)
                {
                   //log exception here
                }
                catch (IOException ioex)
                {
                    //log exception here
                }
                gif.Alignment = iTextSharp.text.Image.ALIGN_LEFT;
                gif.Border = iTextSharp.text.Rectangle.NO_BORDER;
                gif.BorderColor = iTextSharp.text.BaseColor.WHITE;
                gif.ScaleToFit(170f, 100f);
              
                pdfDoc.Add(gif);

                pdfDoc.Close();

            }
        }
    }
If base64string is not valid, it may throw error and if you want to continue execution you want to assign gif object some value in Catch block. Sample code will create PDF in portrait mode but if you want PDF be in landscape mode, use Rotate method as shown below.This is sample code and you can alter it as per your need.
Document pdfDoc = new Document(PageSize.A4.Rotate(), 10f, 10f, 140f, 30f);
Generated PDF will have image as shown below:

clip_image001
I hope it helps!