Wednesday, May 9, 2018

Persistent Data on website (Cookies, Sessions, and Hidden Fields, Oh My!)

The ability to “save” a user’s data when browsing a website has been a long sought after ability beginning with the efforts of the Roman argentarii of the 3rd century BCE; since then, e-commerce has come a long way. It got a little rocky in the dark ages, but really opened up during the renaissance, and greatly accelerated in the last decades of the 20th century. Today we will learn three different ways to save user data: with hidden fields, cookies, and session data.


Our plan today:

1. Overview/definitions
2. Hidden Fields
3. Cookies
4. Sessions
5. Wrap-up


Overview / Definitions


So first, let’s talk about what these three things are. ‘Hidden fields’ are an object you can use on your page that can hold text data, much like an (invisible) label object, but the data can be stored via accessing a “built-in” data array called ViewState. A ‘Cookie’ is an array of variables you can use in your code behind that are stored (effectively) as a plain .txt file on the users/clients machine. Finally, sessions are a way to store data server side in a structure that is similar to the ViewState object.


Hidden Fields


By far the simplest and most straight forward of the options to implement (imho). All you really need to do is include an object on the webpage via either “asp:HiddenField ID="HiddenField1" runat="server"“ or “input id=”HiddenField1” type="hidden"” if using pure html5. After creating the (input) object itself, you can store whatever data/objects you would like in the object/array. In order to store the data, all you need to do is access the “ViewState” object like you would a dictionary object, or an array with a string/text based index, where said index is made up on-the-fly, like this: “ViewState[“myCustomObjectName”]”. You can assign anything you want to the object, including class objects (as long as they are [Serializable]). For our practice/example code today, we will be using a Person class that defined in its own .cs file in the App_Code folder of an ASP web-page using the master/content schema. It looks like this:

[Serializable]
public class Person
{
   public string FirstName, LastName;
   public Person(string FirstName, string LastName)
   {
      this.FirstName = FirstName;
      this.LastName = LastName;
   }
}

Then, in the content-page, we define the input object like this:

<asp:HiddenField ID="HiddenField1" runat="server">

And finally, in the code behind (or in the server side script section), we have the following code:

protected void Page_Load(object sender, EventArgs e)
{
   if (IsPostBack)
   {
      Label1.Text = HiddenField1.Value;
   }
   else
   {
      Label1.Text = "Page_Load: IsPostBack == false";
   }
}

protected void Button1_Click(object sender, EventArgs e)
{
   if (!string.IsNullOrWhiteSpace(TextBox1.Text) &amp;&amp; !string.IsNullOrWhiteSpace(TextBox2.Text))
   {
      ViewState["objP"] = new Person(TextBox1.Text, TextBox2.Text);
      string viewStateData = ((Person)ViewState["objP"]).FirstName;
      viewStateData += "," + ((Person)ViewState["objP"]).LastName;
      HiddenField1.Value = viewStateData;
   }
}

So, when the page 1st loads, if it’s a PostBack (aka, we’ve been here before), it will put the text data we’ve stored in the HiddenField1 into Label1 (don’t forget to put that somewhere on the page) so we can see what we put in there, in this case, the name of the Person. If this is not a PostBack, we set the label.Text to some debug code so we can see better what is going on.

On the same page we also have 2 textboxes and a button (make sure you stick those in there too if you’re following along). The button, after checking to make sure that the 2 text boxes aren’t empty, will store a new Person object into the “objP” ‘dictionary slot’. What we do then, thanks to the [Serializable] attribute of our Person class, is to save the various members of Person into a comma-separated string; and finally, we store that string into the value attribute of our HiddenField1 input object.

Now, when the form is submitted via PostBack from clicking button1, the ViewState item “objP” gets sent with it, and returned with the new page; that way, in the page_load event we can simply access the HiddenField1 object and set the Label equal to its Value property.


Cookies


Cookies are a simple way to store (non-critical, non-security) user data on a client machine for future retrieval. Often, this takes the form of preferences, and form input fields that haven’t yet been submitted or aren’t stored on the server. To a user, a cookie is a text file that gets stored on the local machine; to a programmer, it is an object that holds an array of strings, or an array of arrays of strings, or an array of arrays of arrays that hold … well, you get the idea. To use them we just create an “HttpCookie” object, and then store strings in it via the following syntax:

HttpCookie thisIsACookieObject = new HttpCookie("myCookieName");
thisIsACookieObject.Expires = DateTime.Now.AddSeconds(10);
thisIsACookieObject["ClickTime"] = DateTime.Now.ToString();
Response.Cookies.Add(thisIsACookieObject);

When accessing the data on subsequent visits, you can call a cookie request and store it in a cookie object. As you can see, we can set the expiration of the cookie relative to the DateTime.Now function, as well as simply setting a static datetime if desired. You could also store sets of info in a complex array such as “thisIsACookieObject[“userData”][“firstName”] = “Bob””. Anyway, back to the cookie we’re trying to request: If that cookie is null, then that cookie doesn’t exist on the client machine and you can create one as normal; if it returns non-null, you can pull the string data from it as follows:

HttpCookie myCookie = Request.Cookies["myCookieName"];
if (myCookie != null)
{
   HttpCookie thisIsACookieObject = Request.Cookies["myCookieName"];
   Label1.Text = thisIsACookieObject["ClickTime"];
}
else
{
   //No Cookie found
}

Because all key value pairs in a cookie are stored as strings, you should always perform validation on the data before you use it to make sure you aren’t accidentally trying to use a name as an int, or a double as Date, etc. You can delete a cookie by using the .Remove command, or by setting the expiration of the cookie to be DateTime.Now.AddDays(-1); - just make sure to do a Response.Cookies.Add(thisIsACookieObject); after setting the expiration date.


Sessions


Sessions are a very user-friendly and easy way to store data. The session is stored on the server, and in most regards functions very similarly to the Hidden-Field method of storing data with the ViewState object. The session is initialized and “saved” as an object with nearly identical syntax, all we would need to do is to revise the code for our button in our hiddenField example as follows:

protected void Button1_Click(object sender, EventArgs e)
{
   if (!string.IsNullOrWhiteSpace(TextBox1.Text) &amp;&amp; !string.IsNullOrWhiteSpace(TextBox2.Text))
   {
      Session["objP"] = new Person(TextBox1.Text, TextBox2.Text);
   }
}

As you can see, we are no longer using the hiddenField in this example. Now, rather than saving all of our data in a string format, we are simply saving the session object to it (technically still as a string behind the scenes, but don’t sweat that). Then, it is accessed much like a server-side cookie, if you will, via casting the strings in the Session object back to the appropriate objects, as shown here:

protected void Page_Load(object sender, EventArgs e)
{
   if (Session["objP"] == null)
   {
      Response.Redirect("HiddenFields.aspx");
   }
   else
   {
      Label1.Text = ((Person)Session["objP"]).LastName + ", " + ((Person)Session["objP"]).FirstName;
   }
}


Wrap-up


So when should we use which method? Well, as a quick and dirty rule of thumb: Page specific data should not be stored in Session, since that can cause issues if multiple tabs/windows are open, so in that case using ViewState is a good alternative. If you only need to access the values in page-specific inputs from the client side, then using Hidden Fields should work fine. Cookies are a good way to store user specific data that relates to the web-site as a whole that you may want to remember for a non-trivial duration. Things related the user as an individual – things like font preference, or color schemes, or a name, or other non-security related info – are good candidates of data to store in a cookie.

Wednesday, May 2, 2018

jQuery or Bust

Welcome back!

jQuery is an open source JavaScript Library that is useful for both confusing English majors who always capitalize the first letter in a sentence, and simplifying a great many tasks that might normally take several additional lines of code were it not employed. It does not, however, do anything new; just about anything you can do with jQuery, you can also accomplish without jQuery. Additionally, there are actually times when using jQuery will slow down your website rather than speeding it up. You can see more about this at “http://youmightnotneedjquery.com”. That being said – jQuery is incredibly popular and useful and we are going to learn how to use a few of its ‘super-powers’.

First, we will start off simple, mainly because I’m not pro at this yet myself, and partly because, well, that’s just usually the best place to start.

One of the first things to note is that you need to have the jQuery library ‘enabled’ on the website you are going to use it on. This is accomplished fairly easily. One way to do it is to install it locally on/in the project that you will be using it with. If you are using VS, you can install jQuery pretty quickly though nuGet. Alternatively, although it is a tad slower, you can have jQuery loaded from an online source, called a “Content Delivery Network”. The way to do this is quite similar to how you would include a css or javascript file in your project, except – there’s no file! Here’s how:

Navigate to the head section of your html file where you have these lines of code.
<script src="scripts/scripts.js"></script>
<link href="styles/style.css" rel="stylesheet" />

Then, just above those add
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>


You can test to ensure jQuery is working on your page by opening the console window in Firefox, Chrome, or most other browsers, and typing “jQuery” into the console command line. If you don’t get an error, everything is working fine. Ok, so now that we have jQuery working, lets look at some of the nifty things we can do with it.

The first thing we are going to do is change the color of some text when we click on it. So, in your project, in your JavaScript tag, go ahead and copy this in (without the enclosing quotes of course): “$(function () {$("body").click(function () {$("body").css("color", "#003b6f");});});”. Looks totally easy and obvious with no explanation needed right? Totally self-explanatory? Great, moving on. What’s that? You want me to go over it anyway, just in case your friend doesn’t understand? Ok, fine.

First off, jQuery seems to mostly be done as inline anonymous functions. I don’t know why, and it seems like a horrible way to code, but it’s what the vast majority of websites seem to do with jQuery. There are a few proponents out there of making the code be more readable by using named functions and classes, and calling them at the appropriate times with arguments, much like you would do for, you know, any other programming language. But we’re not going do that here because, well, I’m not that savvy yet. We are stuck with this “spaghetti code”. That being said, lets see what we have.

Our first bit of code is the jQuery Selector “$”, you use this to let the compiler know that you’re about to throw some spaghetti at it. Then we open our parenthesis to start out code. The first “function() {}” is to tell the compiler that this is an inline anonymous function that should be run when triggered. This first function() is actually optional, but if you don’t include it then you have to include your code in the html page where you want it to run, and that script block has to be at the bottom/end of the page.

I’m not sure 100% why it works like this, but I imagine it has to do with needing all the id’s, div’s, classes, css, etc. to be in-place already before it tries to execute the code. Either way, it is generally “better” to put in this opening anonymous “function()” at the start of your script to ensure that it runs when and where you want it to with the least amount of headache.

Which brings us from “$(function(){});” to “$(function() {$(“body”).click();});”. Here, the Selector symbol (still ‘$’), is letting us know that we want to perform the click event when something is clicked. When what is clicked? “body”. So this is telling us that whenever a user clicks anywhere on the “body” of the html page (which is pretty much anywhere at all), that we should do something. What should we do? We should run a function, which brings us to “$(function() {$(“body”).click(function(){});});”. What should that function do you ask? Let me tell you: it should run the following simple jQuery Command: “$(‘x’).css(‘var’, ‘val’);”.

This is a prototypal jQuery command. In this case you would replace x with whichever html or css identifier you want to manipulate, such as ‘div’, ‘a’, ‘body’, ‘#id’,’.class’, ‘nav ul li’, etc. pretty much any way you would define a css style, you put in here as “what to act upon”. Or more accurately, “what to select”. Var would be replaced with the css tag, like ‘color’, or ‘padding’, or ‘height’ (if the css uses a dash, like ‘font-weight’, you replace it with a camel-cased version, a-la ‘fontWeight’). Then, finally, you replace val with the value you want.

So in our case we end up with “$(‘body’).css(‘color’, ‘003d9b’);”. Then we stick that into our $paghetti, to get the final product of: “$(function () {$("body").click(function () {$("body").css("color", "#003b6f");});});”. Now, on that page, when you click (almost) anywhere, all the text turns #003d9b, or, “Tardis Blue”.

I actually have more to say, and can explain 2 more changes/pages, but I’m running out of time since I’m super behind this week due to my Grad school classes sucking super bad, so I will have to wrap this up for now, and turn it in. The code is done and has all the changes done for the full 3 pages, but since I’m out of time to turn it in, this will have to do for now, and when I have time to update this blog post with the code for the other pages, I will do so.