Thursday, April 30, 2015

ASP.Net C# Override Render event to get and manipulate page content before it's rendered

Here's an easy way to intercept the content that an ASP.Net page is going to render and send back to the browser.
   protected override void Render(HtmlTextWriter Writer)  
   {  
      // variables
      string Content = string.Empty;  
   
      // get the fully rendered content of this page so we can do some additional translations if necessary  
      using (StringWriter StringWriter = new StringWriter())  
      {  
         using (HtmlTextWriter HtmlTextWriter = new HtmlTextWriter(StringWriter))  
         {  
            // render current page content to temp writer  
            base.Render(HtmlTextWriter);  
   
            // close writer  
            HtmlTextWriter.Close();  
   
            // get content  
            Content = StringWriter.ToString();  

            // DO SOMETHING WITH THE CONTENT
         }  
      }  

      // render content
      Writer.Write(Content);
   }

Using the override keyword for the Render event lets you get and manipulate the content before it's rendered. Using the example above, the Content string variable will hold the content that will be rendered back to the browser. Now you could manipulate the content before it is rendered. A good example would be some kind of string replacement. Say for example you want to define a custom pattern and use it through your pages, content, resource files, and such. In that case you could use the following code where the DO SOMETHING WITH THE CONTENT comment is.

   // look for <translate></translate> pattern so we can translate them on the fly  
   foreach (Match m in Regex.Matches(Content, @"<translate>(.*?)</translate>", RegexOptions.IgnoreCase))  
   {  
      // get the pattern
      // e.g. <translate>lblFirstName</translate>   
      string Pattern = m.Value.ToLower();

      // remove the pattern so you are left with just the ID
      // e.g. lblFirstName
      string ID = Pattern.ReplaceValue("<translate>", string.Empty).ReplaceValue("</translate>", string.Empty);

      // do some kind of lookup with the ID
      // e.g. This could be something as simple as getting a value from a resource file for a specific language
      string Translation = "Lookup value for the current ID";
   
      // do a string replacement on the Content variable replacing the pattern with your translation
      Content = Content.ReplaceValue(Pattern, Translation);
   }  

The above code is dependent upon a simple ReplaceValue extension method:
   public static string ReplaceValue(this string Value, string Pattern, string Replacement)  
   {  
      return Regex.Replace(Value, Regex.Escape(Pattern), Replacement, RegexOptions.IgnoreCase);  
   }  

This is a simplified version of a solution that I use regularly, and it works really well. This idea sort of evolved over time to handle more complex scenarios were you don't always have the luxury of using simpler techniques. For example, at first glance you might just think about using a simple resource file on your ASPX page. That can work for a lot of situations. Another thought would be to use a custom user control where you can define a "key" attribute and do your resource lookup within the user control. Again, a very good solution that can cover most situations; however, this particular pattern replacement technique allows you to handle other situations where you have data that is not directly within your ASPX page, for example, other resource files, or data from a database, etc.

The pattern can be used literally anywhere on the page. Whether it's in your JavaScript, HTML, or even part of a more complex ASP.Net web control, for example:

JavaScript:
 alert("<translate>FirstNameRequired</translate>");  

HTML:
 <div><translate>lblDisclaimer</translate></div>  

GridView:
 <asp:BoundField DataField="FirstName" HeaderText="<translate>lblFirstName</translate>" HtmlEncode="false" />  

How it's used is really limitless, and for language driven websites, it can be a really nice way to make things more generic and flexible.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

Wednesday, April 29, 2015

ASP.Net C# Creating an AutoFocus property in your Master Page

Recently I posted about Accessing Master Page Controls from Content Pages. This same technique can be used to create an AutoFocus property that you can use generically from your content pages.

Base.Master
   <!-- auto focus -->  
   <asp:PlaceHolder ID="pnlAutoFocus" runat="server">  
     <script language="javascript" type="text/javascript">  
       $(document).ready(function () {  
         $(':input:enabled:visible:not(.noautofocus):first').focus();  
       });  
     </script>  
   </asp:PlaceHolder>  

Notice we're using jQuery and we're targeting the first input control that is enabled, visible, and does not have a noautofocus class. The noautofocus class allows us to still use the AutoFocus feature on a page, but exclude certain controls if necessary, for example:
 <asp:DropDownList ID="ddlState" CssClass="form-control noautofocus" ClientIDMode="Static" runat="server" />  

Next we expose the AutoFocus property in the Base.Master code-behind.

Base.Master.cs
     public bool AutoFocus  
     {  
       get  
       {  
         return pnlAutoFocus.Visible;  
       }  
       set  
       {  
         pnlAutoFocus.Visible = value;  
       }  
     }  

Now you can access the AutoFocus property from your content pages like so.

Test.aspx
  <%@ Page Language="C#" MasterPageFile="~/Base.Master" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="Sandbox.Web.Test" %>   
  <%@ MasterType VirtualPath="~/Base.master" %>  

Test.aspx.cs
   private void Page_PreLoad(object sender, System.EventArgs e)  
   {  
      // auto focus  
      Master.AutoFocus = true;  
   }  

JSFiddle:
http://jsfiddle.net/mpavey/4r1ttfgy/

Why use this approach? Well for me it allows me to keep things generic. Sure you could manually set the focus of the appropriate web control from page to page in its respective code-behind (or with JavaScript); however, this approach lets you just build the form and basically will focus things for you automatically, and you only have to handle exceptions, which can be accomplished with the noautofocus class or by disabling the AutoFocus property for the entire page.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

ASP.Net MVC Using a Base Controller to access the current HTTP request

I'm a big fan of using "base" classes. If I'm working with an ASP.Net web project, I have a BasePage class that all content pages inherit from. If I'm working with a model layer, I have a BaseModel class that all model objects inherit from. If I'm working with a data layer, I have a BaseDB class that all data layer classes inherit from. So when it comes to MVC and dealing with controllers it's no different for MVC controllers or API controllers.

In this example I define a BaseController class that inherits from System.Web.Http.ApiController. This example also shows you how you can access the System.Web.HttpRequest object for the current HTTP request to access information like QueryString, IP Address, URL information, UserAgent information, browser information, and more.
 Public Class BaseController  
   Inherits System.Web.Http.ApiController  

Then you can expose whatever properties or methods you want in your BaseController class.
   Public ReadOnly Property QueryString() As String  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.QueryString.ToString  
       Catch ex As Exception  
         Return String.Empty  
       End Try  
     End Get  
   End Property  
   
   Public ReadOnly Property IPAddress() As String  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.UserHostAddress  
       Catch ex As Exception  
         Return String.Empty  
       End Try  
     End Get  
   End Property  
   
   Public ReadOnly Property UrlRequest() As String  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.Url.AbsoluteUri  
       Catch ex As Exception  
         Return String.Empty  
       End Try  
     End Get  
   End Property  
   
   Public ReadOnly Property RawUrl() As String  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.RawUrl  
       Catch ex As Exception  
         Return String.Empty  
       End Try  
     End Get  
   End Property  
   
   Public ReadOnly Property UrlReferrer() As String  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.UrlReferrer.AbsoluteUri  
       Catch ex As Exception  
         Return String.Empty  
       End Try  
     End Get  
   End Property  
   
   Public ReadOnly Property UserAgent() As String  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.UserAgent  
       Catch ex As Exception  
         Return String.Empty  
       End Try  
     End Get  
   End Property  
   
   Public ReadOnly Property Crawler() As Boolean  
     Get  
       Try  
         Return DirectCast(Request.Properties("MS_HttpContext"), HttpContextBase).Request.Browser.Crawler  
       Catch ex As Exception  
         Return False  
       End Try  
     End Get  
   End Property  

This same concept also works for System.Web.Mvc.Controller.
 Public Class BaseController  
   Inherits System.Web.Mvc.Controller  

In the case of System.Web.Mvc.Controller, we can access the current HTTP request directly from the Request object, without needing to look at MS_HttpContext.
     Public ReadOnly Property QueryString() As String  
       Get  
         Try  
           Return Request.QueryString.ToString  
         Catch ex As Exception  
           Return String.Empty  
         End Try  
       End Get  
     End Property  
   
     Public ReadOnly Property IPAddress() As String  
       Get  
         Try  
           Return Request.UserHostAddress  
         Catch ex As Exception  
           Return String.Empty  
         End Try  
       End Get  
     End Property  
   
     Public ReadOnly Property UrlRequest() As String  
       Get  
         Try  
           Return Request.Url.AbsoluteUri  
         Catch ex As Exception  
           Return String.Empty  
         End Try  
       End Get  
     End Property  
   
     Public ReadOnly Property RawUrl() As String  
       Get  
         Try  
           Return Request.RawUrl  
         Catch ex As Exception  
           Return String.Empty  
         End Try  
       End Get  
     End Property  
   
     Public ReadOnly Property UrlReferrer() As String  
       Get  
         Try  
           Return Request.UrlReferrer.AbsoluteUri  
         Catch ex As Exception  
           Return String.Empty  
         End Try  
       End Get  
     End Property  
   
     Public ReadOnly Property UserAgent() As String  
       Get  
         Try  
           Return Request.UserAgent  
         Catch ex As Exception  
           Return String.Empty  
         End Try  
       End Get  
     End Property  
   
     Public ReadOnly Property Crawler() As Boolean  
       Get  
         Try  
           Return Request.Browser.Crawler  
         Catch ex As Exception  
           Return False  
         End Try  
       End Get  
     End Property  

Now when you create your individual Web or API controllers, you can inherit from the BaseController and access the exposed properties or methods easily.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

ASP.Net Intercept postback event

Ever needed to intercept the ASP.Net postback event from the client-side using javascript so you can override or customize something? Here's a simple way to do it.

Code:
   ...  
   
   <!-- intercept postback event -->  
   <script language="javascript" type="text/javascript">  
     // get reference to original postback method before we override it  
     var __doPostBackOriginal = __doPostBack;  
   
     // override  
     __doPostBack = function (eventTarget, eventArgument) {  
       // show progress modal  
       ShowProgress();  
   
       // postback  
       __doPostBackOriginal.call(this, eventTarget, eventArgument);  
     }  
   </script>  
 </body>  
 </html>  

First you need to get a reference to the original __doPostBack event and save it in the __doPostBackOriginal variable. This is necessary so you can trigger it later.

Once you have the reference to the original postback event you can override __doPostBack. This is where you'll want to put your custom code. In this example, I call a ShowProgress() method. This is where I trigger a custom bootstrap modal so for any postback you see a progress spinner.

After you've added your custom override you call __doPostBackOriginal.call(this, eventTarget, eventArgument); to trigger the original postback event.

It's worth noting that the __doPostBack javascript event is only rendered when it is needed. It will be rendered by ASP.Net whenever you add a web server control to your form, with the exception of Button and ImageButton controls. For buttons you will need to add your own OnClientClick to handle client-side events.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

Tuesday, April 28, 2015

ASP.Net C# Accessing Master Page Controls from Content Pages

This is a pretty simple task, but one I use frequently. Often times I have controls in my master page that I want to access or somehow control differently from page to page. So here is a very simple example of how to accomplish that.

Base.Master
   <asp:PlaceHolder id="pnlDoNotIndex" visible="false" runat="server">  
     <meta name="robots" content="noindex" />  
   </asp:PlaceHolder>  

Base.Master.cs
     public bool DoNotIndex
     {  
       get { return pnlDoNotIndex.Visible; }  
       set { pnlDoNotIndex.Visible = value; }  
     }  

Test.aspx
 <%@ Page Language="C#" MasterPageFile="~/Base.Master" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="Sandbox.Web.Test" %>  
 <%@ MasterType VirtualPath="~/Base.master" %>  

Test.aspx.cs
     private void Page_PreInit(object sender, System.EventArgs e)  
     {  
       // do not index
       Master.DoNotIndex = false;  
     }  

The MasterType declaration provides a way to create a strongly typed reference to the ASP.NET master page when the master page is accessed from the Master property. That allows us to just say Master.DoNotIndex to get/set the publicly exposed property.

Like I said, this example is as simple as it gets, but it allows you to make your master page more generic and only expose the pieces you need from page to page.

Lastly, the reason I prefer an approach like this for the "robots" tag is because it allows me to standardize on a single tag throughout the entire web application to indicate whether or not the page is crawlable or not. An alternative would be to use an asp:ContentPlaceHolder in your master page, and then set the content for it from page to page as needed. I'm not opposed to that solution, and in fact I use that approach quite often for various things, but it really depends on what you are trying to expose and how generic you are trying to keep it. In this case I wanted a single uniform "robots" tag to be defined to not allow a page to be indexed, and if that "robots" tag ever needed to change, I could do that in one place, opposed to each individual content page that had defined it separately.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

ASP.NET C# Using Request.Url and Request.ApplicationPath to get your web application's Base Url

If you ever need to get the base domain and application path of your web application, here is a BasePage property that I use regularly.

Code:
     public string BaseUrl  
     {  
       get  
       {  
         // variables  
         string Authority = Request.Url.GetLeftPart(UriPartial.Authority).TrimStart('/').TrimEnd('/');  
         string ApplicationPath = Request.ApplicationPath.TrimStart('/').TrimEnd('/');  
   
         // add trailing slashes if necessary  
         if (Authority.Length > 0)  
         {  
           Authority += "/";  
         }  
   
         if (ApplicationPath.Length > 0)  
         {  
           ApplicationPath += "/";  
         }  
   
         // return  
         return string.Format("{0}{1}", Authority, ApplicationPath);  
       }  
     }  

I like this technique because whether you are using a virtual directory or not, and whether you are using http or https, you can get the base url easily if you need to build a fully-qualified-url withing your application (e.g. sharing a link, sending an email with a link back, etc).

Example output for a top-level site:
http://dev.sandbox.com/

Example output for a virtual directory:
http://dev.sandbox.com/qa/

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

Monday, April 27, 2015

SQL dm_exec_describe_first_result_set dynamic management function

Here's how to call the dm_exec_describe_first_result_set dynamic management function.

This works for SQL 2012 through current version.

SELECT  *
FROM  sys.dm_exec_describe_first_result_set('StoredProcedureName', NULL, 1)

This dynamic management function takes a Transact-SQL statement as a parameter and describes the metadata of the first result set for the statement.

This is a really useful function if you ever need to dynamically figure out the metadata that will be returned for a given stored procedure. For example, if you just need to figure out the column name and data type of each column in the result set, you can do the following:

SELECT  'Property' = name,
'SqlType' = system_type_name
FROM sys.dm_exec_describe_first_result_set('StoredProcedureName', NULL, 1)

For specific syntax, arguments, and what data is returned visit MSDN.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

jQuery - Populating presidents dropdown list in XML format

Building off of my last post on how to retrieve XML data using jQuery and AJAX, here's an example of how to consume the XML data. In this example we'll iterate through a sub-set of U.S. Presidents data from a free data service called MySafeInfo. The presidents data is in a node named p and it has attributes for the president's ID (id), name (nm), political party (pp), and term (tm).



This example relies on jQuery and uses mysafeinfo.com to retrieve U.S. Presidents data in XML format. MySafeInfo is a free service we offer to software developers to provide test data in a simple, flexible manner, in a variety of formats, including XML, JSON, JSONP, CSV, and more.

Friday, April 24, 2015

jQuery - Retrieving list of presidents in XML format using AJAX

Here's a quick example of how to retrieve XML data from a 3rd party site via AJAX.



This example relies on jQuery and uses mysafeinfo.com to retrieve U.S. Presidents data in XML format. MySafeInfo is a free service we offer to software developers to provide test data in a simple, flexible manner, in a variety of formats, including XML, JSON, JSONP, CSV, and more.

ASP.Net C# Accessing a BasePage from a Master page

In most of my designs there is at minimum a Master page, and several Content pages that use the Master page and inherit from a BasePage.

In some circumstances there might be properties or methods in the BasePage that you want to access from the Master page code-behind.

BasePage.cs
   public class BasePage : System.Web.UI.Page  
   {  
   }  

Base.Master
     private BasePage MyBasePage  
     {  
       get  
       {  
         try  
         {  
           return (BasePage)Page;  
         }  
         catch  
         {  
           return new BasePage();  
         }  
       }  
     }  

Now you can use the MyBasePage variable to access any public information in the BasePage class.

Of course the try/catch is in there to handle situations where a content page may not actually inherit from the BasePage, in which case that would throw an error. That could be handled a few different ways, but that's partly dependent on how you plan to use it. In most cases all of my content pages inherit from the BasePage and this is a safe solution.

This same technique also works if you need to access the BasePage from within a user control.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

Thursday, April 23, 2015

ASP.Net C# 3 simple ways to prompt a file download using Response.BinaryWrite, Response.Write, Response.WriteFile

Here are 3 simple DowloadFile methods to use in your ASP.Net C# base page or utilities class to simplify and standardize providing a file download prompt in the browser.

Option 1 - Pass in the raw byte array
     public void DownloadFile(byte[] data, string FileType = "application/csv", string FileName = "data.csv")  
     {  
       // headers  
       Response.BufferOutput = true;  
       Response.ClearHeaders();  
   
       // explicitly append preamble for csv files so excel recognizes utf-8 encoding  
       if (FileType.ContainsValue("csv"))  
       {  
         Response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());  
       }  
   
       // encoding  
       Response.ContentEncoding = System.Text.Encoding.UTF8;  
   
       // content type  
       Response.ContentType = FileType;  
   
       // content disposition  
       Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", FileName));  
   
       // data  
       Response.BinaryWrite(data);  
   
       // end  
       Response.End();  
     }  

Option 2 - Pass in a simple string, for example HTML data or CSV data
     public void DownloadFile(string data, string FileType = "application/csv", string FileName = "data.csv")  
     {  
       // headers  
       Response.BufferOutput = true;  
       Response.ClearHeaders();  
   
       // explicitly append preamble for csv files so excel recognizes utf-8 encoding  
       if (FileType.ContainsValue("csv"))  
       {  
         Response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());  
       }  
   
       // encoding  
       Response.ContentEncoding = System.Text.Encoding.UTF8;  
   
       // content type  
       Response.ContentType = FileType;  
   
       // content disposition  
       Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", FileName));  
   
       // data  
       Response.Write(data);  
   
       // end  
       Response.End();  
     }  

Option 3 - Pass in the file path to a file that already physically exists
     public void DownloadFile(string FileName, string FileType = "application/csv")  
     {  
       // make sure file exists  
       if (!File.Exists(FileName))  
       {  
         return;  
       }  
   
       // headers  
       Response.BufferOutput = true;  
       Response.ClearHeaders();  
   
       // encoding  
       Response.ContentEncoding = System.Text.Encoding.UTF8;  
   
       // content type  
       Response.ContentType = FileType;  
   
       // content disposition  
       Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", Path.GetFileName(FileName)));  
   
       // data  
       Response.WriteFile(FileName);  
   
       // end  
       Response.End();  
     }  

Example usage:
     // download file  
     base.DownloadFile(data: RawBytes, FileType: "application/pdf", FileName: "test.pdf");  

ASP.Net C# How to create a simple debug panel within your page instead of using Response.Write

Here's a simple way to create a temporary debug panel within your ASP.Net web application if you need to output values for debugging and the normal debugging options aren't available or practical.

Base.Master
 <asp:PlaceHolder ID="pnlDebug" Visible="true" runat="server"></asp:PlaceHolder>  

Base.Master.cs
 public void Debug(string Value = "")  
 {  
    pnlDebug.Controls.Add(new LiteralControl(string.Format("<div>{0}</div>", Value)));  
 }  

Test.aspx

 <%@ MasterType VirtualPath="~/Base.master" %>  

Test.aspx.cs
 // debug  
 if (Configuration.Debug)  
 {  
    Debug(string.Format("SessionID: {0}", Configuration.SessionID));  
    Debug(string.Format("Language: {0}", Configuration.Language));  
 }  

The reason I like this approach is because it gives you the ability to avoid using Response.Write for debugging, which can mangle your layout while testing. It also allows you to build in optional debugging that you can turn on and off through the session and/or querystring (for example) to make debugging easier for applications where step-through debugging is not an option.


Sunday, April 19, 2015

ASP.Net C# Extension Method to Get All Controls (Recursive)

Here is another extension method I use frequently to recursively find all controls (optionally of a certain type) on the page or within a parent.

Code:
     public static IEnumerable<Control> GetAllControls(this Control Parent, System.Type Type = null)  
     {  
       if (Parent == null)  
       {  
         yield break;  
       }  
   
       if (Type == null || Parent.GetType().Equals(Type))  
       {  
         yield return Parent;  
       }  
   
       foreach (Control Control in Parent.Controls)  
       {  
         foreach (Control x in Control.GetAllControls(Type))  
         {  
           yield return x;  
         }  
       }  
     }  

Example usage:
 List<Control> PageControls = Page.GetAllControls().ToList();  
 IEnumerable<Control> DropDownLists = Page.GetAllControls(typeof(DropDownList));  

Thursday, April 9, 2015

ASP.Net C# Convert HTML to PDF using iTextSharp

Click here to view an updated post that optionally supports landscape mode.

The following article on Stack Overflow was a life-saver in a recent project where we needed to convert HTML to PDF.

http://stackoverflow.com/a/25164258

We were using C# and needed to convert a well-formed string of HTML to a PDF file. Using iTextSharp (5.5.5) and itextsharp.xmlworker (5.5.5), both available in the NuGet Package Manager in Visual Studio 2013, and with a great working example from the Stack Overflow answer we ended up with the following:
 public static ReturnValue ConvertHtmlToPdfAsBytes(string HtmlData)  
 {  
       // variables  
       ReturnValue Result = new ReturnValue();  
   
       // do some additional cleansing to handle some scenarios that are out of control with the html data  
       HtmlData = HtmlData.ReplaceValue("<br>", "<br />");  
   
       // convert html to pdf  
       try  
       {  
         // create a stream that we can write to, in this case a MemoryStream  
         using (var stream = new MemoryStream())  
         {  
           // create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF  
           using (var document = new Document())  
           {  
             // create a writer that's bound to our PDF abstraction and our stream  
             using (var writer = PdfWriter.GetInstance(document, stream))  
             {  
               // open the document for writing  
               document.Open();  
   
               // read html data to StringReader  
               using (var html = new StringReader(HtmlData))  
               {  
                 XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, html);  
               }  
   
               // close document  
               document.Close();  
             }  
           }  
   
           // get bytes from stream  
           Result.Data = stream.ToArray();  
   
           // success  
           Result.Success = true;  
         }  
       }  
       catch (Exception ex)  
       {  
         Result.Success = false;  
         Result.Message = ex.Message;  
       }  
   
       // return  
       return Result;  
 }  

The ReturnValue class was simply a helper class that looks like this:
 // return value class  
 public class ReturnValue  
 {  
       // constructor  
       public ReturnValue()  
       {  
         this.Success = false;  
         this.Message = string.Empty;  
       }  
   
       // properties  
       public bool Success = false;  
       public string Message = string.Empty;  
       public Byte[] Data = null;  
 }  

We also had another method to physically create the PDF file in case you didn't want just the bytes array directly, for example:
 public static ReturnValue ConvertHtmlToPdfAsFile(string FilePath, string HtmlData)  
 {  
       // variables  
       ReturnValue Result = new ReturnValue();  
   
       try  
       {  
         // convert html to pdf and get bytes array  
         Result = ConvertHtmlToPdfAsBytes(HtmlData: HtmlData);  
   
         // check for errors  
         if (!Result.Success)  
         {  
           return Result;  
         }  
   
         // create file  
         File.WriteAllBytes(path: FilePath, bytes: Result.Data);  
   
         // result  
         Result.Success = true;  
       }  
       catch(Exception ex)  
       {  
         Result.Success = false;  
         Result.Message = ex.Message;  
       }  
   
       // return  
       return Result;  
 }  

It's important to remember that in order for this to work, you must have valid well-formed HTML; otherwise you can certainly expect for iTextSharp to throw an error. But if you have control over the HTML that you need to convert, this solution is great, and produces very nice PDF files.

It's worth noting that in our case we didn't need to pass the CSS in separately using the overloaded ParseXHtml constructor, ParseXHtml(PdfWriter writer, Document doc, Stream inp, Stream inCssFile), because we were including our CSS styles in our HTML data string instead, which for our solution was a bit cleaner.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

Tuesday, April 7, 2015

ASP.Net C# Extension Method to get Enum Description

Ever needed to get the Description attribute from an enum in C#? Here's an easy way to do it generically with an extension method.

Enum:
 public enum Menu  
 {  
      Home,  
      [Description("About Page Description")]  
      About,  
      [Description("Contact Page Description")]  
      Contact  
 }  

Code:
 public static string Description(this Enum value)  
 {  
      // variables  
      var enumType = value.GetType();  
      var field = enumType.GetField(value.ToString());  
      var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);  
   
      // return  
      return attributes.Length == 0 ? value.ToString() : ((DescriptionAttribute)attributes[0]).Description;  
 }  

Example usage:
 string Description = Enumerators.Menu.About.Description();  

In this case Description variable would be set to the string value "About Page Description". If the enum property you are accessing doesn't have a Description attribute the extension method will return the value of the enum instead.

Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

ASP.Net C# Extension Method to see if a string STARTS WITH a value (case insensitive)

Here is an extension method to see if a string starts with a value, and it's case insensitive. There's also an overloaded version of the method to allow you to check multiple values at once.

Code:
 public static bool StartsWithValue(this string Value, string CompareValue)  
 {  
      bool ReturnValue = false;  
   
      if (Value != null && CompareValue != null)  
      {  
           ReturnValue = Value.Trim().StartsWith(CompareValue.Trim(), StringComparison.OrdinalIgnoreCase);  
      }  
   
      return ReturnValue;  
 }  
   
 public static bool StartsWithValue(this string Value, params string[] CompareValues)  
 {  
      if (Value != null && CompareValues != null)  
      {  
           foreach (string CompareValue in CompareValues)  
           {  
                if (Value.StartsWithValue(CompareValue))  
                {  
                     return true;  
                }  
           }  
      }  
   
      return false;  
 }  

Example usage:
 public bool IsDEV  
 {  
      get  
      {  
           return Request.Url.Host.StartsWithValue("dev.");  
      }  
 }  
 public List<String> Prefixes = new List<String>() { "lbl", "btn" };  
   
 foreach (Control Control in PageControls.Where(x => x.ID.StartsWithValue(Prefixes.ToArray())))  
 {  
      // code   
 }  

jQuery - Populating a dropdown list in JSONP format

Here's a quick example of how to retrieve JSONP data from a 3rd party site via AJAX and bind it to an HTML select control.



This example relies on jQuery and uses mysafeinfo.com to retrieve U.S. States data in JSONP format. MySafeInfo is a free service we offer to software developers to provide test data in a simple, flexible manner, in a variety of formats.

Also, the example above is using $.getJSON and retrieving JSONP data; however, it could just as easily retrieve standard JSON data, or for that matter could retrieve data in another format such as XML, for example:

Monday, April 6, 2015

ASP.Net C# Extension Method to see if a string CONTAINS a value (case insensitive)

Here is another simple extension method to see if a string contains a value, and it's case insensitive. There's also an overloaded version of the method to allow you to check multiple values at once.

Code:
 public static bool ContainsValue(this string Value, string CompareValue)  
 {  
      bool ReturnValue = false;  
        
      if (Value != null && CompareValue != null)  
      {  
           ReturnValue = Value.Trim().IndexOf(CompareValue.Trim(), StringComparison.OrdinalIgnoreCase) >= 0;  
      }  
   
      return ReturnValue;  
 }  
   
 public static bool ContainsValue(this string Value, params string[] CompareValues)  
 {  
      if (Value != null && CompareValues != null)  
      {  
           foreach (string CompareValue in CompareValues)  
           {  
                if (Value.ContainsValue(CompareValue))  
                {  
                     return true;  
                }  
           }  
      }  
   
      return false;  
 }  

Example usage:
 if (WebControl.CssClass.ContainsValue("class1", "class2"))  
 {  
      // code  
 }  


ASP.Net C# Extension Method to compare multiple string values (case insensitive)

A few days ago I posted ASP.Net C# Extension Method to compare string values (case insensitive), which is a simple extension method to compare string values without having to worry about case sensitivity.

Here's an overloaded version of this method that lets you compare a string with multiple values.

Code:
 public static bool IsEqual(this string Value, params string[] CompareValues)   
 {   
      if (Value != null && CompareValues != null)   
      {   
           foreach (string CompareValue in CompareValues)   
           {   
                if (Value.IsEqual(CompareValue))   
                {   
                     return true;   
                }   
           }   
      }   
       
      return false;   
 }   

Example usage:
 foreach(string Action in Actions.Where(x => x.IsEqual("Add", "Update", "Delete")))  
 {  
      // code  
 }  

Again, this is one I use to keep the code a little shorter, and in my opinion more readable, opposed to having to say x == "Add" || x == "Update" || x == "Delete" and having to worry about case-sensitivity, etc.

ASP.Net Page Life Cycle Events when using Nested Master Pages, Content Pages, and Base Pages

A while back I posted Events in ASP.NET Master and Content Pages, regarding the sequence in which events occur when a master page is merged with a content page.

In some cases, the same event is raised in both the content and the master page. For example, both pages raise Init and Load events. The general rule for how events are raised is that the initialization events are raised from the innermost control to the outermost one, and all other events are raised from the outermost control to the innermost one. It is helpful to remember that the master page is merged into the content page and treated as a control in the content page.

I often refer back to that original post as a quick reality check when considering placement for certain code to make sure it happens at the appropriate place in the page life cycle.

But typically my project setup is slightly more complex, and is not just a master page and content page, but more along the lines of:

- Base Master Page (general, script references, style references, etc)
- Nested Master Pages (design/layout/theme)
- Content Pages (page specific functionality)
- Base Page (inherited by each content page typically)

The same rules apply in regards to the sequence of events; however, thinking about this visually can be a little more difficult, so here's a list to help keep it straight:

  • BasePage PreInit
  • Page PreInit
  • Master Init
  • Nested Master Init
  • BasePage Init
  • Page Init
  • BasePage InitComplete
  • BasePage PreLoad
  • BasePage Load
  • Page Load
  • Nested Master Load
  • Master Load
  • BasePage LoadComplete
  • BasePage PreRender
  • Page PreRender
  • Nested Master PreRender
  • Master PreRender
  • BasePage PreRenderComplete
  • BasePage SaveStateComplete
  • Master Unload
  • Nested Master Unload
  • BasePage Unload
  • Page Unload

Sunday, April 5, 2015

ASP.Net C# Extension Methods to check if a string is blank or has a value

Here are 2 more extension methods that are simple enough, but I use on a daily basis to keep code clean and simple. I prefer to use these methods over string.IsNullOrEmpty or string.IsNullOrWhiteSpace or checking the Length of the string to keep things concise.

Code:
 public static bool IsBlank(this string Value)  
 {  
       bool ReturnValue = true;  
   
       if (Value != null)  
       {  
         ReturnValue = Value.Trim().Length == 0;  
       }  
   
       return ReturnValue;  
 }  
 public static bool HasValue(this string Value)  
 {  
      return !Value.IsBlank();  
 }  

Example usage:
 if (Key.IsBlank())  
 {  
      // code  
 }  
 if (Key.HasValue())  
 {  
      // code  
 }  

Sure you may not need both of them, or either for that matter, but when it comes to writing more readable code I like the option of having them both in my library.

Saturday, April 4, 2015

ASP.Net C# Extension Method to select item in DropDownList

Here's another extension method that's part of my standard extension library. It simply selects an item in a DropDownList. Why bother with an extension method you ask? Mainly to keep from having to check if the item exists in the dropdown and also so you don't have to worry about if an item is already selected (e.g. Cannot have multiple items selected in a DropDownList.)

Code:
 public static void SetValue(this DropDownList control, string value)  
 {  
      // variables  
      var ListItem = control.Items.Cast<ListItem>().Where(x => x.Value.IsEqual(value)).FirstOrDefault();  
   
      // check for match  
      if (ListItem != null)  
      {  
           control.ClearSelection();  
           ListItem.Selected = true;  
      }  
 }  

Example usage:
 ddlState.SetValue(State);  

Dependencies:

The SetValue extension method is dependent on the IsEqual extension method previously discussed.

This same technique can also be applied to the HtmlSelect control.
 public static void SetValue(this HtmlSelect control, string value)  
     {  
       // variables  
      var ListItem = control.Items.Cast<ListItem>().Where(x => x.Value.IsEqual(value)).FirstOrDefault();  
   
       // check for match  
       if (ListItem != null)  
       {  
         ListItem.Selected = true;  
       }  
     }  

Friday, April 3, 2015

ASP.Net C# Extension Method to compare string values (case insensitive)


A simple extension method to compare string values without having to worry about case sensitivity.

Code:
 public static bool IsEqual(this string Value, string CompareValue)  
 {  
      bool ReturnValue = false;  
   
      if (Value != null && CompareValue != null)  
      {  
           ReturnValue = string.Compare(Value.Trim(), CompareValue.Trim(), StringComparison.OrdinalIgnoreCase) == 0;  
      }  
   
      return ReturnValue;  
 }  

Example usage:
 if (Users.Any(x => x.FirstName.IsEqual(FirstName) && x.LastName.IsEqual(LastName)))  
 {  
      // code  
 }