Monday, November 5, 2018

Learning Ember in VS Code -- Routing: Optional Dynamic Segments

Or more accurately, making me cry about routing. 

I was working on something that I often use as a test development product when trying new tools and design paradigms.  Basically, it's a story publishing system similar in nature to FictionPress.com or FanFiction.net.  I like this, because it's a fairly complex scenario, but still within the realm of (what I see as) an understandable domain. 

I like this as a problem space because it has complex structures.  At its heart is a STORY, and this story would have attributes (such as title, author, category) and 1 to N CHAPTERS.  While each chapter would have attributes (chapter title, content, etc) would have 0 to N COMMENTS. 

This problem domain gives me nested data elements 3 levels deep, multiple avenues for data filtering and congestion, as well as users at various levels which would impact all of the data elements. 
 
So, I started working on it in Ember, and was doing fairly well until I hit where I was building the route needed to view a specific story, a chapter at a time.

What I wanted to do here, was to use dynamic segments to control which story and chapter was displayed to the end user. Specifically, the route would be "/r/:story_id/:chapter_id."  Now there are a few things to remember here.  

The first is that while story_id is the actual identifier for the story to be read, chapter_id is not the chapter identifier, rather it would be the ordinal indicator for that chapter as a sequence within the overarching story.  So, a route of /r/123/3 would be the third chapter of story id 123. 

The second is that chapter_id needed to be optional. If I used the route of "/r/123" then I should have automatically been taken to the first chapter of story 123. Likewise any value outside of a number should also take you to the first chapter, while a numeric value larger than the highest ordinal chapter number should take you to the last chapter.   

But most of that is a back end issue. It's the optional dynamic segment of :chapter_id that's we needed to focus on. After all, optional dynamic segments are a concept that just doesn't exist in Ember. 

Worse, is that every example I saw, didn't allow for multiple levels of dynamic segments where the first of them is required and the second of them is dynamic. 

So, I kicked at it, and created routes and configured them in a dozen different ways until I figured out how I could accomplish this. 

What I did was built two routes.   

The first I named "story" and the second I named "story-chapter."   Then, instead of nesting the second option inside the first (which is how most of the examples performed something similar to what I was attempting, I entered two lines into the Router.map function found in router.js. 


This configuration means that I have to routes for the "/r" root route, one which accepts the story_id dynamic segment, and the second which accepts the story_id and chapter_id dynamic segments. 

Then in the story.js file, I used this to navigate from the story route to the story-chapter route. 


Basically, this is the beforeModel function which processes before any data access on the request.  Since we know that without a chapter_id dynamic segment, we're supposed to go to the first chapter, this takes the behavior of forcing you to that place. 

Of course, in story-chapter.js, we can access the various dynamic segments in this fashion: 


Now, I just need to get that commented aspect of things working the way I expect. 

Monday, October 29, 2018

Lambda Expressions in VB.Net, an Overview


I have to say, lambda expressions are awesome.  

To be explicit a lambda expression is an anonymous method that is used to create delegates or expression tree types. Additionally, they can be passed as arguments or returned as the result of a function  Ideally, they should be short, highly explicit actions.  Additionally, the convenience factor of lambda over traditional delegates is that they can be worked with without giving the method an explicit name and with the code immediately inline where it is to be used.

I first stumbled across lambda expressions in relation to LINQ-to-SQL.  I was wanting to perform some logic on my returned dataset, and all the documentation pointed that lambda expressions were the only way to accomplish what I was wanting.  

The bad part is that at the time, while VB.Net supported lambda expressions there were very little documentation in relation to them. To the point that I just failed to grok them, and ultimately, just used a user function in SQL Server do the work I needed, and went on. What was probably worse, is that Microsoft didn't really show examples of VB.Net lambda expressions for the longest time.  Sure there was the explicit page for VB.Net lambda expressions, but all the sample codes, and the details on how to do the more arcane (and complicated) use cases  were still in C#.  Luckily, that's starting to change, but I still felt the need to build a more basic primer on them and their use in VB.Net.

First is the base declaration syntax.  As in standard methods, lambda expressions which return a result would use the FUNCTION declaration while ones which do not would use the SUB declaration.

Now, in C# you would get a lambda expression built like this:
n=> n.IsReleased

In that, n is the input parameter, and the function returns the IsReleased property of the input. The same logic in VB.Net would be written as:
Function (movie) movie.IsReleased

As is typically the case the VB.Net code is more verbose, but that verbosity also provides a level of clarity which the C# expression lacks. But despite the difference in verbosity, the syntax is strikingly similar. In the C# code, you start with the input parameter which goes into the logic statement.  In the VB.Net code, you start with the function keyword, and its parameter goes into the logic statement.  The difference is in the declaration of the actual method.  In the C# you use the lambda operator, whereas in VB.Net you use the FUNCTION keyword. 

Another thing to consider is that lambda expressions are just a shorthand for anonymous methods.  Anonymous methods are just those methods without a name, rather they're assigned to a variable of delegate type.  In VB.Net an anonymous method would be written like:
dim IsMovieReleased = Function (m as MovieObject) as Boolean 
                                        Return m.IsReleased 
                                End Function 

Now, when the logic extends to more than one line, then we need to use the Function/End Function syntax. For example: 
Function(movie) 
        Console.Log(String.Format("Checked Released State for {0}", movie.Title))
        Return movie.IsReleased 
End Function 

And since the lambda expression is an anonymous function, it can be assigned to a delegate as well.
Dim isMovReleased As Func(of movie, Boolean) = Function(m) m.IsReleased 
Dim movieObject As New Movie With {.IsReleased = True, .Title="Star Trek"}
Dim isReleased As Boolean = isMovReleased(movieObject)

Microsoft has produced a number of predefined anonymous delegates for our use. The FUNC delegate is for methods which return a value, while the ACTION delegate is for methods which don't. Each of them have a number of different possible parameters for a wide range of use cases.

Now, the ACTION delegate is for assigning anonymous methods which doe not return a value. 
Dim logMovie AS Action(of movie) = Sub(m) Console.Log(m.Title) 
Dim movieObject As New Movie With {.IsReleased = True, .Title="Star Trek"}
logMovie(movieObject)

In VB.Net the primary difference in implementation for these two options would be the fact that one uses Sub/End Sub while the other uses Function/End Function. 

Now, as I stated earlier, I first stumbled across lambda expressions in relation to LINQ-to-SQL queries.  What's happen is that the WHERE extension method for IEnumerable(of T) accepts the FUNC(of T, Boolean) delegate.  This means that a method can be applied to the LINQ Queries applied against the datasource.  Using the movie concept, and pulling the released movies, you would generate a LINQ-to-SQL statement like this:
Dim movieList as List(of Movies) = dc.Movies. Where(Function(mv) mv.IsReleased).ToList()

The final use of lambda expressions, and one that I don't typically use, is Expression trees.  Expression trees are representations of code in a tree-like data structure where each of the nodes of the tree is a single atomic expression. Ideally an expression tree would be immutable once defined, and modifying any specific node would mean the creation of a new expression tree which the modifications are applied to, while leaving the existing tree(s) available to the system.

Being able to compile and run the code represented by an expression tree means that the system can enable dynamic modification of executable code, LINQ executions against a database, as well as create dynamic queries.  

Now, imagine this lambda expression:
Dim deleg As Func(of Integer, Boolean)
deleg = Function(f)  0 < f >= 15 

It's purpose is to determine if the passed in parameter  is between 1 and 15.  But it can be built as an Expression Tree in this manner:
Dim expr as System.Linq.Expressions.Expression(of Func)
expr = Function(f) 0 < f >= 15 
Dim deleg As Func(of Integer, Boolean)
deleg = expr.Compile() 

Lambda expressions are one of the better adds to VB.Net over the years, and can lead to a lot of making the code clearer and helping tighten the code significantly.  An aspect that makes code easier to maintain as well as more readable, at least one the initial hurdle of understanding the explicit needs for declaration and use are groked.  And frankly, anything that helps bring clarity, conciseness, maintainability and readability to code is a good thing in my book. 

Monday, October 22, 2018

SQL Server Index Management


SQL Server is a complex thing, and when Always On Availability Groups are applied, that complexity increases (IMO) exponentially.   Of particular note is that Indexes are harder to work with. Well, not harder, but there's a greater overhead for their creation, and subsequently their rebuilding.  You should try to reorganize them as often as feasible. 

Now, I have a client, and this client has a large database. I believe it was sitting at just shy of 500GB the other day. That in and of itself is not an issue, the issue is that this database churns.  This client has a couple of hundred branches, each of which has an instance of this database, which is synchronized back up to the home office. Now, I neither designed nor built this application, but I am helping to monitor the health of the SQL Server, but that churn, that constant moving of data from those 100 or so branches that they had actually added to the system up to the Main Office did horrible, horrible things to the Index Files.  

A reorganization that knocks an index down to 21% fragmentation can be back up to 97% in just a few days. 

What was worse was that a weekly index reorg command was consistently failing.  Likewise, moving it to a nightly even, still caused it to fail. Or sometimes it wouldn't fail, it would just run all week until the weekly server reboot would force kill it.   Which is a terrible thing to happen to an index operation. 

So, I went and found Ola Hallengren's scripts (https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html) and placed them on the server.  And the behavior still occurred.  I cranked it up so that nothing would be done unless the fragmentation was 95% or greater, and it was still failing. 

And as this was going on, the system was becoming more and more unusable.  Queries were ending in minutes not seconds. 

Now, there were very few things I could impact in this situation. I could not change the database structure. I could not change the replication/synchronization methods. I could not change how the applications accessed data.  My hands were well and truly tied.  The only thing I could impact is the index maintenance task itself.  My solution was to add intelligence into the index maintenance.  

First,  I built a query which every couple of hours went out and gathered the physical statistics of the indexes and stored them in a table. Next I made a stored procedure which would add some intelligence into how it was determining which indexes needed to be reorganized. The logic followed these paths: 

  1. Time Limit for Runs. If the procedure has been running for more than 5 hours, end with success  This was done because we decided that fixing five indexes tonight and a different five the next night, is better than never completing. 
  2. Ranking of Indexes.  A big part of the logic is building the list of indexes, and then ranking them.  The system includes all of the indexes
    1. Avg. Fragmentation.  The value had to be greater than 0, and each index has an expected "start point" for consideration as an index to be reorged.  The first aspect of this is to be higher than the expected start off.  Then a higher rank is given to those with a higher difference between the start point and the Average Fragmentation.   For example, if Index 1 has a Start Point of 40 and an Avg Fragmentation of 60 and Index 2 has a Start Point of 80 and an Avg Fragmentation of 85, then Index 1 would have a greater rank since the difference is 20, verses Index 2's difference of 5. 
    2. Priority.  Some indexes are more important than others.  Basically, a table that is used more often in joins and look-ups, we just care more about its indexes than a history table that is only queried every second day. 
    3. Pages.  Items with more than a 1000 pages are given a higher rank, as we're less concerned with fragmentation when an index can be spread over a small number of pages. 
    4. Age.  If an index hasn't been reorganized in 30 days, then we increase its rank exponentially for every day pass 30.
  3. Running.  The system takes the ranked list, and walks it, issuing a reorg command for an explicit single index.

And in general, this worked beautifully.  Over the course of two months, I was able to slowly walk my Starting Point down from 80% to most have a Starting Point of 30%, while a few priority indexes have it set at 15%. 

Then a few days ago, I got a message from the client asking about a specific index that had apparently been escaping notice from the maintenance tasks.  So I started looking, and the first thing I discovered was that the historical logs recorded a 0% as the Average Fragmentation. Now, the database was clearly showing a 97.7% fragmentation, so I knew that there had to be something at issue with my script. 

So, I went and got the Object_ID for the table, and the Index Id for the index, and ran the Physical Statistics function (sys.dm_db_index_physical_stats) for the index in question. 

Which returned me 3 rows. 

I can admit I was not expecting that.  I had not really looked at the documentation for the query, and every index I had checked manually while building the query which performs the checks only returned one row.   Cognitive bias strikes again.  I had seen a behavior in my results sets, and had assumed that the behavior was only possible result set. 


Anyways, with the three distinct rows, the relevant differential was the alloc_unit_type_desc column.   According to MS Docs, that particular column can have 3 possible values:
  • IN_ROW_DATA
  • LOB_DATA
  • ROW_OVERFLOW_DATA 

The IN_ROW_DATA is the one that all the tables have. And it's the 'important' one for what I was doing.  The other two dealt with large objects, and data from columns that have been pushed off-row (https://blogs.msdn.microsoft.com/sqlserverstorageengine/2006/12/13/more-undocumented-fun-dbcc-ind-dbcc-page-and-off-row-columns/). 

Now, how does this ties into the 0% Average Fragmentation that I was logging? Well its simple. I was  executing the command to get the statistics, and log those values atomically, and explicitly.  In other words, I logged each index in turn. 

Now, when looking at the query results from the Physical Stats function, I was storing the relevant values into a single variable prior to insert those values into my log.  Which means that I was keeping the last row returned.  Which was the LOB_DATA row, and thus had a 0% Average Fragmentation while the first row (IN_ROW_DATA) had the 97.7%.

A quick WHERE clause solved the issue, and my index maintenance once again started humming along nicely.

Monday, October 15, 2018

The Case for WebForms in a .NET Core world


I wanted to be able to write a great article on the power of WebForms. Of how they are just easier to use and more stable than MVC or RAZOR.  

I'm not going to lie, I love WebForms, and I've made WebForms dance to my tune for 15 years now. The typical complaints regarding lack of control of the rendered HTML or CSS, I've ignored and basically forced it to perform how I wanted. I understand WebForms. They work like WinForms in a context that to me makes sense. 

So, yes, I wanted to be able to write a great article on why we need them, why we should keep them, and other such things. 

And instead, while doing my research, and hunting for various numbers, I ran across a reference to SharePoint.

The reference in question was discussing a comparison between SharePoint, WebForms and the then just released MVC Framework, and held specific notations how WebForms had more structure than MVC but had none of the "out-of-the-box" functionality of SharePoint. The stance of the author (which I'm still not sure I agree with) was that WebForms had the drawbacks of both, with none of their features.  Like I said, I can't quite agree to that, but the article was enough to get me thinking. 

I mean, I remember SharePoint when it was first released. When it could be used to build websites. Or Intranets. Or whatever someone twisted it to do. 

The thing is, is that it has been years since I last saw a SharePoint install. None of my clients use it, the Network Architects for my company don't spec it, and it's not something I ever think about considering as an option for  my clients. SharePoint is a powerful tool, it integrates with basically every aspect of Office and Windows to produce a data integration tool for Enterprise. I'm not arguing that.  I'm stating that I haven't seen it in years, don't ever think about it, and have a general negative impression of it due to the complexity it invoked when I did last attempt to do something with it years ago. 

Just like MVC. 

When MVC first released, I poked at it a bit, then went back to work building things with WebForms. I didn't like it. It didn't behave the way I wanted to interact with an ASP.Net site. It was C#. And it had so may files to create any given page.  

I never really gave it a fair shot, because in the end building WebForms with VB.Net was faster. I was able to generate an application from design to production at speed and with ease. Which is typically a highly important aspect to things. After all, the three staples of software development are always cost, time and quality. Using WebForms, I was able to impact all three aspects positively and do so consistently.  

Which is the big case for WebForms. If you know what you're doing, working with them is fast; getting an application up and running is trivial. In my opinion, even getting the CSS to behave as expected is easy. 

And that's something meaningful.  Especially as a consultant, building software to solve other people's problems on their dime. 



Monday, October 8, 2018

Learning Ember -- Integrating Bootstrap

This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, part two started our first route, part three added a Click Event to the code while part four introduced components for code reuse. Today's section works on integrating Bootstrap into the framework. 
There is an Ember CLI element that does some of this work for you, but I just worked with integrating the artifacts from the Bootstrap website directly into my project.

To start with, I just worked with the CDN version of Bootstrap (https://getbootstrap.com) as I wanted to get it working before I worried about having downloaded artifacts. So, I first went to the getting started page for Bootstrap which provides the necessary links for CDN.

Then I opened up the index.html file to add the CDN references there, placing them between the content-for components for the "head" and "head-footer" in the HEAD section of this file.
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>EmberLearn</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    {{content-for "head"}}

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"; integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"; integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"; integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"; integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    {{content-for "head-footer"}}

  </head>

This means that the pages will include the Bootstrap elements as they're served. Now, my initial thought was that I'd be able to add the "container" DIV to this file, wrapping it around the content-for component for the body and body-footer. This didn't work. The EMBER content was served outside of the container DIV.

Instead, you need to open up the application.hbs, which is the global template for the Ember content, and add the container DIV here.
1
2
3
4
5
<div class="container">
    <h1>Wish List</h1>

    {{outlet}}
</div>

Elements like the NAVBAR could be implemented in either the index.html or application.hbs files.

But, this isn't the end of things. We now need to style our item-list component to display its content within the context of Bootstrap elements.

So, we open up the item-list component template file, and wrap the H2 element, and the UL elements within row DIVs and column DIVS
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="row">
    <div class="col-12">
        <h2>{{title}}</h2>
    </div>
</div>
<div class='row'>
    <div class="col-12">
        <ul>
            {{#each items as |item|}}
            <li {{action "showItem" item}}><cite>{{item}}</cite></li>
            {{/each}}
        </ul>
    </div>
</div>

This is a step in the right direction, but we also want the items to be displayed in a slightly better context as well. So, we'll switch the LI out for a DIV that implements the CARD class, and replace the UL with a DIV that implements he card-columns class. With a bit of CSS Styling, we end up with a nice set of boxed titles that still react to a user event.

Now, to make this server local assets for the Bootstrap libraries, for scenarios where you don't want functionality to change as things are updated, then you'd download the CSS and JS files and place them in the ASSETS folder of the application.

Then change the references to the CDN to reference "{{rootURL}}assets/" instead. Everything should just work at that point.
Bootstrap Cards

Monday, October 1, 2018

Learning Ember in VS Code -- Adding a Component

This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, part two started our first route  and part three added a Click Event to the code. Today's section works on adding a component to the system to allow for shared user interfaces.

As a programmer, I have to say that Ember components are awesome. These are user interface elements that can be shared in different places in the application. This means either on separate and distinct pages or multiple times on the same web page.

In this situation, I want to turn my list of items into an "item-list" template. Again, Ember has a generator to perform the slog work of boilerplate coding for you.

1
ember generate component item-list

This generator creates:
  1. a component JavaScript class (in app\components)
  2. the component's template (in app\templates\components)
  3. And of course a Unit Test
The first thing we need to do is move the code from our items route template over to our new item-list template. Next we want to parameterize the H2 element with the 'title' attribute. The final change is to modify the word model to the attribute "items."

The code in the item-list component template should read:

1
2
3
4
5
6
7
<h2>{{title}}</h2>

<ul>
    {{#each items as |item|}}
    <li {{action "showItem" item}}><cite>{{item}}</cite></li>
    {{/each}}
</ul>

We also have to remember that the LI has an action associated with it. Thus, we need to move that action from the items route class to the item-list component class.

So, the item-list.js file needs to look like this:

 1
2
3
4
5
6
7
8
9
10
import Component from '@ember/component';

export default Component.extend({

    actions: {
        showItem(item) {
            alert(item);
        }
    }
});

And the items.js file needs to end up looking like this:

1
2
3
4
5
6
7
import Route from '@ember/routing/route';

export default Route.extend({
    model(){
        return ['Friday', 'Dragon Riders of Pern', 'Foundation', 'Ringworld', 'RAMA'];
    }     
});

Then we need to return to the item route template, and wire it up to display our new component element.

1
{{item-list title="List of Books" items=model}}

What's going on here, is that the double curly braces indicate that this is a component, specifically the "item-list" component. The title used is the value passed into that attribute, while the array of items to use is passed into the items attribute, and is the model of the particular page.

In truth, the end result of this should show the exact page as previously, but components are an important concept to know as they allow for code re-usability.

The next entry will see about including Bootstrap into the framework.

Monday, September 24, 2018

Learning Ember in VS Code -- The First Event!


This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, part two started our first route and today we're actually going to have the application do something by having it respond to a mouse click.


Currently, the application shows a list. Not exactly ground breaking, or very useful.  So, what we need is to make the system respond to user interaction. Since this is the web, that interaction is a click event.  

To accomplish this, we add an action to the list item element in the items template.  The action helper takes in the name of the function to run, and the paramters for that function. for this function we'll name it "showItem" (and notice the casing for expected JavaScript styling) and pass it the item object that's referenced in the #each helper.

1
2
3
4
5
6
7
<h2>List of Items</h2>

<ul>
    {{#each model as |item|}}
    <li {{action "showItem" item}}><cite>{{item}}</cite></li>
    {{/each}}
</ul>

The default behavior for the action helper is to add a click event listener to the associated HTML element. This means that clicking the LI element will call the showPerson function from the items route class.

This means we need to modify the items route class file to add this function definition. For now, all we'll do is use an alert dialog to display the book title, later we'll make changes to display more information about the item. 

 1
2
3
4
5
6
7
8
9
10
11
12
import Route from '@ember/routing/route';

export default Route.extend({
    model(){
        return ['Friday', 'Dragon Riders of Pern', 'Foundation', 'Ringworld', 'RAMA'];
    }
    , actions: {
        showItem(item) {
            alert(item);
        }
    }
});

So, now our application is actually doing something.
Ember Alert
Next time, we'll be introducing how to share things appropriately. 

Monday, September 17, 2018

Learning Ember in VS Code -- The First Route


This is my continuing efforts to work with the Ember JS (www.emberjs.org) Framework. The expectation is to build a simple wish list of items.  Part one started the Ember application, while today's section works on adding the first route to the system, where we display a list of items.
The first thing to do is modify the Application.hbs file (found in app/templates/application.hbs) and replace its contents with the below. 

1
2
3
<h1>Wish List</h1>

{{outlet}}

Now, we want to add a route to the system, specifically a route which provides a list of products that need to be shown. Luckily, Ember has a number of generators that make the creation of boilerplate code for common tasks simple and easy.  What this means in practice is that we need to run the below command inside our current Ember application's directory


1
ember generate route items

This command generates the template seen when the user visits the "/items" route, the actual route logic in the application router, and a route object which fetches the model to be used by the template. And you get a unit test. 
So, our first step is to go manipulate the template.  Open the "items.hbs" file found in app/templates and and an h2 tag with the text "Items."  An {{outlet}} line should already exist, and needs to remain for right now. 
After saving, you will be able to navigate to http://localhost:4200/items, and see the new page.
Of course, a template is not much use without the model to display the details of.  So, let's open up the items.js file from the "app/routes" folder.
The boilerplate has an import statement, and the standard extension statement.  We need to add a "model" method. The important part here is that the model method supports any library that uses JavaScript promises. For now, though, we just want to return a simple array.  So, modify the code until it looks like the below:

1
2
3
4
5
6
7
import Route from '@ember/routing/route';

export default Route.extend({
  model() {
    return ['Friday', 'Dragon Riders of Pern', 'Foundation', 'Ringworld', 'RAMA'];
  }
});

Once that's changed, then the model is returning an array of items. In this case, a list of book titles.  Our next step is to tell Ember  how we want to display the array. We need to return to the items template, and add the code to make the program loop through the array and print its contents. 

1
2
3
4
5
6
7
<h2>Items</h2>

<ul>
    {{#each model as |item|}}
    <li><cite>{{item}}</cite></li>
    {{/each}}
</ul>

So, using the "each" helper, we create a list of book titles, also notice the use of the "CITE" tag to emphasis that his is a title. 

Monday, September 10, 2018

Learning Ember in VS Code -- Getting Started


This is a headache and a half.  I mean, I've just spent the past 15 years building ASP.Net applications utilizing WebForms, and was quite happily doing so.  But, an upcoming project has needs; and those needs aren't best served by the traditional WebForms model of ASP.Net.  So, I took a look around and started brainstorming. 

And discovered three big ones. 
  1. React JS (www.reactjs.org)
  2. Angular JS (www.angularjs.org)
  3. Ember JS (www.emberjs.org)

Angular JS has been replaced with just Angular (www.angular.io), which is more monolithic than before. Not a good idea for dealing with initially learning these things. 

But also looking at things, Facebook creates React and Google creates Angular, and Microsoft has .NET starter projects for both.  Which leads to good thoughts towards them. They appear more stable than other options.  But at the same time, they're made by Facebook and Google; and I'm certain those organizations use them in their own applications, which means that their needs are the primary driving force behind both libraries.

Which means that Ember kind of wins in my opinion.

In truth though, all three are kind of the same. You have to have Node.js installed, and then you can use NPM to get the relevant frameworks.  

Building a simple website is just as easy, as it follows a simple paradigm:
  1. Use NPM to perform base configuration 
  2. Add Class to handle things 
  3. Make class do something 
  4. compile and display in browser 

And while that's the 50,000 foot view, that's basically all there is in getting the page to say "Hello World." 

Of course, there's specific details involved, and like I said, I choose Ember.  

First thing is to install it. Which is really just launching Visual Studio Code, opening the terminal (CTRL+`) window and entering the following command: 
    npm install -g ember-cli 

Or just go to the marketplace, or more specifically this page: https://marketplace.visualstudio.com/items?itemName=felixrieseberg.vsc-ember-cli

To begin, open the embedded terminal found within VS Code (CTRL + `) and enter the command to generate a new Ember project (I'm calling mine "ember-learn":
    ember new ember-learn 

What happens, is that the Ember CLI creates a directory in your current working folder named whatever you called your project, and sets up a new Ember application inside of it. 

Once that's done, use the CD command to go into the folder.  

VS Code Example 1Then, since we're using VS Code, use the "Split Terminal" command to create a new terminal window. This is useful, as you will be able to interact with NPM and the EMBER CLI from one window, and have Ember serving the application from the other.  

Once you've split the terminal window, CD to the new folder from that second window and then enter the command:
    ember serve

Note: if you get a message stating "Running without permission to symlink will degrade build performance" then run either VS Code (or your command window) as an Administrator. 

Pointing a browser at the provided localhost port (http://localhost:4200) will get you the compiled website. 

VS Code Example 2

But since I'm wanting a "Hello World" thing, the page currently doesn't say that.  So we need to do a bit of editing to get there. 

And that means making an edit at the root of the application.  Ember provides a template for things that are always shown on the page. This file (application.hbs) is found in the "app/templates" folder. 

VS Code Example 3
I just replaced everything there with the following lines: 
1
2
3
4
<h1>Learning Ember</h1>
<h2>Hellow World</h2>

{{outlet}}
You need the "{{outlet}}" bit, as that's where the nested routes will be rendered.  Important bit there.

Anyways, the system should have detected the change, recompiled, and reloaded the page while you were saving.  



Monday, September 3, 2018

Simple Programmer -- Blogging Course


After my realization regarding the technical debt I was accruing, I made a greater effort to consume information about programming and being a programmer on both hard and soft skills.  One of the ways I did this was turning over my commute time (roughly 40 minutes each way) to listening to programmer based podcasts rather than the radio, and a second way was I bought a couple of books on development.  

What's amusing is that both things led me to John Sonmez.  At this time, I can't remember exactly which podcast it was, but they had an interview with him regarding learning, just being a good programmer and his blog/company Simple Programmer (https://simpleprogrammer.com). And I had also purchased his book The Complete Software Developer's Guide (https://www.amazon.com/dp/B073X6GNJ1) on my Kindle.

So of course I read the book and in the process surrendered my email for some additional content. Which of course got me on a mailing list. 

So here I am, reading this book, listening to podcasts, a number of which focused on "soft skills" and other things just trying to get caught back up, when an item from that mailing list appears offering me the option of enrolling in a email-based blogging course (https://simpleprogrammer.com/blog-course). 

I couldn't argue with the cost (Free!), so I thought why not. 

I mean I have a programming blog, and have had one for a decade now. The first post on it was December of 2006 and I posted quite regularly for the next 5 years, generating a bit over 200 posts until life (2 young kids and a wife) and work apparently overwhelmed my posting schedule.  As an unrelated aside, I also had a SF/Geek-life blog that had nearly twice that many posts in the same time frame. 

So, I had this blog that had not had any new content in seven years, I knew that the best way for me to internalize new information and knowledge was to write about it, and I had just signed up for a blogging course for programmers. 

I'm not going to lie, there is nothing truly new in this course that I'd not seen previously.  It's a solid, well thought out presentation of those elements, and condensed for ease of consumption. 

But I'm also fairly certain that I'm not quite exactly the desired audience as I had ran a blog in the past, and had let it lapse as the time I spent on it was rededicated to my family and completing customer projects at work.  And while I have no complaints regarding the extra time that it gave me with my kids, I also realized that writing the blog was something that kept me learning, and kept my brain engaged. 

Scott Berkun has a book entitled The Dance of the Possible: the mostly honest completely irreverent guide to creativity, and has this to say about creativity:
The word create is a verb. It’s an action. Creativity is best thought of in the same way—it’s something you can use while involved in an activity, like painting, writing, debating or dancing.
Berkun, Scott. The Dance of the Possible: the mostly honest completely irreverent guide to creativity (p. 9). Berkun Media LLC. Kindle Edition.
And this is what the blog was for me. It kept me creative and engaged. It was a verb aspect of how I learned about my craft.

Which is why I think every developer needs one, or a podcast, or a twitch stream, or something that allows them to create and to internalize as they learn.

Monday, August 20, 2018

Using PLUpload with ASP.Net


It's a fairly common use case scenario in which one must allow their users to upload files into a web system for various means. Of course, in the situations I find myself, I need to allow this to happen, and I don't necessarily have a maximum size allowed for the file to be processed.  It's been a while since I last looked into uploading files, and even then I just used the traditional Input Type='File' control that's a part of the standard suite of HTML4 form elements.

Of course I had to push up the number of bytes that were allowed up at any given time, but it was still the simple file upload control. 

Fast forward a few years, and I knew there had to be a better solution. Or at least I hoped there was. 

Prayer was involved as well.  Just saying. 

Anyways, I stumbled into a nice deep hole which involved things like chunking, iFrames, Silverlight and Flash movies.

With a day of research and writing JavaScript already behind me, I  decided that running face first into the brick wall of the exterior of the office would be more productive than continuing the path I was on.  

So, I started looking for controls. 

And quickly found the Telerik suite of controls. Of which I wanted just the one. Sadly, they don't sell them that way. To use the Telerik upload control, I would have to buy the other dozen or so controls I did not need, want or would ultimately use.  And the DevExpress version was bundled in the exact same way. 

So, I continued my search. 

And found PLUpload (https://www.plupload.com/).

A quick download, 10 minutes of reading documentation, and then about two hours of coding, I was streaming chunks of data up to my development web server, and into the database. 5 more minutes, I was then generating a link which I could click that would stream those chunks back to me as the image they started life out as. 

My .ASHX had a fairly straightforward logic built into it, and looked like this: 
 Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        context = context
        Request = context.Request
        Response = context.Response
        sessionId = Request.Cookies("uploadSessionId").Value
        If Request.Files.Count > 0 Then
            Dim fileUpload As HttpPostedFile = Request.Files(0)
            Dim fileName As String = fileUpload.FileName
            If String.IsNullOrWhiteSpace(fileName) Or String.Equals(fileName, "blob") Then
                fileName = If(Request("name"), String.Empty)
            End If 'String.IsNullOrWhiteSpace(fileName) Or String.Equals(fileName, "blob")
            Dim tstr As String = If(Request("chunks"), String.Empty)
            Dim chunks As Integer = -1
            If Not Integer.TryParse(tstr, chunks) Then chunks = -1
            tstr = If(Request("chunk"), String.Empty)
            Dim chunk As Integer = -1
            If Not Integer.TryParse(tstr, chunk) Then chunk = -1
            ' If there Then are no chunks sent the file Is sent As one this likely a plain HTML 4 upload (ie. 1 single file)
            If chunks = -1 Then
                fileName = IO.Path.GetFileName(fileName)
                If Not onUploadStart(0, 1, fileName) Then Return
                If onUploadChunk(fileUpload.InputStream, 0, 1, fileName) Then
                    onUploadComplete(fileName)
                    WriteSucessResponse()
                End If ' onUploadChunk(fileUpload.InputStream, chunk, chunks, fileName)
                Return
            Else ' chunks = -1
                If chunk = 0 Then
                    If Not onUploadStart(chunk, chunks, fileName) Then Return
                End If
                If onUploadChunk(fileUpload.InputStream, chunk, chunks, fileName) Then
                    If chunk >= chunks - 1 Then
                        onUploadComplete(fileName)
                    End If ' chunk >= chunks - 1
                    WriteSucessResponse()
                End If ' onUploadChunk(fileUpload.InputStream, chunk, chunks, fileName)
                Return
            End If ' chunks = -1
        End If ' Request.Files.Count > 0
    End Sub

Basically, I check for something on the FILES upload, and check how many chunks are supposed to be sent for this file, and which chunk this particular file item is.  The behavior is slightly different for a file that has a single chunk (if chunks = -1), but the basic steps are:
  1. If the first chunk, do upload start (in this case, create a record in the db indicating a file is upload, and the user its associated with)
  2. Save the uploaded chunk somewhere 
  3. if this is the last chunk, tell the db that all chunks are uploaded

Then performing the actual file saving aspects, went something like this:

    Private Function onUploadChunk(fs As IO.Stream, chunk As Integer, numberOfChunks As Integer, fileName As String) As Boolean
        Dim newFileName As String = ""
        Dim stream As IO.Stream
        Try 
            // set newFileName from DB
            Dim uploadFilePath As String = IO.Path.Combine(Me.fileLocationPath, String.Format("{0}.{1}",newFileName , chunk.ToString("#000")))
            If IO.File.Exists(uploadFilePath) Then IO.File.Delete(uploadFilePath)
            stream = New IO.FileStream(uploadFilePath, IO.FileMode.OpenOrCreate, IO.FileAccess.Write)
            fs.CopyTo(stream, 16384)
        Catch ex As Exception
            ' Need to set status on this file to bad, as  a chunk failed to upload....
            WriteErrorResponse(ex.Message, 100, True)
            Return False
        Finally
            If stream IsNot Nothing Then stream.Dispose()
        End Try
        Return True
    End Function

Again, fairly straightforward code.  Though a few thinks, my logic records the file that this is, into the database, that means that the file that I'm saving to the file-system, only has a GUID for a name. Then the chunks are given an extension of which chunk they actually are. 

Now, I just need to find the best solution for scanning the files as they're uploaded into the network. 



Blog Widget by LinkWithin