Thursday, November 30, 2017

November Queso

  1. The Iron Yard Academy is closing all shops.
  2. A would be merger between Sprint and T-Mobile has fallen apart.
  3. Log4j is a Java-based logging utility.
  4. "I Am Rich" is an old iPhone app that cost $999.99 and did nothing.
  5. Rover is like Airbnb for pet sitting.
  6. In 2000, SharePoint was orginally WSS or Windows SharePoint Services.
  7. Smartsheet is software as a service kind of like both SharePoint and Excel.
  8. Airtable lets you collaborate in an Excel sheet format "in the air" and then use an API call to save the records off to a database.
  9. Bitcoin is a kind of cryptocurrency and Coinbase is a wallet for cryptocurrency. Litecoin and Ethereum are other types of cryptocurrency.
  10. There is a way to use ref variables with a standalone delegate in C# even if you cannot do so with a Func or an Action.
  11. Tableau Software makes software for buisness intelligence.
  12. There are no semicolons in CoffeeScript!
  13. J2EE (Java 2 Platform Enterprise Edition) is a run anywhere (Mac, Windows, etc.) Java-flavored development thingamabob (platform) for the web with some canned APIs, JavaBeans, and support for HTML and Java applets.
  14. ZeroMQ is a messaging library for distributed/SOA challenges.
  15. Bamboo is a kind of continuous integration server.
  16. @whatever and @.whatever are both equal and equal to this.whatever in CoffeeScript.
  17. Nullable reference types are coming in C# and this means that the regular reference types will cease being nullable breaking a lot of existing code should you turn this on. The idea is that it will be less painful to go forward this way.
  18. White is a tool for testing WPF and WinForms.
  19. Kentico is a CMS.
  20. You may burn a Blu-ray Disc not unlike how you might have burned a CD a dozen years ago.
  21. T-Mobile will flag applicable text messages as "Scam Likely" when appropriate.
  22. GraphQL is a Facebook-made query language not unlike SQL. See how they both have QL in common?
  23. dice.com is a site like monster.com for finding a job. It is, after monster.com, probably the second biggest player in this space.
  24. The OpenAPI Specification is the name for what was Swagger but is now OpenAPI. Stripe is an API for Ruby-with-Sinatra-flavored web sites.
  25. https://www.visualstudio.com/vs/preview/ is an immediate link for a free version of Visual Studio 2017. Get the Community/Professional/Enterprise versions for free.
  26. The IMEI is an International Mobile Station Equipment Identity for a smartphone. This is mundane. The IMSI or International Mobile Subscriber Identity at the SIM card is a more security critical bit of data.

Wednesday, November 29, 2017

How do I get the distinct values from one column in T-SQL while showing the most current value from a second column?

Declare @StatusesFat TABLE
(
   EmployeeId uniqueidentifier NOT NULL,
   WorkStatus varchar(20) NULL
)
INSERT INTO @StatusesFat

...IMAGINE WHATEVER YOU WANT HERE...

Declare @StatusesFlat TABLE
(
   Id uniqueidentifier NOT NULL
)
INSERT INTO @StatusesFlat
SELECT distinct EmployeeId from @StatusesFat
GROUP BY EmployeeId
Declare @Statuses TABLE
(
   EmployeeId uniqueidentifier NOT NULL,
   WorkStatus varchar(20) NULL
)
INSERT INTO @Statuses
SELECT Id as 'EmployeeId', (SELECT top 1 WorkStatus FROM @StatusesFat
      WHERE EmployeeId = Id) as 'WorkStatus'
FROM @StatusesFlat

In convoluted T-SQL mechanics NOT takes precedence over OR and OR takes precedence over AND.

Honestly though, it would be best to just break up your logic with brackets so you don't have to remember these rules.

Add yourself to a channel in Slack.

Click on "Channels" as the title of the list of channels at the left nav. This fills Slack with the "Browse channels" modal of sorts. Type the name of the channel to join at the first fill-in-the-blank field that has a greyed-out magnifying glass in it followed by: "Search channels"

Tuesday, November 28, 2017

Using Pi in T-SQL!

Yes this is a thing. If you have diameter and you need a translation of it to a circumference, well there you go. I never thought I'd use it, but today I have.

SELECT Size * Pi() as 'Foo' FROM Bar

 
 

decimal(22,7) is the type for this, Pi and things multiplied against it.

Thursday, November 23, 2017

How do I get an image to show up in my Angular 4 app?

This is kinda tricky, huh? If you just make a folder somewhere then paths out to stuff in it will be interpreted as routes in the routing right? That won't do. If you look at angular-cli.json you will find a setting called assets that is probably also set to "assets" too. This setting defines a folder to be for images and hence an exception case for the routing rules. The folder (named "assets") needs to live inside the src folder but not a level deeper in the app folder. Look into it like so:

background-image: url("../../assets/GroverCleveland.png");

 
 

I hope everyone is having a Happy Thanksgiving.

Monday, November 20, 2017

How do I make dropdown list controls in SSRS reports?

When creating a parameter at "Parameters" within the "Report Data" pane in Microsoft SQL Server Report Builder as suggested here a dialog with buttons for General, Available Values, Default Values, and Advanced at the upper left will appear dubbed "Report Parameter Properties" and changing the "Data type:" at the General subsection will change the type of control. The options are Text, Boolean, Date/Time, Integer, and Float and Text tends to make a fill-in-the-blank text field while Date/Time is going to create a calendar control of sorts. To make a drop down list, start off with a Text type control and then switch over to Available Views where "Select from one of the following options:" needs to change from "None" to "Get values from a query" in the name of procuring a set of options. You will be prompted to pick a Dataset. When setting up the "Query type:" for the Dataset it may be wise to select the option for "Stored Procedure" in lieu of the option for "Text" where you could just free form some SQL. The reason is that you may find yourself repurposing queries for dropdowns. It is somewhat tricky to have a nullable option for a dropdown. You may solve the problem with a query like so:

Declare @Options TABLE
(
   CompanyId uniqueIdentifier null,
   CompanyName varchar(100) null
)
INSERT INTO @Options (CompanyId, CompanyName) VALUES (null, null)
INSERT INTO @Options
SELECT CompanyId, CompanyName FROM Company
SELECT * FROM @Options

To set up a new Dataset in an existing Data Source in Microsoft SQL Server Report Builder...

...right-click on the data source in the Report Data pane and pick: "Add Dataset..."

Sunday, November 19, 2017

Stub a service in test in an Angular 4 app.

I just got this working today in a GitHub project you may see here. You will want to use basic IoC dependency injection in your outermost wrapper module as suggested here like so:

providers: [
   Configuration,
   {provide: IpContract, useClass: IpService}
]

 
 

The Configuration above is a pseudoWeb.config as suggested here. It is used in my service like so:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Configuration } from '../../configuration';
import { HttpClient } from '@angular/common/http';
import { IpAddress } from '../models/ipAddress.model';
import { IpContract } from '../contracts/ip.contract';
@Injectable()
export class IpService implements IpContract {
   constructor(private httpClient: HttpClient, private configuration: Configuration) { }
   
   getIp():Observable<IpAddress>{
      let route: string = this.configuration.routeToApi + "api/ip";
      return this.httpClient.get<IpAddress>(route,{});
   }
}

 
 

Our contract looks like this:

import { Observable } from 'rxjs/Observable';
import { IpAddress } from '../models/ipAddress.model';
export class IpContract {
   constructor() {}
   public getIp: () => Observable<IpAddress>;
}

 
 

We may just stub our contract like so:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
import { IpAddress } from '../models/ipAddress.model';
import { IpContract } from '../contracts/ip.contract';
@Injectable()
export class IpContractStub implements IpContract {
   constructor() { }
   
   getIp():Observable<IpAddress>{
      let ipAddress:IpAddress = new IpAddress();
      ipAddress.Ip = "127.0.0.1";
      return Observable.of(new IpAddress()).map(o => ipAddress);
   }
}

 
 

We are going to test a component that has a simple template like so:

<section>{{greeting}}</section>

 
 

...and looks like this on the TypeScript side:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/observable';
import { IpAddress } from '../models/ipAddress.model';
import { IpContract } from '../contracts/ip.contract';
@Component({
   selector: 'ip',
   templateUrl: './ip.component.html'
})
export class IpComponent implements OnInit {
   greeting:string;
   ipAddress:IpAddress;
   
   constructor(public ipContract: IpContract) {
   
   }
   
   ngOnInit(): void{
   this.ipContract.getIp().toPromise().then(
      function(data) {
         this.ipAddress = data;
         this.greeting = "Welcome " + this.ipAddress.Ip + " to Grover Cleveland Hopscotch!";
      }.bind(this),
      function(error){
         console.log(error);
      });
   }
}

 
 

Out test:

import { TestBed, fakeAsync, tick, async, ComponentFixture, inject } from '@angular/core/testing';
import { IpComponent } from './ip.component';
import { IpContract } from '../contracts/ip.contract';
import { IpContractStub } from '../contracts/ip.contract.stub';
import { ActivatedRoute } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
 
describe('IpComponent (shallow)', () => {
   let fixture: ComponentFixture<IpComponent>;
   let component: IpComponent;
   let element;
   
   beforeEach(() => {
      TestBed.configureTestingModule({
         imports: [
            FormsModule
         ],
         declarations: [
            IpComponent
         ],
         providers: [
            {provide: IpContract, useValue: new IpContractStub()}
         ]
      });
      fixture = TestBed.createComponent(IpComponent);
      component = fixture.componentInstance;
      element = fixture.nativeElement;
   });
   
   describe('greeting', ()=> {
      it('should contain ip address', fakeAsync(()=> {
         
         fixture.detectChanges();
         tick();
         fixture.detectChanges();
         fixture.whenStable().then(() => {
            fixture.detectChanges();
            expect(element.querySelector('section').textContent).toContain('Welcome
                  127.0.0.1 to Grover Cleveland Hopscotch!');
         });
      }));
   });
});

How do I turn off the Pascal case to camel case effect in handing objects back from MVC controllers in a .NET Core application?

I attended a tech talk on this once, and, yes: It's not a bug. It's a feature.

services.AddMvc();

 
 

...in Startup.cs should be replaced with the following, expanded line of code to fix the feature per this.

services.AddMvc().AddJsonOptions(opt => opt.SerializerSettings.ContractResolver =
      new DefaultContractResolver());

 
 

This is what it is assuming that JavaScript should idiomatically have names in camel case while C# POCOs should idiomatically have names in Pascal Case. However, you don't want camel case names at TypeScript objects.

Saturday, November 18, 2017

launchSettings.json

In the "Properties" folder of a .NET Core MVC app there is a file called launchSettings.json which has settings for a default route and the application URL.

return Ok(whatever);

...in a .NET Core Controller action will return an OkObjectResult which is a type of an ObjectResult.

How do I make a .NET Core app spit out the NuGet packages it is using as .dll files in the bin folder upon a build?

Open the .csproj file of a project using the stuff to barf out in Notepad and splice this...

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

 
 

...just inside this tag:

<PropertyGroup>

Friday, November 17, 2017

How to use the Parameters filter "controls" in Microsoft SQL Server Report Builder's SSRS reports.

Basically, these are going to fill the place the declared variables with leading @ symbols in your T-SQL query. Just write queries that have dummy values for these at the top of the script and then when it is time to copy and paste your script into Microsoft SQL Server Report Builder just leave off the top of the script where the variables are declared and set.

setting dates in T-SQL from magic strings

The dates here represent wide adoption of Gregorian calendar in Sweden and the comet Swift–Tuttle passing close to Earth:

SET @StartDate = (CASE WHEN @StartDate is null THEN '1753-01-01' ELSE
      @StartDate END)
SET @EndDate = (CASE WHEN @EndDate is null THEN '2126-08-05' ELSE
      @EndDate END)

 
 

'1753-01-01 00:00:00.000' is the long form.

Make some controls for a report in Microsoft SQL Server Report Builder.

At the "Report Data" pane in Report Builder where "folders" are titled Built-in Fields, Parameters, Images, Data Sources, and Datasets, the Parameters folder will hold controls. Right-click here and pick "Add Parameter..." to make your own control for filtering.

Thursday, November 16, 2017

How do I cast an IHttpActionResult from a controller to something sane in C#?

IHttpActionResult actionResult = await myController.Whatever();
var result = actionResult as OkNegotiatedContentResult<string>;

loop through the properties on a JSON object in JavaScript

I stole this from here. I can't find my previous blog post on this topic.

var obj = {
   name: "Simon",
   age: "20",
   clothing: {
      style: "simple",
      hipster: false
   }
}
 
for(var propt in obj){
   alert(propt + ': ' + obj[propt]);
}

A struct is going to be mutable not immutable in C#.

This has a way around that. Basically you take in all parameters as settings at the constructor and then make the getsetters only expose getting. Simple types you don't make yourself like int and DateTime are immutable value types even if the structs you roll yourself are not.

Tuesday, November 14, 2017

blanket turn off push notifications in Google Chrome?

Per this:

  1. In Google Chrome, click on that button that looks like three dots in a vertical line at the upper right.
  2. Scroll down to: "Advanced"
  3. Expand: "Advanced"
  4. In the "Privacy and security" subsection click on "Content settings" line item
  5. Click on: "Notifications"
  6. Turn off "Ask before sending (recommended)" so that setting just says: "Blocked"

 
 

Addendum 2/22/2018: Step one and a half above should read: Go to "Settings"

Throw away saved passwords in Microsoft SQL Server Report Builder 3.0.

  1. Click on that circle in the far upper left that has what I might describe as a meshwork triangle bending back upon itself.
  2. Pick: "Options"
  3. Click the button that says: "Clear all recent item lists"

Monday, November 13, 2017

concatenation with plus symbols in T-SQL

Well, it can be easy if you are just working with varchar types:

SELECT FirstName + ' ' + LastName As Name, Birthday
FROM Whatever

 
 

Otherwise you may need to convert to varchar types:

SELECT CONVERT(varchar(10),SuccessPercentage) + '%' As SuccessRate, Birthday
FROM Whatever

Present a true or false conditional as a query column in T-SQL.

SELECT Foo, CASE WHEN Bar = 'Baz' THEN 'Yes' ELSE 'No' END as Qux
FROM Whatever

If you want 'Are you sure?' as a column for query results in a T-SQL query you have to enclose it in single quotes.

Spaces and question marks do not otherwise play nicely with column names.

SELECT Affirmation, SignOff as 'Are you sure?'
FROM Whatever

Make a generic SSRS report in modern times.

  1. Download Microsoft SQL Server 2008 R2 Report Builder 3.0 here. You will use this as the IDE instead of BIDS.
  2. When the app opens and it tries to bring up a wizard, just close the wizard.
  3. Click on the link at the lower left which says "Connect" and feed the dialog box which appears the URL to your SSRS server.
  4. In the "Report Data" pane where there are "folders" for Built-In Fields, Parameters, Images, Data Sources, and Datasets, right-click on Data Sources and pick "Add Data Source..." to set up a data source, i.e. a connection to a database.
  5. Right-click on Datasets next and pick "Add Dataset..." and then walk through the little wizard that appears. (Change the first radio button from "Use a shared dataset" to "Use a dataset embedded in my report." and then pick a data source and finally paste SQL for a query into the Query window before clicking: "OK")
  6. Click on "Table" at the "Insert" tab at the top ribbon and pick "Table Wizard..." to start stepping through another wizard yet. Select your data set and at the "Arrange fields" portion of the wizard move all of the columns for your query at the "Available fields" subsection to the subsection titled "Values" with a Sigma symbol by it.
  7. Click the "Run" button at the upper left of the "Home" tab at the ribbon to see what you've made.
  8. When you close Report Builder it will prompt you to save a file with an .rdl file extension for the thing you have crafted.

Sunday, November 12, 2017

opening up CORS in a .NET Core MVC project

As suggested here, it is different than what is here. Follow these steps:

  1. Install CORS with this NuGet command:
    install-package Microsoft.AspNetCore.Cors
     
  2. services.AddCors();
    ...goes in the ConfigureServices method of Startup.cs just before...
    services.AddMvc();
     
  3. app.UseCors(builder =>
          builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

    ...goes in the Configure method of Startup.cs just before...
    app.UseMvc();

 
 

I have, this weekend, made a dummy Hello World project that shows off Angular 4 and .NET Core 2.0 playing nicely together complete with tests on both sides of the wire and IoC on both sides of the wire. If you'd like to take a look you may see it here. The CORS thing is one of many challenges I fought with to make this happen.

Saturday, November 11, 2017

ng serve suddenly not working

In setting up .NET Core 2, I seem to have sabotaged the Angular CLI. When I try to run the npm start command to spin up an app I get an error telling me that ng serve ain't there. Following somewhat what is suggested partway down this thread but also doing my own thing a little bit I fixed the problem by destroying outright my node_modules folder and then running these commands:

  1. npm uninstall -g angular-cli @angular/cli
  2. npm install -g @angular/cli
  3. npm install --save-dev @angular/cli
  4. npm install @angular/cli
  5. npm install

upgrading Visual Studio 2017 to use .NET Core 2.0

I undertook the following steps and I cannot say if these had to happen in this order exactly.

  1. I downloaded and installed .NET Core 2.0.
  2. I clicked on the flag in Visual Studio 2017 Professional and then clicked something-er-other to prep an update, though this itself did not update anything.
  3. I closed Visual Studio 2017 Professional.
  4. I typed "Visual Studio Installer" at the start menu to spin up Visual Studio Installer and I let that app do its thing.

Where do I keep the equivalent of Web.config appSettings in an Angular app?

Well, I've made this in the topmost folder side by side with main.ts and index.html:

export class Configuration {
   public routeToApi:string = "http://localhost:61995/";
}

 
 

It has its own file and what you see is the entirety of the file. I loop it in as a provider in my outermost module wrapping everything else and that allows me to pull it in at the constructor line of a service. Is this ghetto?

Friday, November 10, 2017

Flinching paginated lists flinch upon a sort.

The column widths change some don't they? Should we even try to fix this problem or is it normal? A hard fix is going to take the shape of assigning widths to all of the columns and having that which overflows either wrap or get the ellipsis cutoff treatment. There is a happy medium between two extremes however and that entails setting the min-width of the columns allowing them only to collapse only so far. When one column starts to bully the others the change can thus only be so jarring.

integer division versus real division in T-SQL

Dividing integers by integers will give integers for results. In the event of a non-even split in which there is a remainder, an error is not thrown. Instead, SQL just deals with it with rounding to the nearest integer. Surreally, this can produce scenarios is which you may divide not zero by not zero and end up with zero which should be impossible. The fix is to cast the denominator of your "fraction" (that which you will divide by not that which you will divide) to a float just before the cutting like so:

SELECT Foo, Bar, Baz, (Foo + Bar) / CAST(Baz as float) * 100 as Qux
FROM Whatever

Thursday, November 9, 2017

I'm getting more and more comfortable in using Func and Action solutions in C#.

Inside of a Visual Studio solution when project A has some code that reaches into a repository in project B and the method therein has some acrobatics which end up requiring a type from project A even though project B doesn't have the type (in my case I am mapping from a POCO made from consuming Excel sheet gunk and then mapping getsetters from the POCO onto getsetters at an Entity Framework object while casting some string getsetters to getsetters of other types) well the problem may be hacked around by handing in a method from project A to project B as a Func or as an Action. There is a bit of a readability problem with what I have going on stemming from an inability to use ref or out variables. I want to hand in an Entity Framework object and get it back, doctored-up, and then save changes on the context. Well, I shouldn't just get a new variable back from a Func and then attach the new variable to the context in advance of a save as that would be adding something that was already there as the pointer/reference for the object is never broken as it goes into the Func and then back out the other side and even if it was via a deep clone or something the originally object would still be in the context and you still wouldn't want a readd. Since the pointer/reference never breaks. I could get a variable back from the Func, do nothing with it, and then save the context. Well, that is ghetto too. I have settled for handing in the object at the mouth of the method and not returning it at all. Even if an Action returns void a reference type inside of its machinery can get affected and in the next line of code after the call to the Action the object will have the battle scars from the meat grinder it just went through. Not all that readable.

Wednesday, November 8, 2017

bridge tables in Entity Framework's .edmx paradigm and how they behave in code

You could have a many-to-may relationship between clowns and Car with a bridge table made like so. Note that the primary key is a combination of the two primary keys from the Clown table and the Car table and that there is not otherwise a primary key named for the bridge table itself nor any other columns beyond the two that loop in Car and clowns.

CREATE TABLE [dbo].[ClownToCarBridge](
   [ClownID] [uniqueidentifier] NOT NULL,
   [CarID] [uniqueidentifier] NOT NULL,
   CONSTRAINT [PK_ClownToCarBridge] PRIMARY KEY CLUSTERED
   (
      [ClownID] ASC,
      [CarID] ASC
   )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
   IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
   ALLOW_PAGE_LOCKS = ON)
)
GO
ALTER TABLE [dbo].[ClownToCarBridge] WITH CHECK
ADD CONSTRAINT [FK_ClownToCarBridge_ClownID] FOREIGN KEY([ClownID])
REFERENCES [dbo].[Clown] ([ClownID])
GO
ALTER TABLE [dbo].[ClownToCarBridge]
CHECK CONSTRAINT [FK_ClownToCarBridge_ClownID]
GO
ALTER TABLE [dbo].[ClownToCarBridge] WITH CHECK
ADD CONSTRAINT [FK_ClownToCarBridge_CarID] FOREIGN KEY([CarID])
REFERENCES [dbo].[Car] ([CarID])
GO
ALTER TABLE [dbo].[ClownToCarBridge]
CHECK CONSTRAINT [FK_ClownToCarBridge_CarID]
GO

 
 

The way this materializes in code is interesting. There is no ClownToCarBridge C# class. Instead, the Car object will have as a new getsetter an ICollection of Clown objects called "Clowns" and the Clown object will have as a new getsetter, you guessed it, an ICollection of Car objects dubbed: "Cars"

Ternary expressions do not play nicely with nullable types in C#.

DateTime? x = String.IsNullOrWhiteSpace(y) ? null : Convert.ToDateTime(y);

 
 

...cannot compile and must become:

DateTime? x;
if (String.IsNullOrWhiteSpace(y))
{
   x = null;
}
else
{
   x = Convert.ToDateTime(y);
}

The orderBy by pipe which comes with Angular and mfDefaultSorter do not play nicely together.

<tr *ngFor="let person of people | orderBy: 'BirthDate'">

 
 

...probably needs to be replaced by:

<tr *ngFor="let person of people">

 
 

...to fix bust column sorting. Do the initial upfront sort on the TypeScript side like this.

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

This has a good fix for this error. In the partial for modifications which has a sister partial class that inherits from DbContext put something like so:

public override int SaveChanges()
{
   try
   {
      return base.SaveChanges();
   }
   catch (DbEntityValidationException ex)
   {
      var x = ex.EntityValidationErrors.SelectMany(y => y.ValidationErrors).Select(z =>
            z.ErrorMessage);
      string message = string.Join(" ", x);
      message = string.Concat(ex.Message, " The validation errors are: ", message);
      throw new DbEntityValidationException(message, ex.EntityValidationErrors);
   }
}

 
 

This will give you much better reporting. In my particular problem I had made a column/getsetter for a varchar/string not nullable when it should have been nullable. I dropped and recreated the database tables and I opened the .edmx as a big blob of XML and found the two places inside where the column was referenced and I set the nullability state from false to true.

Monday, November 6, 2017

Database Diagrams!

In SSMS 17.1 at the pseudofolders beneath a database in the "Object Explorer" which are titled Database Diagrams, Tables, Views, External Resources, Synonyms, Programmability, Query Store, Extended Events, Storage, and Security, right-click on Database Diagrams and pick "New Database Diagram" to make a visual representation of how some database tables interact (you will be able to cherry pick which tables) not unlike an Entity Framework .edmx. You may right-click in the white space around the diagram to find an option for "Zoom" which does what you'd expect.

painful lessons of .NET Core

  1. Make supporting projects for your UI in a solution in Visual Studio 2017 of .NETCoreApp 1.1 and not of .NETStandard 1.4 as there are not test projects for .NETStandard 1.4.
  2. There really are not mocking frameworks yet working for the before mentioned test projects. You will have to stub everything.
  3. The canned MVC projects will require a different approach to CORS, not like this but perhaps like this.

Sunday, November 5, 2017

Property value is not valid.

One or more values are invalid. Mismatched PageRule with the wrong ItemType.

I got this error attempting to set the "Copy to Output Directory" setting of a .txt file to "Copy if newer" in Visual Studio 2017 at the "Properties Window" that one sees when one presses F4. I Googled against this problem and it just is what it is, you know? The IDE has a bug. To hack around it, right-click on the file that you want to alter in the Solution Explorer and pick "Properties" and that will bring up a little dialog box where you may do the same damn thing only successfully so.

Saturday, November 4, 2017

the base tag in HTML

You stick this in the head tag to define what relative paths in href and src parameters are relative to.

<base href="/">

 
 

This suggests that something like this...

<base href="https://www.w3schools.com/images/" target="_blank"">

 
 

...will keep you free of sprinkling target="_blank" everywhere in markup.

named arguments in C# 7.2

...as opposed to positional arguments, these are variables handed in when calling a method that do not necessarily have to correspond sequentially to the variables at the method signature. You lead a variable with its name followed by a colon to make this happen, and beyond that you otherwise just specify variables as separated with commas as you would normally. Named arguments may even be mixed with positional arguments as suggested here. Something newish with C# 7.2 is that you may have a named argument followed by a positional argument followed by another named argument in lieu of having to have named arguments at the end of calling positional arguments. In that scenario, the second positional argument gets hydrated with the second value. optional and reloadOnChange as given here are examples of named arguments.

I am pleased to report that it is easy to get StructureMap working with a .NET Core application.

Steps:

  1. I ran this command in the NuGet Console in Visual Studio 2017...
    install-package StructureMap
    ...which gave me StructureMap 4.5.2.
     
  2. I followed what was suggested at this to add...
    ConfigureIoC(services);
    ...immediately after...
    services.AddMvc();
    ...in the ConfigureServices method inside of Startup.cs.
     
  3. The line of code I added was red/angry as it tried to find a method that wasn't there. I put this method into Startup.cs to fix that:
    public void ConfigureIoC(IServiceCollection services)
    {
       services.AddTransient<IFlatFileMechanics, FlatFileMechanics>();
    }

 
 

Startup.cs ends up looking like so:

using HelloWorld.Core;
using HelloWorld.Infrastructure;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace HelloWorld.RestApi
{
   public class Startup
   {
      public Startup(IHostingEnvironment env)
      {
         var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
         Configuration = builder.Build();
      }
      
      public IConfigurationRoot Configuration { get; }
      
      public void ConfigureServices(IServiceCollection services)
      {
         services.AddMvc();
         ConfigureIoC(services);
      }
      
      public void Configure(IApplicationBuilder app, IHostingEnvironment env,
            ILoggerFactory loggerFactory)
      {
         loggerFactory.AddConsole(Configuration.GetSection("Logging"));
         loggerFactory.AddDebug();
         app.UseMvc();
      }
      
      public void ConfigureIoC(IServiceCollection services)
      {
         services.AddTransient<IFlatFileMechanics, FlatFileMechanics>();
      }
   }
}

 
 

With modern StructureMap we expect dependencies to be hydrated at controller constructor signatures and that is still true. This worked for me:

using HelloWorld.Core;
using Microsoft.AspNetCore.Mvc;
namespace HelloWorld.RestApi.Controllers
{
   [Route("api/[controller]")]
   public class ValuesController : Controller
   {
      public IFlatFileMechanics _flatFileMechanics;
      
      public ValuesController(IFlatFileMechanics flatFileMechanics)
      {
         _flatFileMechanics = flatFileMechanics;
      }
      
      [HttpGet]
      public string Get()
      {
         return _flatFileMechanics.ReadFlatFile();
      }
   }
}

 
 

Addendum 10/3/2018: If you look close we are not using StructureMap at all. The IoC is just a part of .NET Core now. We don't need to explicitly use StructureMap. I was misguided when I typed this up.

Friday, November 3, 2017

ErrorHandler

I'm not going to think about it today but this and this touch on making your own class that inheirts from (implements) ErrorHandler to catch errors and do things with them. It vaguely appears that all you have to do is loop your creation in as a provider at the outermost module in an Angular 4 app. I could be wrong about that. I've only skimmed the text in these two blog postings. Import ErrorHandler like so:

import { ErrorHandler, Injectable } from '@angular/core';

 
 

Your implemenation needs to be injectable too. So it would seem at a glance. What would we even do with the errors? Log them to the console? Use a REST endpoint to take them back up to the server for real logging?

I want to use LinqToExcel to scrape an Excel sheet's rows to a list of C# POCOs but I don't want all of the getsetters to be strings necessarily.

If you follow my suggestion here you just end up with strings and that is a pretty good place to start. Do not expect to just replace a string with an int or a nullable int as you'll end up with an error like this:

Object of type 'System.String' cannot be converted to type 'System.Int32'.

 
 

What is more, something like a string-to-become-a-DateTime may be in a funny shape in your Excel data and may need to be hit with hammers a little bit to give it the tough love it needs to become a DateTime. I looked into putting getsetters into my POCO that have extra mechanics in them to potentially cast strings to properties of other types on the same object, but that both breaks with the reflection magic I've rolled so far (which expects auto-properties) and just makes a dirty mess. When it is time to write records back to a database, you probably are going to use a different POCO suitable for NHibernate or the code first Entity Framework paradigm or the .edmx Entity Framework paradigm anyways so I would suggest just making a static method in a static utility class somewhere to just map the records complete with all of the casting logic and then get your ETL massage masseuse under unit tests.

Thursday, November 2, 2017

Angular is running in the development mode. Call enableProdMode() to enable the production mode.

Are you sick of seeing this in the console? Me too! In your outermost main.ts file outside of even your outermost module, use this to make this message go away:

enableProdMode();

 
 

In order for this line of code to work you must have this line of code somewhere above it in main.ts:

import { enableProdMode } from '@angular/core';