Wednesday, October 21, 2015

Creating and Using a Git Ignore File

Most of the time, there are certain files and folders that you do not want to track in your Git repository.  You have to explicitly tell Git which ones to ignore.  You provide this information in a special file you create in the root of your repository.  It is simply a text file named .gitignore.  Notice that there is no filename, just an extension.  Windows will not let you create a file with no name, so you have to create the file using a command in Git Bash.  Run the following from your root folder:

echo /bin > .gitignore

This command will create a file named .gitignore and put the "/bin" text in it.  This is the start of a very basic git ignore file.  It tells Git to ignore a folder named bin and all files contained in it.  You can add individual files and folders on separate lines.  Just double click the file in Windows and edit in Notepad.

Wednesday, October 14, 2015

Regular Expression Primer

I feel like I've finally cracked the code on regular expressions.  This is my attempt to document the essentials of regular expressions using JavaScript.  A regular expression essentially describes a pattern of text.

Generally, you use a regular expression (regex) in one of two ways:

  1. Test to see whether a specified string matches a regex exactly.  This is mainly used for validating input.
  2. Extract all instances of the pattern from a larger string of text.  The main use here is to replace the instances of the pattern with something else.
The easiest way to perform the first use is to define the regular express on the fly and then call the test method like so:

/^[0-9]+$/.test(inputToTest)

The test method returns true or false, based on whether the input string was a match.  The forward slashes simply delimit the regular expression.  The ^ indicates the beginning of the string, and the $ indicates the end of the string.  [0-9] says to match any number, and the plus means any number 1 or more times.  So, only numbers with one or more digits will match the regex.

The second use often involves replacing the matching text.  You can use a regex as a parameter when calling the string.replace method.  Let's say you want to replace all numbers in a string with the letter x.  Here is how you do it:

var results = inputString.replace(/[0-9]+/g, "x");

What's the "g" for?

That's the global flag.  That says to replace every matching text in the string with "x".

Now, let's talk about parenthesis.  A parenthesis in a regex means you can extract just the part in the parentheses.  Let's say you want to find everything with curly braces, and replace it all with just the text inside the curly braces.

var results = inputString.replace(/\{([A-Za-z]+)\}/g, "$1");

The &1 refers to the text matched by the first parenthesis.  So we would replace "{test}" with just "test".  Notice that the backslash is used to escape the curly brace character.

Sometimes a parenthesis is just a parenthesis and doesn't have to be referred to later.  You can just use it to group stuff.

These are really dumb examples to keep things simple, but these techniques are very powerful.  The best reference I've found for dealing with regex is here.


Monday, October 5, 2015

Use a Comparer to sort a generic List

I use lists a lot and most of the time I can sort the data before I load it into a list.  However, occasionally, I find myself in a situation where I really want to sort the data after it has been put into a list.  You can't use LINQ to sort a list.  You have to use the Sort method of the list object, and this method takes an IComparer object as a parameter.

Let's say you have a simple domain object with two properties:

Public Class DomainObject
    Public Property Name As String
    Public Property StartDate as Date
End Class

Then, let's say you have a List that's been loaded up with a bunch of DomainObject's.  Here's the definition:

Dim MyList As New List(Of DomainObject)

First, let's sort by just name.  You first have to create a Comparer class.  The Comparer class is a bit of code that tells the Sort method how to sort.  (NOTE:  If you're list consists of ONE simple type, like string, you don't have to provide the Sort method with a Comparer class.)  Here's a Comparer class that sorts only by the name:

Private Class DomainObjectComparer
    Implements IComparer(Of DomainObject)

    Public Function Compare(x As DomainObject, y As DomainObject) As Integer Implements IComparer(Of DomainObject).Compare

        '-1 means y is greater (i.e. y is AFTER x)
        '0 means x and y are equal.
        '1 means x is greater (i.e. x is AFTER y)

        If x.Name > y.Name Then
            Return 1
        Else
            Return -1
        End If

    End Function

End Class

This function compares two individual DomainObjects.  If x's Name is greater than y's Name, then we return 1.  When we return a 1, we are saying that x is greater than y.  In other words, x will come AFTER y.  The inverse is true when we return -1.  And if we return 0, they are absolutely equal.

Now, all we have to do is instantiate our DomainObjectComparer class and feed the resulting object into the Sort method like this:

Dim MyComparer As New DomainObjectComparer
MyList.Sort(MyComparer)

Now, our list is sorted by the name property.

If you want to sort first by Name and then by StartDate descending, try this:

Private Class DomainObjectComparer
    Implements IComparer(Of DomainObject)

    Public Function Compare(x As DomainObject, y As DomainObject) As Integer Implements IComparer(Of DomainObject).Compare

        '-1 means y is greater (i.e. y is AFTER x)
        '0 means x and y are equal.
        '1 means x is greater (i.e. x is AFTER y)

        If x.Name > y.Name Then
            Return 1
        ElseIf x.Name = y.Name Then
            If CDate(x.StartDate) > CDate(y.StartDate) Then
                Return -1 'Notice here that it's -1 because we want descending order.
            Else
                Return 1
            End If
        ElseIf x.Name < y.Name Then
            Return -1
        End If

    End Function

End Class

Friday, September 25, 2015

Simple CSS "Sticky Footer"

This method would probably need some tweaking to work in older browsers, but for my purposes, it works pretty good:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <style>
        html {
            height: 100%;
        }
        body {
            height: 100%;
            margin: 0px;
        }
        .container {
            background-color: lightgray;
            height: 100%;
        }
        .footer {
            height: 50px;
            background-color: gray;
            margin-top: -50px;
        }
    </style>
</head>
<body>
    <div class="container">
        
    </div>
    <div class="footer">

    </div>
</body>
</html>

Thursday, September 24, 2015

Git push and pull

As I've explained in earlier posts, the command

git push origin master

is used to push changes to a remote repository.  Similarly, the following command

git pull origin master

pulls changes from the remote repository and merges these changes in with your local branch.

Tuesday, September 15, 2015

Implementing Forgot Password and Email Confirmation in ASP.NET Identity

This is one of those tasks that is not very difficult to actually accomplish but exceedingly difficult to find good instructions on how to do it.  Forgot Password is simply a page where the user can enter his or her email address if he has forgotten his/her password.  He/she then receives an email containing a link where the password can be reset.  Email Confirmation means that when a user first registers, he/she cannot log in until the email is confirmed.  How is the email confirmed?  The person is sent an email containing a link to click that will mark the address as confirmed.  This all sounds complicated, but ASP.NET Identity builds all of this for you when you create an ASP.NET web application with Individual Accounts.  However, the code in the AccountController is commented out initially.  Because email is a central part of these operations, you must first configure your email.

To configure your email, just open up the IdentityConfig.vb file.  Find the EmailService class and add code to the SendAsync method.  The code below illustrates some code that sends an email using a traditional SMTP server:

Public Class EmailService
    Implements IIdentityMessageService

    Public Function SendAsync(message As IdentityMessage) As Task Implements IIdentityMessageService.SendAsync
        ' Plug in your email service here to send an email.

        Dim SmtpServer As String

        If System.Configuration.ConfigurationManager.AppSettings("SmtpServer") Is Nothing Then
            Throw New Exception("The SmtpServer key is not present in the web.config file.")
        Else
            SmtpServer = System.Configuration.ConfigurationManager.AppSettings("SmtpServer")
        End If

        Dim FromAddress As String

        If System.Configuration.ConfigurationManager.AppSettings("ConfirmationEmailFrom") Is Nothing Then
            Throw New Exception("The ConfirmationEmailFrom key is not present in the web.config file.")
        Else
            FromAddress = System.Configuration.ConfigurationManager.AppSettings("ConfirmationEmailFrom")
        End If

        Dim MyClient As New System.Net.Mail.SmtpClient(SmtpServer)

        Dim MyMessage As New System.Net.Mail.MailMessage

        MyMessage.From = New Net.Mail.MailAddress(FromAddress)

        MyMessage.Subject = message.Subject

        MyMessage.Body = message.Body
        MyMessage.IsBodyHtml = True

        MyMessage.To.Add(message.Destination)

        MyClient.Send(MyMessage)

        Return Task.FromResult(0)

    End Function

End Class

Once this is configured, go back to your AccountController and uncomment out the appropriate lines.

reCAPTCHA 2.0

The folks at Google have released a new version of their CAPTCHA product named reCAPTCHA.  They refer to the new version as the No CAPTCHA reCAPTCHA.  It's fairly easy to implement even in an ASP.NET MVC web application as I'll show below.

First, go here and sign up.  You input the domains at which your site will be hosted.  LocalHost always "just works" so don't worry about development.  However, if you're testing at a different domain than production, be sure to put both in there.  You'll be given two keys.  The "site" key and the "secret" key.

Implementing the CAPTCHA is a two part process.

First Part - Display the CAPTCHA control for the user to "solve"

Add this to the top of your view:

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

Then add this where you want the CAPTCHA box to appear:

<div class="g-recaptcha" data-sitekey="SITE-KEY-GOES-HERE" ></div>

That's all.

Second Part - Verify that the CAPTCHA was solved correctly

This is the more tricky of the two parts.

Once the user submits the form, reCAPTCHA is going to insert an additional form field named g-recaptcha-response into the form.  This will look like gobbly-gook.  This response along with the secret key needs to be sent to a Google web service.  The web service will return a JSON object that contains a success attribute.  If the success attribute is true, the user solved the CAPTCHA and you can safely assume that he or she is not a bot.

First, in your controller, add a data contract that you can deserialize the JSON response into:

<System.Runtime.Serialization.DataContract>
Private Class GoogleResults
    <System.Runtime.Serialization.DataMember(Name:="success")>
    Public Success As Boolean
End Class

Next, in your post action method within the controller use the following code:

Dim RecaptchaResponse As String = Request("g-recaptcha-response")

Dim MyClient As System.Net.WebClient = New System.Net.WebClient

Dim Reply As String = _
            MyClient.DownloadString(String.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", "SECRET-KEY-GOES-HERE", RecaptchaResponse))

Dim MySerializer As New System.Runtime.Serialization.Json.DataContractJsonSerializer(GetType(GoogleResults))

Dim MyStream = New System.IO.MemoryStream(Encoding.Unicode.GetBytes(Reply))

Dim Results As GoogleResults = CType(MySerializer.ReadObject(MyStream), GoogleResults)

If Not Results.Success Then
    ModelState.AddModelError("", "You must verify that you are not a robot.")
End If

If Not ModelState.IsValid Then
    Return View(model)
End If