Thursday, December 28, 2017

ASP.NET GridView : Change Command Field to Template Field

For example, with a Delete button.


<asp:CommandField ShowDeleteButton="True" />


                                                        <asp:LinkButton ID="lbDelete" runat="server" CommandName="Delete"

Sunday, December 3, 2017

ASP.NET AJAX Cheat Sheet

REMEMBER: Only the stuff inside the UpdatePanel gets updated from the postback.
In Design View: In this order, from Toolbox (AJAX section), add
Script Manager, UpdateProgress, then Update Panel.

If you are using Master Pages, and this is a content page, put this under <asp:Content element.

For UpdateProgress, fill out AssociatedUpdatePanelID="UpdatePanel1" DisplayAfter="100".

Add <ContentTemplate> before any Div's.

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
 <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1" DisplayAfter="100">
            <h1 class="red">Please be patient....updating database....</h1>

    <asp:UpdatePanel ID="UpdatePanel1" runat="server">

<div all the stuff on your page></div>


Saturday, November 11, 2017


To quickly get a list of all CONSTRAINTS on tables in a database:

SELECT * FROM sys.objects


Superb article:

(copied for posterity)

Triggers are database operations which are automatically performed when an action such as Insert, Update or Delete is performed on a Table or a View in database.
Triggers are associated with the Table or View directly i.e. each table has its own Triggers.
Types of Triggers
There are two types of Triggers. After and Instead of Triggers.
After Triggers
These triggers are executed after an action such as Insert, Update or Delete is performed.
Instead of Triggers
These triggers are executed instead of any of the Insert, Update or Delete operations. For example, let’s say you write an Instead of Trigger for Delete operation, then whenever a Delete is performed the Trigger will be executed first and if the Trigger deletes record then only the record will be deleted.
After Triggers
Now I will explain you with examples the After Triggers for Insert, Update and Delete operations.
Insert Trigger
Below is an example of an After Insert Trigger. Whenever a row is inserted in the Customers Table, the following trigger will be executed. The newly inserted record is available in the INSERTED table.
The following Trigger is fetching the CustomerId of the inserted record and the fetched value is inserted in the CustomerLogs table.
       ON [dbo].[Customers]
       DECLARE @CustomerId INT
       SELECT @CustomerId = INSERTED.CustomerId       
       INSERT INTO CustomerLogs
       VALUES(@CustomerId, 'Inserted')
Update Trigger
Below is an example of an After Update Trigger. Whenever a row is updated in the Customers Table, the following trigger will be executed. The updated record is available in the INSERTED table.
The following Trigger is fetching the CustomerId of the updated record. In order to find which column is updated, you will need to use UPDATE function and pass the Column name of the Table to it.
The UPDATE function will return TRUE for a Column if its value was updated else it will return false.
Finally based on which column of the record has been updated a record (containing the CustomerId and the appropriate action) is inserted in the CustomerLogs table.
       ON [dbo].[Customers]
       DECLARE @CustomerId INT
       DECLARE @Action VARCHAR(50)
       SELECT @CustomerId = INSERTED.CustomerId       
       IF UPDATE(Name)
              SET @Action = 'Updated Name'
       IF UPDATE(Country)
              SET @Action = 'Updated Country'
       INSERT INTO CustomerLogs
       VALUES(@CustomerId, @Action)
Delete Trigger
Below is an example of an After Delete Trigger. Whenever a row is delete in the Customers Table, the following trigger will be executed. The deleted record is available in the DELETED table.
The following Trigger is fetching the CustomerId of the deleted record and the fetched value is inserted in the CustomerLogs table.
       ON [dbo].[Customers]
       DECLARE @CustomerId INT
       SELECT @CustomerId = DELETED.CustomerId       
       INSERT INTO CustomerLogs
       VALUES(@CustomerId, 'Deleted')
The following screenshot displays the Log table after the above Triggers were executed.
Simple Insert Update and Delete Triggers in SQL Server with example
Instead Of Triggers
Below is an example of an Instead Of Delete Trigger. Whenever anyone tries to delete a row from the Customers table the following trigger is executed.
Inside the Trigger, I have added a condition that if record has CustomerId value 2 then such a record must not be deleted and an error must be raised. Also a record is inserted in the CustomerLogs table.
If the CustomerId value is not 2 then a delete query is executed which deletes the record permanently and a record is inserted in the CustomerLogs table.
CREATE TRIGGER [dbo].[Customer_InsteadOfDELETE]
       ON [dbo].[Customers]
       DECLARE @CustomerId INT
       SELECT @CustomerId = DELETED.CustomerId       
       IF @CustomerId = 2
              RAISERROR('Mudassar Khan''s record cannot be deleted',16 ,1)
              INSERT INTO CustomerLogs
              VALUES(@CustomerId, 'Record cannot be deleted.')
              DELETE FROM Customers
              WHERE CustomerId = @CustomerId
              INSERT INTO CustomerLogs
              VALUES(@CustomerId, 'Instead Of Delete')
The following error message shown when record with CustomerId 2 is deleted.
Simple Insert Update and Delete Triggers in SQL Server with example
The following screenshot displays the Log table after the Instead Of Trigger is executed.
Simple Insert Update and Delete Triggers in SQL Server with example

Friday, October 27, 2017

NuGet How I Hate Thee, Let Me Count the Ways

An error occurred while trying to restore packages: Unable to find version 2.0.1 of package Microsoft.AspNet.Providers.LocalDB.

Unable to find version '2.0.1' of package 'Microsoft.AspNet.Providers.LocalDB'.

Unable to find version '2.0.1' of package 'Microsoft.AspNet.Providers.LocalDB'.

Saturday, October 21, 2017

rare case of ternary operator I approve of

var  thingamajig= Request.QueryString["thingamajig"] ?? Request.Form["thingamajig"];

see  null-coalescing operator ?? double question-mark

Saturday, October 14, 2017

Gnossis or Gnosis

String product = ConfigurationManager.AppSettings["reportProduct"];
                String buildVersion = ConfigurationManager.AppSettings["appBuild"];
                string productVersionNumberFromDll = "";
                string fileVersionNumberFromDll = "";
                    string dllFile = Server.MapPath("bin/applicationWeb.dll");
                    FileVersionInfo dllFileVersionInfo = FileVersionInfo.GetVersionInfo(dllFile);
                    fileVersionNumberFromDll = dllFileVersionInfo.FileVersion;
                    productVersionNumberFromDll = dllFileVersionInfo.ProductVersion;
                catch (Exception)
                    string NETAssemblyVersion = Environment.Version.ToString();
                    string OS = Environment.OSVersion.ToString();
                    string MachineName = Environment.MachineName.ToString();
                    string UserDomainName = Environment.UserDomainName.ToString();
                    string UserName = Environment.UserName.ToString();

                    Response.Write("Product: " + product);
                    Response.Write("<BR>application Version: " + buildVersion);
                    Response.Write("<BR>dll File Version: " + fileVersionNumberFromDll);
                    Response.Write("<BR>dll Product Version: " + productVersionNumberFromDll);

                    Response.Write(".NET Version: " + NETAssemblyVersion + "<BR>");
                    Response.Write("OS: " + OS + "<BR>");
                    Response.Write("MachineName: " + MachineName + "<BR>");
                    Response.Write("UserDomainName: " + UserDomainName + "<BR>");
                    Response.Write("UserName: " + UserName + "<BR>");

                    string myConn = DBConnection.getDBConnection();
                    Response.Write("<P>" + myConn);

                    Response.Write("URL Components<BR><HR><BR>");
                    Response.Write(" Request.Url.Scheme : " + Request.Url.Scheme + "<BR>");
                    Response.Write(" Request.Url.Host  : " + Request.Url.Host + "<BR>");
                    Response.Write(" Request.Url.IsDefaultPort : " + Request.Url.IsDefaultPort.ToString() + "<BR>");
                    Response.Write(" Request.Url.Port : " + Request.Url.Port + "<BR>");
                    // string URLprefix = Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host + (Request.Url.IsDefaultPort ? "" : ":" + Request.Url.Port);
                catch (Exception ex)

Error Handling in ASP.NET

In Global.asax:

void Application_Error(object sender, EventArgs e)
            Exception exc = Server.GetLastError();

            if (exc is HttpUnhandledException)
                if (ConfigurationManager.AppSettings["logErrorsInDb"] == "true")
                        string UserId = "n/a";
                        if (Session["usernameEmail"] != null)
                            UserId = Session["usernameEmail"].ToString();

                        string Webpage = Request.PhysicalPath;

                        // get IP **********************************
                        string IP = "n/a";
                        System.Web.HttpContext context = System.Web.HttpContext.Current;
                        string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

                        if (!string.IsNullOrEmpty(ipAddress))
                            string[] addresses = ipAddress.Split(',');
                            if (addresses.Length != 0)
                                IP = addresses[0];
                            IP = context.Request.ServerVariables["REMOTE_ADDR"];
                        // *******************************************

                        Persist persist = new Persist();
                        persist.logError(exc.InnerException.Message, UserId, exc.InnerException.StackTrace, Webpage, IP);
                    catch (Exception ex)

                // Pass the error on to the error page.
                Server.Transfer("Oops.aspx?handler=Application_Error%20-%20Global.asax", true);

My simple error logger:

public void logError(String Message, String UserId, String StackTrace, String Webpage, String IP)
            using (SqlConnection cn = new SqlConnection(DBConnection.getDBConnection()))
                int rowsAffected = 0;

                String sql = @"INSERT INTO [dbo].[ErrorLog](Message,UserId,StackTrace,Webpage,IP)
SqlCommand cmd = new SqlCommand(sql, cn);
                cmd.CommandType = System.Data.CommandType.Text;
                if (Message.Length > 1000)
                    Message = Message.Substring(0, 999);
cmd.Parameters.AddWithValue("@Message", Message);
                cmd.Parameters.AddWithValue("@UserId", UserId);
                if (StackTrace.Length > 3000)
                    StackTrace = StackTrace.Substring(0, 2999);
cmd.Parameters.AddWithValue("@StackTrace", StackTrace);
                if (Webpage.Length > 500)
                    Webpage = Webpage.Substring(0, 499);
cmd.Parameters.AddWithValue("@Webpage", Webpage);
                cmd.Parameters.AddWithValue("@IP", IP);

                    rowsAffected = cmd.ExecuteNonQuery();
                catch (Exception err)

DDL for table:



CREATE TABLE [dbo].[ErrorLog](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Message] [nvarchar](1000) NULL,
[Timestamp] [datetime] NULL DEFAULT (getdate()),
[UserId] [nvarchar](50) NULL,
[StackTrace] [nvarchar](max) NULL,
[Webpage] [nvarchar](500) NULL,
[IP] [nvarchar](50) NULL,
[Id] ASC


Thursday, October 5, 2017

Git Git!

  1. Commit will simply make record of your changes that you have made on your local machine. It will not mark the change in the remote repository.
  2. Commit and Push will do the above and push it to the remote repository. This means that any changes you have made will be saved to the remote repository as well.
  3. Commit and Sync does three things. First, it will commit. Second, it will perform a pull (grabs the updated information from the remote repo). Finally, it will push.
Microsoft tutorial here:

  • fetch , which downloads the changes from your remote repo but does not apply them to your code.
  • merge , which applies changes taken from fetch to a branch on your local repo.
  • pull , which is a combined command that does a fetch and then a merge.

Difference Between DBNull.Value and Null Reference

Let's say you are looking up some numerical value in a table, based on some id, like a PRODUCT ID, for example, the PRICE. 

If the table allows nulls for the PRICE (and in the real world, sometimes this happens, out of your control), then it is possible that there is a PRODUCT ID in the table that has a NULL price.  If you do a query in SQL Server Mgt Studio, you'll actually see it say in the cell, NULL.

On the other hand, let's say that the PRODUCT ID is erroneous, that is, it does not exist in the table.  So a query for the price would return no rows.

If you are using ExecuteScalar(), then you have two possible types of null situations to consider.

In the former situation, ExecuteScalar() would return an object which has the value of DBNull.Value.
In the latter, it would return null.

object returnValue = cmd.ExecuteScalar();
if(returnValue == DBNull.Value){
//table allows nulls for this field

if(returnValue == null) {
// no records were returned

if(returnValue != null && returnValue != DBNull.Value){
     double price = (double)returnValue;

Tuesday, August 15, 2017

Hash vs Encryption

Hashing:  one-way, (fixed length), you can never un-hash...all you can do is compare hash values, because the same hash will be created for the same string.
That's why it is used for passwords.  All you can do is hash the user entered value and see if it matches the stored hash value of the password.

Salting:  What if the user has a simple or common password?  Then the hashes would look the same, and an attacker gaining one would gain access to the other by looking for same hash.  So add another string, called a salt, which is unique per user.

Encryption:  meant to also be decrypted using a key.  That key can be the same for both encrypting and decrypting, or you can have a different one for each pathway.


A hash is a string or number generated from a string of text. The resulting string or number is a fixed length, and will vary widely with small variations in input. The best hashing algorithms are designed so that it's impossible to turn a hash back into its original string.


Hashing is an ideal way to store passwords, as hashes are inherently one-way in their nature. By storing passwords in hash format, it's very difficult for someone with access to the raw data to reverse it (assuming a strong hashing algorithm and appropriate salt has been used to generate it).

When storing a password, hash it with a salt, and then with any future login attempts, hash the password the user enters and compare it with the stored hash. If the two match up, then it's virtually certain that the user entering the password entered the right one.

Hashing is great for usage in any instance where you want to compare a value with a stored value, but can't store its plain representation for security reasons. Other use cases could be checking the last few digits of a credit card match up with user input or comparing the hash of a file you have with the hash of it stored in a database to make sure that they're both the same.


  • MD5 - MD5 is the most widely known hashing function. It produces a 16-byte hash value, usually expressed as a 32 digit headecimal number. Recently a few vulnerabilities have been discovered in MD5, and rainbow tables have been published which allow people to reverse MD5 hashes made without good salts.
  • SHA - There are three different SHA algorithms -- SHA-0, SHA-1, and SHA-2. SHA-0 is very rarely used, as it has contained an error which was fixed with SHA-1. SHA-1 is the most commonly used SHA algorithm, and produces a 20-byte hash value.
  • SHA-2 consists of a set of 6 hashing algorithms, and is considered the strongest. SHA-256 or above is recommended for situations where security is vital. SHA-256 produces 32-byte hash values.


Encryption turns data into a series of unreadable characters, that aren't of a fixed length. The key difference between encryption and hashing is that encrypted strings can be reversed back into their original decrypted form if you have the right key.

There are two primary types of encryption, symmetric key encryption and public key encryption. In symmetric key encryption, the key to both encrypt and decrypt is exactly the same. This is what most people think of when they think of encryption.

Public key encryption by comparison has two different keys, one used to encrypt the string (the public key) and one used to decrypt it (the private key). The public key is is made available for anyone to use to encrypt messages, however only the intended recipient has access to the private key, and therefore the ability to decrypt messages.


Encryption should only ever be used over hashing when it is a necessity to decrypt the resulting message. For example, if you were trying to send secure messages to someone on the other side of the world, you would need to use encryption rather than hashing, as the message is no use to the receiver if they cannot decrypt it.

If the raw value doesn't need to be known for the application to work correctly, then hashing should always be used instead, as it is more secure.

If you have a usecase where you have determined that encryption is necessary, you then need to choose between symmetric and public key encryption. Symmetric encryption provides improved performance, and is simpler to use, however the key needs to be known by both the person/software/system encrypting and decrypting data.

If you were communicating with someone on the other side of the world, you'd need to find a secure way to send them the key before sharing your secure messages. If you already had a secure way to send someone an encryption key, then it stands to reason you would send your secure messages via that channel too, rather than using symmetric encryption in the first place.

Many people work around this shortcoming of symmetric encryption by initially sharing an encryption key with someone using public key encryption, then symmetric encryption from that point onwards -- eliminating the challenge of sharing the key securely.


  • AES - AES is the "gold standard" when it comes to symmetric key encryption, and is recommended for most use cases, with a key size of 256 bits. 
  • PGP - PGP is the most popular public key encryption algorithm. 

Wednesday, August 9, 2017

Bundling and Minification for ASP.NET

Adding Bundling and Minification to Web Forms

My   B/M tutorial provides a good introduction to benefits of Bundling and Minification. You should read it to become familiar with the bundling and minification. This blog will focus on using B/M with Web Forms, my B/M tutorial focused on ASP.NET MVC.
Create a new ASP.NET Web Forms application which targets the .Net 4.5 framework.
Run the application launch the IE F-12 developer tools. Select the Script tab, then use the assets button to view the JavaScript files.
You can select one of the JavaScript files and view it in the left pane. Note the full (non-minimized version) of the files are used.

Creating the jQuery Bundles

Add jQuery, jQuery.UI and jQuery validation to the  BundleConfig class in the App_Start folder. The following code shows the complete class:
using System.Web.Optimization;

public class BundleConfig
    public static void RegisterBundles(BundleCollection bundles)
        bundles.Add(new ScriptBundle("~/bundles/jquery").Include(

        bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(

        bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(

        bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include(

        bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include(

        bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(

Register the Bundles

The templates create the code hook up the bundle registration in the Application_Start method in the Global.asax file.
void Application_Start(object sender, EventArgs e)

Reference the Bundles

Add the jQuery bundles to the <asp:PlaceHolder > markup as shown in the following code:
    <asp:PlaceHolder runat="server">        
         <%: Scripts.Render("~/bundles/modernizr") %>
         <%: Scripts.Render("~/bundles/jquery") %>
         <%: Scripts.Render("~/bundles/jqueryui") %>
Comment out the jQuery script references in the ScriptManager tag as shown below:
    <form runat="server">
    <asp:ScriptManager runat="server">
            <asp:ScriptReference Name="jquery" />
            <asp:ScriptReference Name="jquery.ui.combined" />

CSS Bundles

Examine the Bundle.config file, which contains the markup to create CSS style bundles.
<?xml version="1.0" encoding="utf-8" ?>
<bundles version="1.0">
  <styleBundle path="~/Content/css">
    <include path="~/Content/Site.css" />
  <styleBundle path="~/Content/themes/base/css">
    <include path="~/Content/themes/base/jquery.ui.core.css" />
    <include path="~/Content/themes/base/jquery.ui.resizable.css" />
    <include path="~/Content/themes/base/jquery.ui.selectable.css" />
    <include path="~/Content/themes/base/jquery.ui.accordion.css" />
    <include path="~/Content/themes/base/jquery.ui.autocomplete.css" />
    <include path="~/Content/themes/base/jquery.ui.button.css" />
    <include path="~/Content/themes/base/jquery.ui.dialog.css" />
    <include path="~/Content/themes/base/jquery.ui.slider.css" />
    <include path="~/Content/themes/base/jquery.ui.tabs.css" />
    <include path="~/Content/themes/base/jquery.ui.datepicker.css" />
    <include path="~/Content/themes/base/jquery.ui.progressbar.css" />
    <include path="~/Content/themes/base/jquery.ui.theme.css" />

You can add your own style bundles to the Bundle.config file.
The following markup shows the CSS bundles and JavaScript bundles referenced. Note that you can multiple bundles in one call to the Render method.
<%: Styles.Render("~/Content/themes/base/css", 
                    "~/Content/css") %>
<%: Scripts.Render("~/bundles/modernizr") %>
<%: Scripts.Render("~/bundles/jquery",
                    "~/bundles/jqueryui") %>