Thursday, February 28, 2019

Change themes at Angular Materials?

This suggests there are four default themes:

  1. deeppurple-amber.css
  2. indigo-pink.css
  3. pink-bluegrey.css
  4. purple-green.css

 
 

Include in a CSS file like so:

@import '@angular/material/prebuilt-themes/deeppurple-amber.css';

random just-getting-started notes on mixing Azure DevOps Pipelines with Octopus deployments

  • 1.$(Rev:r).0 is an example of a version number in Azure DevOps incrementing the minor version.
  • The package application command for an Angular app turns a dist folder into a .nupkg file (NuGet package). This is a part of a build pipeline as opposed to a release pipeline. The .nupkg is one of the Artifacts in Azure DevOps. A release pipeline in distinction takes an artifact and puts it in an environment, copying files onto a server somewhere, etc.
  • At a pipeline in Azure DevOps you may click the three dots in a horizontal progression at the upper right and pick "Export" to make a .json file out of all of the rules that make up that pipeline. There is an "Import a pipeline" beneath the "New" menu at Builds under Pipelines too that may be used to import such a file to be used as a starter for a new pipeline! YAML (Yet Another Markup Language) is apparently used to store the pipelines internally within Azure DevOps, but the YAML gets cast to JSON when exported from the interface.
  • Just as you need an application pool to run a website in IIS, you need an agent pool to run an Azure pipeline. The agent pool denotes the server to do the work of running tests, packaging, etc.
  • A build will have a series of tasks for doing things like running tests and linting. When you add a task you may search for "npm" to find a task type to run npm commands. This will have a drop down containing "install" which runs npm install and "custom" which runs npm run FILLINTHEBLANKHERE alternatively. You will use "custom" and type in "test" to run the unit tests. All of the tasks have a "Control Options" accordion to expand and the "Continue on error" checkbox, which is not checked by default, can allow the build to keep running even if a test fails though I do not recommend such an approach to continuous integration.
  • Under "Builds" under "Pipelines" in Azure DevOps at the upper right, there are two icons. One that looks like a bunch of checkmarks by a bunch of line items for "Recent" and one that looks like a manila folder for "Folders" in contrast. Click the folder icon if you do not see your build. It may have ended up tucked away here if it is not deemed to be recent.

How do I turn Pascal Case into Title Case in TypeScript?

I think there is a way to do that with lodash, as this suggests...

_.startCase('helloThere');

 
 

If you want roll something yourself you can do something like this however my invention can't really account for characters that are not letters. If you want to account for characters that are not letters you would have to check to see if .toUpperCase() and .toLowerCase() off of a character matched up I suppose. My stuff also does not play nice with one letter words like I or A. Anyhow, this will turn this:

export enum Role {
   Administrator,
   ComplianceGroup,
   BusinessUnitSME,
   BUAggregator,
   ReadOnlyAuditor
}

 
 

...into this:

  1. Administrator
  2. Compliance Group
  3. Business Unit SME
  4. BU Aggregator
  5. Read Only Auditor

I'm maybe going to do Jest testing.

Jest tests are basically like Jasmine/Karma tests except that the "it" leading a test is "test" instead of "it" unless you explicitly use "it" which will work too. There is also the concept of snapshot testing. If a snapshot of a component does not exist you may make one which is some sort of blob of data. Going forward, you may compare the blob created in a test to an existing blob to see if the component (including the template) changed (unexpectedly). There is a command (using the U keyboard key) to update snapshots if you are expecting change instead of being wary of it. This snapshot comparison stuff isn't particularly "code first" but that doesn't mean it is bad either.

Wednesday, February 27, 2019

SAP PowerDesigner

It's SAP's version of Balsamiq Mockups as best as I can tell at a glance.

Turn the text value of a TypeScript enum back into something with some spaces in it.

The backflips below account for acronyms.

private GetFriendlyRoleName():string {
   let betterName:string = "";
   if (this.user) {
      let spacelessName:string = Role[this.user.Role];
      let counter = 0;
      while (counter < spacelessName.length){
         if(counter > 0){
            if (spacelessName.charAt(counter) ==
                  spacelessName.charAt(counter).toUpperCase()){
               if (spacelessName.charAt(counter-1) == spacelessName.charAt(counter-
                     1).toUpperCase()){
                  if (counter + 1 < spacelessName.length) {
                     if (spacelessName.charAt(counter+1) ==
                           spacelessName.charAt(counter+1).toUpperCase()){
                        betterName = betterName + spacelessName.charAt(counter);
                     } else {
                        betterName = betterName + " " + spacelessName.charAt(counter);
                     }
                  } else {
                     betterName = betterName + spacelessName.charAt(counter);
                  }
               } else {
                  betterName = betterName + " " + spacelessName.charAt(counter);
               }
            } else {
               betterName = betterName + spacelessName.charAt(counter);
            }
         } else {
            betterName = betterName + spacelessName.charAt(counter);
         }
         counter++;
      }
   }
   return betterName;
}

package-lock.json is npm's version of yarn.lock

We may not really need Yarn anymore. The way it worked its magic was when you ran npm install for the first time and the dependencies in package.json got hydrated to the node_modules folder, a yarn.lock file would get created denoting what specific version, down to the patch, was pulled and what specific server it came from. Of course, both of these things are kind of wishy-washy and, in being subject to change, both of these things can break your app when you get different stuff in a second pass at npm install. If the yarn.lock files exists however, it will be used as guideline to prevent different versions and different servers from being used. In modern times you can do all this without Yarn by getting npm to make a package-lock.json file that does the same trick.

UberConference

It is made by Dialpad and it is like Skype.

Tuesday, February 26, 2019

SecurityException in the System.Security namespace in C#

This is a pretty good type of exception to use in a .NET Core 2.1 middleware breakout like this for throwing HttpStatusCode.Forbidden errors which should return a 403 instead of the more generic 500 you might associate with other exceptions. Pimp out your BubbleUpExceptions playa! It is probably good to also keep the specifics you log from coming back up from the API like so:

public override void OnException(ExceptionContext context)
{
   _logWriting.Log(_whereToLogTo,
         StringManipulations.FlattenException(context.Exception), _timekeeping);
   if (context.Exception is SecurityException)
   {
      context.Result = new JsonResult("{'Message': '" + context.Exception.Message + "'}");
      context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
   }
   else
   {
      context.Result = new JsonResult("{'Message': 'An error at the API occurred. The
            specific error message is being hidden from what the API exposes for security. If
            you have access to the logs you may see a better description free from
            obfuscation therein.'}");
      context.HttpContext.Response.StatusCode =
            (int)HttpStatusCode.InternalServerError;
   }
}

 
 

Addendum 4/30/2019: The use of JsonResult here is bad. See this instead.

A domain controller is a server at your LAN somewhere which has the job of authenticating requests beyond it.

The DC is the gatekeeper.

There are no scaffolders supported for this item.

When you right click and pick: Add > Controller... ...at Visual Studio 2019 Preview, do you see this error? If you do, just try the same act a second time. It will work the second time. This is a Beta hiccup.

Monday, February 25, 2019

Several mid-process databases for the steps in an ETL process?

I really don't know much about the challenges ETL developers face, but I am getting some exposure. I had always envisioned stuff getting moved from a point of origin to a final destination with no other stops along the way, but it turns out that it can get more complicated than that. In an undertaking we are working on we have a concept of a contract and it is represented many different ways in many different systems. There are contracts in both SAP and JD Edwards, for example, and in JD Edwards contracts are spread across eight different tables with unintuitive names. The process we are laying out has records getting pulled from SAP into one database where there will be a Contracts_SAP table and records from JD Edwards getting consolidated from the eight JD Edwards tables into a Contracts_JDE table in the same database. Farther downstream in the process there is a second, different database that will just have a Contracts table and the very different Contracts_SAP and Contracts_JDE tables will have their records massaged into a common format to get records into that table to make things level set.

Sunday, February 24, 2019

architecture: the beat-up and the beautiful

I am playing architect for the first time at work setting up an Angular 7 frontend to talk into what is technically a second application, a .NET Core 2.1 ReST API. This is not me working on an Agile team. This is me cowboy coding with limited oversight. I once botched an interview elsewhere wherein the team wanted someone who could set an app up from end-to-end and I had to qualify that as a worker bee on an Agile team there were really some things that I never touched like the logging implementation or whatever apparatus might be for managing user logins. Well, now it seems I have passed a similar interview instead of failing it and I am in a position where I need to shine. The logging part is easy, but the managing of user logins has led me to make some compromises. A coworker suggested that it was wise to have as much of the Angular app as possible behind the lazy-loading of secondary modules. This, he felt, would allow the application's version of Angular to be easier to upgrade. This seemed smart and I envisioned a scenario in which users would land at a static, bland home page which just had some copy on it and then when navigating the menu system hit a secondary module and lazy-load all of the services. One wrinkle in the works was the manner in which adal.js works. It redirects you to another server and back to your app and when you come back a bunch of gunk chases a pound sign in the URL making it impossible for the URL to be a nested URL in a useHash strategy. You have to come back to the root of the site and thus adal.js is at least one service that must be uploaded upfront and not walled off behind a secondary lazy-loaded module. Ouch! At the C# API side, I have an Onion Architecture approach going on and I wanted to hand the tokens from adal.js that I got from the Angular app mundanely through the UI down to the Infrastructure project where I could have code to interact with Active Directory, yes, walled off. Again, this too is impossible... or at least very hard. All of the examples online for catching the token that I could find wire the token assessment directly into the middleware of Startup.cs in the UI. From there one fishes out who the user is in the controllers in the UI. Yuck! At first this was appalling for me, but then I begrudgingly found acceptance when I realized that the Inversion of Control bootstrapping for my Onion Architecture was happening in Startup.cs anyways and I could thus kinda squint my eyes and tell myself that this was just more of the bootstrapping. Of course the problem with that lie is that the bootstrapping herein is doing more than it really should do. It should not be that fancy-schmancy. It should be stupid, devoid of logic. I've had to make some compromises, eh? While I am speaking of impossible architecture, I want to mention that I'm not a big fan of patterns as there is often little to think about. Maybe you need to know the façade and factory (repository) patterns, but that is it. The others are either esoteric fringe case contortions or of overarching architecture at a level where you won't have to make a decision. The strategy pattern seems legit on the surface and then never comes up. I once botched a different interview (phone screen) in which the company had ten different technologies (at least) going on and when they started a project they just picked the best language for the job. Good luck recruiting candidates guys and good luck doing maintenance. Most places are just on a particular stack and if everything in your environment is Java the next app is going to be Java too. The only thing to wonder about is if you are going to use the latest and greatest Java or the version you've been using. The photos here were taken on the eve of this most recent Christmas Eve in the Mall of America in Bloomington, Minnesota.

another Sunday

Chaos occurs...

Saturday, February 23, 2019

When you accidentally archive something in gmail, how can you find it?

At the left where it says: Inbox, Starred, Snoozed, Sent, Drafts, More ...click on "More" and then "All Mail" at the expanded menu that has Less, Important, Chats, All Mail, Spam, Trash ...you will see, yes, "All Mail" at "All Mail" and you may right-click on any one email item and pick "Move to" to get it to another box.

Friday, February 22, 2019

JAD stands for Joint Application Design

Let's gather in the teamroom and whiteboard together! These jam sessions hammer away ambiguity and get everyone closer to being on the same page.

dbo stands for database owner

This is the default schema name it seems in MSSQL stuff.

Request.Headers.Values

In a controller action in a .NET Core 2.1 MVC implementation, this will have a collection of what is in the header of the HTTP request in.

I saw J. Alan Childs speak on having an offline mode for a mobile app at Minnesota Enterprise Mobile last night.

He uses SQLite databases for keeping data locally and then, when an internet connection is available, there is a way to sync this stuff up to a server of master records somewhere. This of course reminded me of the architecture I was exposed to at the @hand corporation and led me to attend Minnesota Enterprise Mobile which is basically a Xamarin user group when I otherwise probably would not of had much interest. It is the other user group that meets at ILM's office, the first being the Twin Cities .NET User Group which certainly I've attended many times. J. Alan Childs is at the left in the photo here and to the right is Steve Killingbeck introducing him. The wand in foreground is used to read the RFID (radio-frequency identification) tag out of a pig's ear in a manner that gives the user a little more reach and eventually some Bluetooth magic will associate wands like these to Mr. Child's mobile app which has to do with pig farming, a sphere of business in remote locales where there is no 3G (third generation broadband internet), 4G (fourth generation broadband internet), no Wi-Fi, and probably no roaming even, hence demanding the need for an offline mode. A lot of times the pigs are inside of a metal-sided barn and there is no way to even talk to a wireless router in an adjacent building really. Realm databases are also used in Mr. Child's stuff in addition to SQLite. I could tell he likes SQLite better though he admitted that Realm had better performance. He described Realm as MVCesque and not what one typically thinks of as a relational database. Conceptually the "Source of Truth" in a mobile app is one URL to hit for an API regardless of your version of a mobile app. You should talk to a consistent set of endpoints, handing in the version of your app, and then branch to differing code as needed based on the version. This will allow users to stay on older versions for a while without huge pressure to upgrade their mobile app or a breaking change occurring at the API. When syncing stuff to the server, things have to be transaction-based. Either all of the data makes it or none of the data makes it. Think of transferring money from checkings to savings in banking. If some part of the transaction fails. The whole of the transaction needs to be rolled back. If $100 cannot make it to savings then $100 should not just vanish from checkings. Instead of OtterBox cases for tablets, the Kids Case with a handle was recommended for field work. Seach Amazon for "Kids Case" and the product should be findable. This product is a case with a handle on the long edge of an iPad. It's that simple. There are many different vendors at Amazon that sell the Kids Case. Don't expect to scan QR (Quick Response) codes and barcodes in the pig business because things are too dirty and fans are blowing, making pieces of paper wave. UV (UltraViolet) lights may be used to clean smart devices going into areas with livestock to keep them from spreading germs. Your phone is the most unclean thing on you! Bleach can be used to clean it too. If you are trying to get an app approved in Apple's App Store the absence of in-app purchases may make it tricky or at least bring about a long wait. Apple makes a lot of its money off of in-app purchases. Renesas, a type of Japanese Microchip, was namedropped by a member of the audience.

npm uninstall -g YOURNAMEHERE

This should globally uninstall whatever is making your environment sick at npm. I think I've already spoken to this at my blog.

 
 

Addendum 2/23/2019: I thought of something new to say to make this original because I hate dupes. It does not matter what side of the module the -g is on. This is legit too:

npm uninstall YOURNAMEHERE -g

Once I have adal.js working in my Angular 7 app, how may I communicate my identity to a .NET Core 2.1 MVC application?

My Startup.cs is more or less what you see here save for the changes in green below.

Nasty!

using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Authentication.JwtBearer;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Trifecta.Core.ExternalDependencies;
using Trifecta.Infrastructure.ExternalDependencies;
using Trifecta.RestApi.Helpers;
namespace Trifecta.RestApi
{
   public class Startup
   {
      public IConfiguration Configuration { get; }
      
      public Startup(IConfiguration configuration)
      {
         Configuration = configuration;
      }
      
      public void ConfigureServices(IServiceCollection services)
      {
         
services.AddAuthentication(sharedOptions =>
         {
            sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
         }).AddJwtBearer(options => Configuration.Bind("Adfs", options));

         services.AddCors();
         services.AddMvc(options =>
         {
            options.Filters.Add(new BubbleUpExceptions(
               Configuration,
               services.BuildServiceProvider().GetRequiredService<ILogWriting>(),
               services.BuildServiceProvider().GetRequiredService<ITimekeeping>()
            ));
         })
.AddJsonOptions(opt => opt.SerializerSettings.ContractResolver
               = new DefaultContractResolver())
               
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
         ConfigureIoC(services);
      }
      
      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
         if (env.IsDevelopment())
         {
            app.UseDeveloperExceptionPage();
         }
         app.UseCors(builder =>
               builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
         
app.UseAuthentication();
         app.UseMvc();
      }
      
      public void ConfigureIoC(IServiceCollection services)
      {
         services.AddTransient<ILogWriting, LogWriting>();
         services.AddTransient<ITimekeeping, Timekeeping>();
      }
   }
}

 
 

My appsettings.json looks like this:

{
   "Adfs": {
      "Authority": "https://www.example.com/adfs",
      "Audience": "7c67b6a3-3ce6-4b81-a706-68ca145bb4de"
   },
   "FileFolderForLogs": "C:\\Temp\\Logs"
}

 
 

Herein, https://www.example.com/ corresponds to environment.activeDirectoryServer here while the adfs chunk at its end matches up to environment.activeDirectoryTenant and 7c67b6a3-3ce6-4b81-a706-68ca145bb4de would be kept in environment.activeDirectoryClient furthermore. In any of the actions in any of the controllers in my application, I may now do this:

string whoAmI = User.Identity.Name;

 
 

whoAmI will end up with your active directory username it in led by the domain with a backslash between the domain and the username! On the Angular side you have to communicate over the access token like so in order for whoAmI to not be null:

public GetContracts(token: string):void{
   let headers = new Headers({ 'Content-Type': 'application/json' });
   headers.set('Authorization', `Bearer ${token}`);
   let options = { headers, 'observe': 'response' };
   this.http.get(environment.apiUrl + "contract", options).toPromise().then(
      function(data:any) {
         let contract:any = JSON.parse(data._body);
         console.log(contract);
   }, function(error){
         console.log(error);
   })
}

Thursday, February 21, 2019

Unexpected module 'HttpModule' declared by the module 'ContractsModule'. Please add a @Pipe/@Directive/@Component annotation.

I got this error when I accidentally put HttpModule in the declarations metadata property for a module when really it goes in the imports. @angular/http does not come with Angular 7 when you make a new Angular 7 app from the Angular CLI. You need to install it like so at the command line:

npm install @angular/http

 
 

This will allow for looping in HttpModule at a module (at the imports) and Http, Headers, RequestOptions at the service where you have an implementation.

HAL can stand for hardware abstraction layer.

This is a driver to allow the operating system to speak to a specific bit of the hardware, the trackball or something.

Julian date format!

In this format the first two of five numbers represent the year (a twentieth century year) and the last three of five numbers represent how many days into the year we are. 98033 is thus Groundhog's day of 1998.

When importing records en masse into the first-point-on-entry undoctored landing tables for an ETL process upstream of tables of transformed data it may be wise to turn off the RI for ease of speed.

RI is referential integrity.

Why use your own wacky in-house font at the web?

Well, it could be for accessibility. A screen reader may need to be able to distinguish between a lower case l and the number 1 and such.

Linked servers are frowned upon in MSSQL orchestrations as they lead to slow and buggy interactions as one tends to be crossing a domain.

What do instead? You may crosstalk across two databases if the two databases are always going to be on one server together with stored procedures. The alternative is to use SSIS ETL approaches, but these are comparatively more buggy.

Wednesday, February 20, 2019

I now work in Inver Grove Heights.

I commute in from Eden Prairie every day along I-494. The only thing to see in Inver Grove Heights is the Rock Island Swing Bridge across the Mississippi River. I braved the snow today to take this photo. That's the Andeavor petroleum refinery on the other side in St. Paul Park.

Get a SQL script that will make the schema for an entire database in SQL Server Management Studio v17.9.1.

  1. Right-click on the database and pick: Tasks > Generate Scripts...
  2. Use the option for "Script entire database and all database objects" as you complete the wizard to walk through.

install SQL Server 2017 Evaluation Edition!

Go get it! After you get it, click on the "Connect Now" button to see the server name.

When IntelliSense puts the squiggly red line under the name of the table you just made in SQL Server Management Studio v17.9.1...

Go to: Edit > IntelliSense > Refresh Local Cache

SET NOCOUNT ON;

...in a sproc goes immediate before INSERT or UPDATE or DELETE yet after AS.

Create a new schema and move a table on the dbo schema to the new schema.

  1. create schema MySchema
  2. alter schema MySchema transfer [dbo].[MyTable]

If you have enough tables it can help to break them up by schema for readability shake. Also, you may assign permissions/security at the schema level. Yay for T-SQL!

Tuesday, February 19, 2019

leading commas at inbound parameters at stored procedures

This can be a good convention to have. This allows one of the parameters to be easily commented out.

ALTER pr
 
,
,
,
ocedure [dbo].[Update_BusinessUnit]
@BusinessUnitID int
@BusinessDivision varchar(255)
@BusinessUnit varchar(255)
@isProcessing bit

Monday, February 18, 2019

How will archival records jive with schema changes.

Let's say we are making some reports daily with ETL snapshots from elsewhere. The daily records are stored in a history and we want to be able to rerun reports not just from the immediate day but also from a prior point in time. Well, after our app is all set up and working and everything is fine, the day will come when we need schema changes right? How do we not sabotage the archives in changing the schema? When we need to delete a column... Well, we would probably never delete a column. We would just stop reporting on it. New column? Make it null at old records? When a value is null, how can we know if it was null to begin with or null due to after the fact changes? A coworker suggested you have to have a second new column for every column added (and I'd imagine you would also want a column for the ignored pseudodropped columns too) that decried whether or not there was a modification, perhaps a nulls allowed bit type column that was either null or true.

A class-wide protected variable in C# should be in camelCase with a leading underscore.

The same convention for class-wide private variables applies here.

Cherwell

They are a company that has some trouble ticketing software.

Kimball methodology

You should have a star schema or a snowflake (denormalized marts which are denormalized schemas) in addition to your normalized schema per Ralph Kimball's methodology. Bill Inmon's methodology in contrast entails just having a normalized schema and doing reporting off of that. Inmon methodology is also called 3NF for Third Normal Form and this speaks to that.

ODS stands for operational data store.

This is a place to aggregate data to for reporting. I do not mean that this is a denormalized schema, but instead if a parent company and its two different acquisitions all have three different ERPs it might be best to aggregate the data into one place via some ETL magic and do common reporting off of there.

Get the middleware for managing exceptions to also log exceptions in a .NET Core 2.1 application.

Why not? Why write try/catches in the Controllers themselves anymore? BubbleUpExceptions here may just be expanded like so:

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Trifecta.Core.ExternalDependencies;
using Microsoft.Extensions.Configuration;
using Trifecta.Core.Utilities;
namespace Trifecta.RestApi.Helpers
{
   public class BubbleUpExceptions : ExceptionFilterAttribute
   {
      private ILogWriting _logWriting;
      private ITimekeeping _timekeeping;
      private string _whereToLogTo;
      
      public BubbleUpExceptions(IConfiguration configuration, ILogWriting logWriting,
            ITimekeeping timekeeping)
      {
         _logWriting = logWriting;
         _timekeeping = timekeeping;
         _whereToLogTo = configuration["FileFolderForLogs"];
      }
      
      public override void OnException(ExceptionContext context)
      {
         _logWriting.Log(context.Exception, _whereToLogTo, _timekeeping);
         context.Result = new JsonResult(context.Exception);
         context.HttpContext.Response.StatusCode =
               (int)HttpStatusCode.InternalServerError;
      }
   }
}

 
 

This means that Startup.cs has to change some too. Behold:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Trifecta.Core.ExternalDependencies;
using Trifecta.Infrastructure.ExternalDependencies;
using Trifecta.RestApi.Helpers;
namespace Trifecta.RestApi
{
   public class Startup
   {
      public IConfiguration Configuration { get; }
      
      public Startup(IConfiguration configuration)
      {
         Configuration = configuration;
      }
      
      public void ConfigureServices(IServiceCollection services)
      {
         services.AddCors();
         services.AddMvc(options =>
         {
            options.Filters.Add(new BubbleUpExceptions(
               Configuration,
               services.BuildServiceProvider().GetRequiredService<ILogWriting>(),
               services.BuildServiceProvider().GetRequiredService<ITimekeeping>()
            ));
         }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
         ConfigureIoC(services);
      }
      
      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
         if (env.IsDevelopment())
         {
            app.UseDeveloperExceptionPage();
         }
         app.UseCors(builder =>
               builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
         app.UseMvc();
      }
      
      public void ConfigureIoC(IServiceCollection services)
      {
         services.AddTransient<ILogWriting, LogWriting>();
         services.AddTransient<ITimekeeping, Timekeeping>();
      }
   }
}

Saturday, February 16, 2019

When a Task in C# is not a Task of something but just a Task...

Well, such a task is a Task of void. A method like so...

public void WorkshopNcoaIdUpdate(int id, string nocaId)
{
   foreach (var workshop in _context.Workshops.Where(w => w.Id == id))
   {
      workshop.NcoaId = nocaId;
   }
   _context.SaveChanges();
}

 
 

...may be rewritten like so and doing so allows the method to run asynchronously.

public async Task WorkshopNcoaIdUpdate(int id, string nocaId)
{
   foreach (var workshop in _context.Workshops.Where(w => w.Id == id))
   {
      workshop.NcoaId = nocaId;
   }
   await _context.SaveChangesAsync();
}

Friday, February 15, 2019

Fish out specifics about the user from adal.js!

Assuming .GetUserInfo() as described here...

let user = activeDirectoryContract.GetUserInfo();
let name = user.profile.unique_name;
let email = user.userName;

 
 

Well, email is going to end up with the user's e-mail address in it and name will have the active directory login username complete with the leading domain separated by a backslash.

LG phones have a convenience feature for easily blocking unwanted numbers with a press of a button.

LG stands for Lucky-Goldstar.

The type or namespace name 'DataAnnotations' does not exist in the namespace 'System.ComponentModel' (are you missing and assembly reference?)

Fix this with this NuGet command:

Install-Package System.ComponentModel.Annotations

 
 

If you are isolating your POCOs in the core project of an Onion Architecture implementation which will feed an Entity Framework Code First approach in the infrastructure project, you will need to explicitly loop in the annotations for the keys at the .NET Core project for core logic.

The basics of getting adal.js working with Angular 7.

You need a service as seen below. Note that MyModel, which could be named better, is what I offer here. When you redirect to ADFS and back you will land at the redirectUri specified below and the URL will be chased with a pound sign and then id_token= and finally a bunch of gobbledygook which is your token. You may use GetAccessToken() to fish out the token going forward and you will need to hand the token on as a bearer token to every request made to your .NET Core API so that the token may validate the user of the immediacy against Active Directory.

import { ActiveDirectorySettings } from '../models/active-directory-settings.model';
import { MyModel } from '../models/my.model';
import { Injectable } from '@angular/core';
import { ActiveDirectoryContract } from '../contracts/active-directory.contract';
import * as AuthenticationContext from 'adal-angular';
import * as adal from 'adal-angular';
import { environment } from '../../environments/environment';
@Injectable()
export class ActiveDirectoryService implements ActiveDirectoryContract {
   private settings: ActiveDirectorySettings;
   private context: adal.AuthenticationContext;
   
   constructor() {
      this.settings = {
         instance: environment.activeDirectoryServer,
         tenant: environment.activeDirectoryTenant,
         clientId: environment.activeDirectoryClient,
         redirectUri: environment.baseUrl,
         postLogoutRedirectUri: environment.baseUrl + "#/shutout"
      };
      this.context = new MyModel(this.settings);
   }
   
   public GetAccessToken() {
      return this.context.getCachedToken(this.settings.clientId);
   }
   
   public GetUserInfo() {
      return this.context.getCachedUser();
   }
   
   public HandleCallback() {
      this.context.handleWindowCallback();
   }
   
   public IsAuthenticated():boolean {
      return this.GetUserInfo() && this.GetAccessToken();
   }
   
   public Login() {
      this.context.login();
   }
   
   public Logout() {
      this.context.logOut();
   }
}

 
 

If you have { useHash: true } in your routing strategy, and you probably need this, you will find the manner in which the numbers symbol leads the token to be frustrating. It makes it so that you cannot redirect back to a route nested somewhere in your routing. Instead you have to make a custom route for id_token which Angular will interpret as, yes, a route, and then fish the token out from there in a CanActivate route guard like so:

import { Injectable, Injector } from '@angular/core';
import { ActiveDirectoryContract } from '../contracts/active-directory.contract';
import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router';
import { routerNgProbeToken } from '@angular/router/src/router_module';
@Injectable()
export class HomeTokenGuard implements CanActivate {
   private activeDirectoryContract:ActiveDirectoryContract;
   
   constructor(public injector: Injector, private router: Router){
      this.activeDirectoryContract = injector.get(ActiveDirectoryContract);
   }
   
   canActivate(route: ActivatedRouteSnapshot): boolean {
      let pieces = document.URL.split('=');
      if (pieces && pieces.length > 0) {
         let token = document.URL.split('=')[1];
         this.activeDirectoryContract.HandleCallback();
         let user = this.activeDirectoryContract.GetUserInfo();
      } else {
         this.router.navigate(['shutout']);
      }
      return true;
   }
}

 
 

Do not try to fight this. I tried to redirect to a static HTML page in the assets folder, use JavaScript to grab the token and then redirect to a different Angular route and then handle the token from there, but .HandleCallback() cannot deal with the double redirect. At your "home" page/route you will need a CanActivate guard to kick off the login process should one not be logged in. It should look like so:

import { Injectable, Injector } from '@angular/core';
import { ActiveDirectoryContract } from '../contracts/active-directory.contract';
import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router';
import { environment } from '../../environments/environment';
@Injectable()
export class HomeLoginGuard implements CanActivate {
   private activeDirectoryContract:ActiveDirectoryContract;
   
   constructor(public injector: Injector, router: Router){
      this.activeDirectoryContract = injector.get(ActiveDirectoryContract);
   }
   
   canActivate(route: ActivatedRouteSnapshot): boolean {
      if(!this.activeDirectoryContract.IsAuthenticated()) {
         this.activeDirectoryContract.Login();
      }
      return true;
   }
}

 
 

Write something to log individuals back out like so:

if (activeDirectoryContract.IsAuthenticated()){
   activeDirectoryContract.Logout();
}

Thursday, February 14, 2019

IPS stands for in-plane switching and is tech for LCD (liquid crystal display) monitors.

It's modern stuff. This is an improvement on old LED tech, but I don't really understand it.

Waco redux?

News broke today that Amazon will NOT build a headquarters in New York after all after Empire State politicans such as Alexandria Ocasio-Cortez pushed back hard. Does this mean a second chance for Waco?

Apigee

They provide API management software of some sort. There are analytics tools and such. You can do data mining.

Wednesday, February 13, 2019

Decrypt an adal.js and see what is inside!

http://calebb.net/ is a pretty good online tool for as much.

In Visual Studio 2019 Preview "Extensions and Updates..." is the token option in an "Extensions" menu.

This was broken out from the "Tools" menu where it used to live.

adal.js errors!

Error parsing a meta element's content: ';' is not a valid key-value pair separator. Please use ',' instead.

This means you are trying to redirect to a partial URL and not a complete URL. That won't work. Duh.

 
 

Cannot set property 'REQUEST_TYPE' of undefined

This means up are not setting the adal.AuthenticationContext in constructor of your service. It has to happen in the constructor. You cannot just call a method to do this work. You will do so like so:

 
 

this.context = new MyModel(this.settings);

 
 

...while MyModel looks like so:

import * as AuthenticationContext from 'adal-angular';
import * as adal from 'adal-angular';
export const MyModel: adal.AuthenticationContextStatic = AuthenticationContext;

IEEE 1394 is also known as FireWire!

This is another kind of port, not unlike a USB port.

Monday, February 11, 2019

A40 stands for Analysis for Office.

It is business intelligence stuff for SAP.

A rectangle with a wavy line across the bottom represents a report in UML.

The following has a little cheatsheet on what the shapes are. The parallelograms of data transfer are missing huh?

window.location.origin

This is a variant of window.location.href as best as I can tell. In Googling against it I see things that suggest it may misbehave in IE (Internet Explorer). This has a cheatsheet on some of the stuff hanging off of window.location to play with.

Sunday, February 10, 2019

I saw Jesse Sanders speak at AngularMN on Cypress testing on Wednesday night.

Jesse is an Angular GDE (Google Developer Expert) which is the new hotness which is kinda like being a Microsoft MVP (Most Valuable Professional) ten years back. There are only thirty-four Angular GDEs, only twenty of the thirty-four do consulting, and six of the twenty, Mr. Sanders included, work at BrieBug. The art of end-to-end testing, the space where Cypress.io is an emerging player, starts with VB4 (I guess there was a VB4 before VB6) and was done with ActiveX (X a stand-in for numerous diversified things as is the case with DirectX maybe?). In our modern times we have Selenium, WebDriver, Protractor, and Nightwatch and all four of these basically boil down to just being Selenium under the hood which was written in 2004 when the web had an always-leave-the-page-for-the-server-and-come-back-to-a-new-page vibe consistently devoid of API calls for updating the page at hand and certainly long before SPA apps appeared. Attempts to modernize Selenium have been kludgy and end-to-end testing is in many ways still trapped in 2004 with Howard Dean and Hellboy. Criticisms? The tests take too long, fail randomly, and the wait.until paradigm of WebDriver and all of its sisters in sister tools for making sure that one or more asynchronous calls are done resolving are ghetto. Here is another criticism. Maybe we shouldn't be doing end-to-end tests. Maybe we could have one or two of those and then otherwise stub the API, huh? If we don't go in that direction we have wacky workflows in which we pump data into a form in order to get data in the app just so we can test how the data reads. The E2E nature is part of what is slowing us down. These are smoke tests really to make sure all of the API intergration is there. Cypress.io has a way to mock APIs! Cypress.io in contrast to the Selenium quartet is an Electron app written in modern times, beginning in 2015. It has readable error messages, not the mumbo jumbo StackTrace gunk of Selenium. Common libraries like Sinon.JS, jQuery, Underscore, minimatch (converts glob expressions, an alternative to regular expressions, into regular expressions), and Moment.js are baked into Cypress.io. Every time a test fails you get a screenshot and every test will also give you a video of the test running be it pass or fail. npx cypress open opens the testing and runs it before your eyes while npx cypress run runs it at the server. CircleCI can run the Cypress.io tests in continuous integration implementations. The question was asked of how Cypress runs tests and Jesse wasn't sure offhand if Headless Chrome (the new PhantomJS now that PhantomJS is long antiquated) was used under the hood. It is a fact that Cypress.io will only work with Google Chrome for the moment. There was talk of getting it to play with the other browsers. Also, drag-and-drop support is something "coming" that is not yet here. An example of testing, direct from one of Jesse's slides, is:

describe('My actions tasks', () => {
   beforeEach(() => {
      cy.visit('https://example.cypress.io/commands/actions')
   })
   
   it('.focus() - focus on a DOM element', () => {
      
// https://on.cypress.io/focus
      cy.get('.action-focus')
         .focus()
         .should('have.class', 'focus')
         .prev().should('have.attr', 'style', 'color: orange;')
   })
});

 
 

Here is deeper example of doing stuff that doesn't really test anything but shows off some of the how-to. Note the use of the word "enter" in curly braces to simulate character thirteen.

describe('My actions tasks', () => {
   beforeEach(() => {
      cy.visit('https://example.cypress.io/commands/actions')
   })
   
   it('actions', () => {
      cy.get('button').click().dblclick();
   
      cy.get('input#keyword').type('redux{enter}').clear();
   
      cy.get('input#firstName').focus().blur();
   
      cy.get('#iAgree').check().uncheck();
   })
});

 
 

This slide showed off implicit versus explicit testing:

// implicit subjects
cy.get('#header a')
   .should('have.class', 'active')
   .and('have.attr', 'href', '/users')
 
// or explicit subjects
cy.get('tbody tr:first').should(($tr) => {
   expect($tr).to.have.class('active')
   expect($tr).to.have.attr('href', '/users')
})

 
 

Alright, here we having the stubbing. Json Server may be used to fill in what comes back from a faked API call. Json Server is exactly what it sounds like. You use it to make a dummy API to talk to when building out the head for a headless app. When I was at Wells Fargo Advisors we were using it amid an Express app to interact with from Angular.

cy.server()
 
// we set the response to be the activities.json fixture
cy.route('GET', 'users/*', 'fixture:users.json');
 
//or
cy.fixtures('users.json').as('usersJSON');
cy.route('GET', 'users/*', '@usersJSON');

 
 

Beyond Jesse Sanders' talk, a few other interesting things came up. For example I could not resist taking a picture of Will Buck's laptop as he had put stickers over all of the keys.

In particular, I like the use of Ms. Pac-Man and Pac-Man as less than and greater than symbols. While things are not normally taken this far, what is with geeks putting stickers on their laptops? How did this start? If you put stickers on your skateboard in 1989 is this just the thirty years ahead flash forward from that? There was talk of Microsoft sunsetting TFS in favor of GitHub, but also some talk of how it would not happen quickly given the way tech giants love to milk reoccurring contracts around subscriptions to old tech until the bitter end. "The Axe" is a static library for accessibility tools (Axe is the formal name), and Appsee is an accessibly tool which will allow for sensitive bits of information to be blacked-out in testing. There is some corny tool that will convert your web site into a Yahoo! GeoCities-style web site incomplete (maybe) without a MIDI (musical instrument digital interface) file playing. For some reason I did not write down in my notes what this thing was. It might be Geocities-izer which I found in Googling.

Saturday, February 9, 2019

Use EPPlus to loop through the rows of an Excel sheet.

using System.IO;
using ClosedXML.Excel;
namespace Foo.Bar.Baz.Qux
{
   public static class ExcelHelper
   {
      public static void CdsmeNcoaImport(Stream stream)
      {
         using (ExcelPackage package = new ExcelPackage(stream))
         {
            foreach (ExcelWorksheet worksheet in package.Workbook.Worksheets)
            {
               switch (worksheet.ToString().Trim())
               {
                  case "Host Organization":
                     ExcelCellAddress start = worksheet.Dimension.Start;
                     ExcelCellAddress end = worksheet.Dimension.End;
                     for (int row = start.Row; row <= end.Row; row++)
                     {
                        for (int col = start.Column; col <= end.Column; col++)
                        {
                           string setting = worksheet.Cells[row, col].Text;

 
 

This is in contrast to this, and I want to mention that without regard to if it is an IXLWorksheet with ClosedXML.Excel or an ExcelWorksheet of OfficeOpenXml (the EPPlus namespace) the means of getting at the name of a worksheet are the same.

leading a method name with Attempt or LogicFor?

It is has been pointed out to me that every method is attempting to do something and that every method is logic for something. When attempting (forgive the pun) to be explicit, do not be redundant by way of asserting that which is obvious and always applies. This is a paragraph.

Path.Extension() in C#!

This is how to get the path from an IFormFile type that gets hydrated from a file type HTML input control.

if (Path.GetExtension(ThisThing.FileName).ToLower() == ".xlsx")
{

Friday, February 8, 2019

Use environment.ts for the Web.config/appsettings.json settings stuff in an Angular 7 app.

In contrast to this, there is now a default way to keep settings as explained here. There will be an "environments" folder in the "app" folder of any Angular application made with the Angular-CLI and it will have environment.ts inside holding, for starters:

export const environment = {
   production: false
};

 
 

environment.prod.ts will sit beside environment.ts and it holds, for starters:

export const environment = {
   production: true
};

 
 

Loop in the environment at a service like so:

import { environment } from '../../environments/environment';

 
 

Get stuff from the environment like this:

let isProduction = environment.production;

 
 

environment.ts versus environment.prod.ts probably has to do with production mode, huh?

npm install adal-angular

This will bring the Active Directory Authentication Library into your Angular 7 application.

Change your photo in Skype.

Click on the circular avatar! Easier than reading off a teleprompter!

In attempting to play analyst this week and write user stories...

...it occurs to me that a good question to ask is "Could a tester test that?" as a story to do analysis is really a research spike and not a story as there is no way for a tester to test.

In an app I am looking at there are fonts in the assets folder of an Angular application.

There will be a .eot, a .svg, a .ttf, and a .woff file for each font. I do not understand what is going on yet. .ttf is for TrueType font, a 1980s Microsoft format, EOT is Embedded Open Type, and WOFF is Web Open Font Format. OTF, not here, is for OpenType.

copyright symbol

&copy; is the HTML encoding for the copyright symbol. &reg; is the registered symbol. &trade; is for the TM for a trademark. &#8480; is for service marks.

Maplytics has maps for integration with Microsoft Dynamics CRM!

It makes Bing Maps maps specifically.

Thursday, February 7, 2019

I set up the lazy loading of modules in an Angular 7 application for the first time today and in struggling realized that one has to have a routing module breakout for the lazy loaded module!

I do not remember this from earlier versions of Angular, but here it is. Assuming I have a route like so in my main routing module...

{ path: 'contracts', loadChildren: './modules/contracts.module#ContractsModule' }

 
 

...my ContractsModule could be like so:

import { NgModule } from '@angular/core';
import { ContractsComponent } from '../components/contracts.component';
import { ContractsRoutingModule } from './contracts-routing.module';
@NgModule({
   declarations: [ContractsComponent],
   imports: [ContractsRoutingModule],
   providers: [],
   bootstrap: [ContractsComponent]
})
export class ContractsModule { }

 
 

It needs a supporting ContractsRoutingModule like so:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ContractsComponent } from '../components/contracts.component';
const routes: Routes = [
   { path: '', component: ContractsComponent }
];
@NgModule({
   imports: [RouterModule.forChild(routes)],
   exports: [RouterModule]
})
export class ContractsRoutingModule { }

 
 

Do note the use of .forChild above and not .forRoot as .forRoot is to only appear in the main routing module like so:

imports: [RouterModule.forRoot(routes, { useHash: true })],

Azure Service Fabric

...is for building microservices in the Azure space.

Don't let the perfect be the enemy of the good.

a François-Marie Arouet quote that comes up in software all the time (Voltaire got this right.)

Install styles of Angular Materials!

ng add @angular/material

...is going to give you some stylesheet stuff. You will need to pick a theme like so:

Wednesday, February 6, 2019

persona/action/value

This suggests two things for storybuilding:

  1. The convention of: As a _____ I want to _____ so that _____ .
  2. Bake stories into a backlog perhaps using a traditional waterfall document as a starting point.

The three blanks above from left to right have the monikers of persona, action, and value.

Notes from a phone-calls-over-Skype meeting yesterday.

Your "presence" in Skype is the bit of information by your name that says "In a meeting" and if you click on your presence it is the best way to log out of Skype. There will be an option for as much here while just closing Skype does not close Skype really. It runs in the background in that scenario and you are still logged in. You can make multiple phone calls, and you may click on the icon that looks like three dots in a horizontal row to pick an option for Merge to merge phone calls into a conference call. Avaya, Plantronics, and Esperanto Technologies, Inc or ET all make tech in this space, the last of these offering ET-Minion which is architecture that helps with Watt efficiency in electronics and multithreading.

ADAL is the Active Directory Authentication Library, also known as adal.js.

There is also an MSAL (Microsoft Authentication Library) or msal.js which is similar. It is ADAL that we are going to use in an Angular project at work however to do the JWT tokens security stuff. A coworker made this whiteboard drawing here in explaining it to me yesterday. ADFS as shown is Active Directory Federation Services.

@hand may have been a mobile company, but they had an old means for logging in that they never revisited that wasn't terribly mobilesque. You submitted a form, posted to a different page (and not by API ...you left one page for another), and then you got redirected elsewhere upon a successfully login. This of course broke with the whole SPA concept. Downstream of that nastiness you would again have the SPA experience undeterred, so perhaps it was a sacrifice everyone could just live with. This is how ADAL works. When you click a login link in your Angular app a 302 (page temporarily moved) redirect takes you to a form to authenticate against Active Directory and then there is a redirect to the real meat of the SPA app. There is an Auth token for access to the domain and an Access token for what you may do. (Once the front door is open it does not mean that every door inside is open, right?) You can get both of these tokens at once if you are just going to use the JWT tokens to talk to one API, however if you are going to talk to numerous APIs and have differing permissions across them perhaps, well you will need a different Access token for each API. If there are two or more, you need to defer getting the Access tokens until after you have the Auth token. I am not sure why but I suspect that there is overhead in drumming up permissions in diversified systems that is somehow minimized if there is just one system in question. Perhaps you may go to any of the Active Directory services that are the keepers for any one API to also get an Auth token too. I'm not sure yet. Also, if two or more APIs require a second call then it is really good practice to make interacting with a single API require a second call too as this just makes for good, common architecture for later expansions. This sphere of things is the OAuth implicit grant flow. A second call means a second break with the SPA paradigm probably, huh? Well, there is a way around "changing pages" with the calls to get Access tokens by using an iFrame. Yee-haw! Let's hack!

Tuesday, February 5, 2019

HP ALM

It's the Hewlett-Packard Application Lifecycle Management tool! It used to be HP QC (Quality Center) and Mercury before that, or maybe parts of these got incorporated into it. You manage a project with this thing.

branch policies

In Azure DevOps these are the rules policies preventing someone from just merging directly against the master branch or requiring a second party approver, perhaps from a particular group, for a pull request to be merged to master. While I am at this, work items are the stories, tasks, bugs, etc. in the Boards portion of the side menu.

SHOUTcast DNAS

Have your own onlne "radio station" with this stuff. DNAS stands for Distributed Network Audio Server. I don't think SHOUT is an acronym. I think it is in all caps just to be shouting. Winamp is a media player to crosstalk with SHOUTcast. This made me think of the RealPlayer from fifteen years ago before Flash started being the de facto standard for video.

Monday, February 4, 2019

SAP Data Services

Is what is typically used to do an ETL out of SAP (Systeme, Anwendungen und Produkte in der Datenverarbeitung ...or Systems, Applications & Products in Data Processing in English). SSIS isn't really proven for this sort of thing. SAP HANA is a relational database in the SAP space wherein HANA stands for "Hasso's New Architecture" and Hasso Plattner was a cofounder of SAP SE. (Societas Europaea, a European public company)

 
 

Addendum 2/27/2019: There is an SAP HANA Studio (kinda like SSMS) for interacting with SAP HANA.

ADFS stands for Active Directory Federation Services.

It is SSO of an Active Directory flavor.

an Entity Framework 6 example of a spec for the database side length of a string and also the demand that the string be unique

[Index(IsUnique = true), MaxLength(50)]
public string EncodeId { get; set; }

I seem to be distracted from reading "ASP.NET Core 2 and Angular 5" by Valerio De Sanctis as my life gets busy.

Some notes from the last few pages I have read:

  1. material2 is really just another name for Angular Materials.
  2. Foundation, Pure, Materialize, UIKit, and Skeleton are Bootstrap rivals.
  3. Web Compiler by Mads Kristensen is a Visual Studio plugin for either LESS or Sass while CompileSass by Same Rueby just compiles Sass and uses LibSass to do so which beyond Visual Studio and CompileSass compiles Sass for many languages including a language called Crystal per this which I had not heard of before this morning.
  4. Guards in LESS prevent a mixin from ever being evaluated if a condition is not met.
  5. You may have loops in LESS. You may hand a number to one of these and then have it n number of times shrink or expand a div an n multiple of 10px or such.

Mule is a Java-based ESB.

ESB stands for Enterprise Service Bus.

Sunday, February 3, 2019

Get .debounceTime working with an autosuggestion feature in an Angular 6 application.

One of things this FormControl has going for it...

import {FormControl} from '@angular/forms';

 
 

...is that you may do a .valueChanges.debounceTime(500) off of a FormControl type variable, but then again... everyone hates the forms. What if you just want to make something simple like this...

<input id="iAmSpecial" />

 
 

...in the template of a component and have it serve as a search box for searching wherein there is an autocomplete feature that goes to the server based on what you type but which will wait until you are done typing for a half second so that it does not just go to the server every time you type a letter? Alright, let's make that happen. First of all, I thought this would have to do with doing a .debounceTime off of the Observable I got back from the server/API, but really we need to do a .debounceTime before we ever reach the code that tries to even call out to the server/API. This has an example and we will need these imports at our component.

import { Component, OnInit, HostListener, OnDestroy } from '@angular/core';
import { debounceTime } from 'rxjs/operators';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';

 
 

In our component we need two private variables like so:

private subject = new Subject();
private subscription: Subscription;

 
 

We also need two events in our component:

  1. ngOnInit(){
       this.subscription = this.subject.pipe(
          debounceTime(500)
       ).subscribe((e:any) => {
          alert(e.srcElement.value);
       });
    }

     
  2. ngOnDestroy() {
       this.subscription.unsubscribe();
    }

 
 

I know the any above is a bit hacky and also you won't want to have an alert right? Instead of the alert you will want to either call a different method that calls the server/API or I guess you could less elegantly just have the code you might have in that method where the alert is without any more abstraction. Lastly, we need a HostListener to make all of the magic work. An example:

@HostListener('keyup', ['$event'])
clickEvent($event) {
   if ($event && $event.target && $event.target.id == "iAmSpecial")
   {
      $event.preventDefault();
      $event.stopPropagation();
      this.subject.next($event);
   }
}

Saturday, February 2, 2019

Doctor up n number of records in Entity Framework 6's code first paradigm.

foreach (var card in _db.Cards.Where(c => c.Suit == suit))
{
   card.Digit = digit;
}
_db.SaveChanges();

 
 

What is above works and what is below does not.

_db.Cards.Where(c => c.Suit == suit).ForEachAsync(c => { c.Digit = digit; });
_db.SaveChanges();

 
 

The .ForEachAsync approach will break because the code will run before the .Where can bring records back from the database. You do not want to chain things in such a manner. You also don't want to break records to edit off of the context and reattach them with .Attach as seen below as that did not work for me either.

List <Card> cards = _db.Cards.Where(c => c.Suit == suit).ToList();
cards.ForEach(c =>
{
   c.Digit = digit;
   _db.Cards.Attach(c);
});
_db.SaveChanges();

Kick the iPhone X awake when the screen freezes.

  1. Press volume up.
  2. Press volume down.
  3. Press the power button on the right side of the device opposite the two volume buttons on the left edge.

To keep the phone from freezing to begin with it might be best to power it down and then up at least once a week. Do that by holding the power button and the volume up button together. This act will both power down and power up the phone. You need to take a break between the two actions. Do not except the phone to power down and then back up again while you consistently squeeze it.

Friday, February 1, 2019

Rollback to a reasonable Entity Framework 6 migration when you change branches to start a new story?

This could be a smart move. If you don't do this you are apt to make a migration in your new story that trys to drop a column that won't exist in other environments or some other tangled gobbledegook of horror. Just fall back to before the things you just did in the story you stepped away from. If you can merge to dev right away you can just branch the new story from dev to get around this pain point, but if you have to wait on a pull request...

transactions in Entity Framework 6's code first approach to things

using (var transaction = _context.BeginTransaction())
{
   try
   {
      
DO WHAT NEEDS TO BE DONE HERE
      await _context.SaveChangesAsync();
      transaction.Commit();
   }
   catch (Exception ex)
   {
      transaction.Rollback();
      throw ex;
   }
}

 
 

Instead of .SaveChangesAsync() you may just have .SaveChanges() and I bet you can imagine the difference.