Insights on Software Development and Architecture

ErionPC's weblog on software development

Category Archives: ASP.NET

JQuery calendar

I like using the Ajax Control Toolkit in the ASP.NET websites I maintain and I had been using a CalendarExtender for a while to pop up a calendar from watermarked textboxes.
I found out that with the new relase of Mozilla Firefox (4.0.1) my ajax calendar stopped working. I didn’t particularly like the fact that it sent postbacks to the server on date-change anyway, so I thought it was time to look for something different, completely client-side and javascript-based.
This is how I discovered Any+Time™. It’s a Date/time picker based on JQuery which I found was easy to integrate in my projects and flexible enough to be customized and extended. The source code is available so it can be adapted to many different contexts.

This is how it looks in its basic form

date picker

It can be adapted to show just the date picker or just the time picker, or both. It also supports localization. The only prerequiste required is the jquery framework, even in its minimal version.

The Date Picker is composed by the following files:

  • anytime.js (main js file)
  • anytimetz.js (optional: to support localization)
  • anytime.css (presentation)

After including the above files and the jquery file in the HTML you can use the following code to bind Date pickers to your textboxes:

function resetDatePickers() {
    $(document.getElementById("<%= this.myTextBox.ClientID %>")).AnyTime_noPicker();
    $(document.getElementById("<%= this.myTextBox.ClientID %>")).AnyTime_picker({ format: "%d/%m/%Y", labelTitle: "Seleziona la data", labelDayOfMonth: "Giorno", labelMonth: "Mese", labelYear: "Anno", dayAbbreviations: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], monthAbbreviations: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"], firstDOW: 1 }).removeAttr("disabled");
}

It would be a good idea to call this function after every page postback (ex. inside the Page_Load method in ASP.NET). After this, a click on this.myTextBox will popup a date picker which will change the Text property on any click, obviously without posting back to the server. In the above example I use the Italian localization.

I have also called the function removeAttr("disabled"), because I want to be able to edit the text of my textbox manually and this isn’t possible unless you call this function. I extended anytime.js so that the date/time entered in the textbox is cleared after a keyboard-del or backspace. This is useful because otherwise there is no other way to clear the textbox if you don’t want to enter anything and you’ve just clicked on it.

Another thing to notice is that I called the function AnyTime_noPicker() before calling AnyTime_picker(). I had to do this because if the page posts back and you try using the datepicker inside an ajax update panel without reloading the page, it doesn’t work anymore because the datepicker object doesn’t get destroyed on a postback which partially updates the page.  AnyTime_noPicker() destroys any existing instances of the date picker and makes it possible to re-bind it to the textbox after a postback. The author was kind enough to help me get to this solution very quickly.

This is what I’ve added to anytime.js to clear the text on Delete.

key: function(event) {
   if ( key == /* ... */ ) { /* ... */ }
   // ....
   // My code
   else if ((key == 8) || (key == 27) || (key == 46)) // backspace, escape or delete
   {
      this.inp[0].value = "";
      this.dismiss(null);
   }
   else
      this.showPkr(null);
   // ....
}

For any further details, refer to the original documentation on http://www.ama3.com/anytime/.

This is my extended version of anytime.js https://erionpc.files.wordpress.com/2011/05/anytime.odt. You need to rename anytime.odt to anytime.js after download (wordpress work around).

Advertisements

A SOA approach to dynamic DOCX-PDF report generation – Part 2

Introduction

Having already achieved automatized MsOffice-independent Docx report generation in a client-server architecture following the approach explained in my previous article “A SOA approach to dynamic DOCX-PDF report generation – part 1”, now we’ll look into automatically printing those docx files into PDF from managed code and transmitting the PDF bytes through HTTP.

The PDF conversion is based on a free BullZip PDF product, which offers a free, full-featured, programmable and very well documented PDF printer that can print any file to PDF, including Docx files.

Needless to say that PDF is probably the most used document exchange format between different platforms, therefore the need to have PDF reports of some kind of data is common to most data-centric applications.

1. Installing the PDF Printer

The first thing to do is to download and install BullZipPdf. It will create a PDF printer in the system and it will include the help file in the installation directory. Read through the help file to learn how to use the Bullzip.PdfWriter namespace.

2. Adding the PDF Conversion to an Existing Visual Studio Solution

First of all, we need to import the package into the solution. As sweet as it can be, we can find the package in the GAC, so just go on Add Reference -> .NET and find BullZip Pdf Writer. This will add the Bullzip.PDFWriter assembly to the solution, which exposes its classes and methods under the Bullzip.PDFWriter namespace. The next thing to do is configuring the PDF printer. This can be achieved through a .ini file, but I’m not going to enter into this, you can read a lot about it in the Bullzip documentation. The printer settings are managed by a class called PdfSettings, whilst the PDF creation methods are in a class called PdfUtils. Everything is ready now, we can already start converting to PDF!

3. Converting to PDF

Here’s what the test application does:

  1. It includes some docx templates with sample data in a templates directory
  2. Generates customized docx reports based on the docx templates and some XML-serialized Business-Logic data whose structure corresponds to the custom XML parts in the docx templates
  3. Saves the docx reports into a temporary directory
  4. Prints the docx reports into PDF
  5. Sends the PDF bytes through HTTP
  6. Destroys the docx and PDF files

This PrintToPdf method loads the printer settings from an “.ini” file, it “reads” a docx file from a temporary directory, creates the PDF file and then destroys the original docx and PDF.

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Configuration;
using System.ServiceModel;
using Bullzip.PdfWriter;

namespace DocxGenerator.SL.WCF
{
    public class PdfMaker
    {
        internal static byte[] PrintToPdf(string appFolder, string tempDocxFileName)
        {
            try
            {
                string tempFolder = appFolder + @"\temp";
                string tempDocxFilePath = tempFolder + @"\" + tempDocxFileName;

                PdfSettings pdfSettings = new PdfSettings();
                pdfSettings.PrinterName = ConfigurationManager.AppSettings["PdfPrinter"];

                string settingsFile = pdfSettings.GetSettingsFilePath(PdfSettingsFileType.Settings);
                pdfSettings.LoadSettings(appFolder + @"\App_Data\printerSettings.ini");
                pdfSettings.SetValue("Output", tempFolder + @"\&lt;docname&gt;.pdf");
                pdfSettings.WriteSettings(settingsFile);

                PdfUtil.PrintFile(tempDocxFilePath, pdfSettings.PrinterName);
                string tempPdfFilePath = tempFolder + @"\Microsoft Word - " + tempDocxFileName + ".pdf";

                bool fileCreated = false;
                while (!fileCreated)
                {
                    fileCreated = PdfUtil.WaitForFile(tempPdfFilePath, 1000);
                }

                byte[] pdfBytes = File.ReadAllBytes(tempPdfFilePath);

                File.Delete(tempDocxFilePath);
                File.Delete(tempPdfFilePath);

                return pdfBytes;
            }
            catch (Exception ex)
            {
                throw new FaultException("WCF ERROR!\r\n" + ex.Message);
            }
        }
    }

Points of Interest

The scope of this article is limited to a mere illustration of what can be achieved through this architecture. With a little bit of head-scratching, you can extend this and make it into a PDF conversion server (did anyone think of a free version Adobe Distiller ???), a scheduled batch printer, an archiving system, etc.
If integrated in the SOA report generation solution mentioned above this permits you to get rid of the docx files and use PDF as the document exchange format.

Have fun!

History

The previous (must-read to understand the SOA integration concepts) article that brought to this: “A SOA approach to dynamic DOCX-PDF report generation – part 1”

Click here to view this article on CodeProject.

Click here to download the test application’s source code.

ASP.NET – Get Client Screen Resolution

No matter ASP.NET offers the “Page.Request.Browser.ScreenPixelsWidth” and “Page.Request.Browser.ScreenPixelsHeight” methods, these don’t help when you need to obtain the client’s screen resolution on the server side. They give false results. I think the best way to do this is through JavaScript. Here’s an example:

C#


<%if (!this.IsPostBack)
{%>
<script language="javascript" type="text/javascript">
var rowURL = window.location.href;
var screenWidth = window.screen.availWidth;
if (rowURL.indexOf("screen_width") == -1)
window.location.href = window.location.href + "?screen_width=" + screenWidth;
</script>
<%}%>

This script just needs to be pasted inside the <body> tag of the page. The script basically checks whether the query string contains the “screen_width” parameter. If it doesn’t, it appends the “screen_width” parameter to the query string and refreshes the page. Server-side, you just need to retreive the value of the “screen_width” Request parameter.