https://www.justinbuchanan.com/blogJustin Buchanan20222022-01-07T03:57:23Zhttps://www.justinbuchanan.com/blog/blog/images/dsc_4729_resized.jpgYet Another Bloghttps://www.justinbuchanan.com/blog/posts/developer-tools-install-2020Developer Tools to Install - 2020 Edition2020-07-03T00:00:00Z<p>Since I'm starting a <a href="./posts/chemvm">new role with ChemVM</a>, I decided to document what I install on a new dev machine.</p>
<blockquote class="blockquote">
<p>For this go around, I switched from a Dell Precision 5530 to a Thinkpad X1 Extreme Gen 2. I may document my experience with that switch elsewhere, but suffice to say I really like everything about the Thinkpad, with the possible exception of where they put the Fn key.</p>
</blockquote>
<p>First up, the basic stuff to install.</p>
<h2 id="microsoft-edge">Microsoft Edge</h2>
<p>I've mostly switched to using <a href="https://www.microsoft.com/en-us/edge">Microsoft Edge</a> (chromium) for my daily browser and for development.</p>
<h2 id="firefox">FireFox</h2>
<p>My previous default browser, I still love <a href="https://www.mozilla.org/en-US/firefox/">Firefox</a>. Gotta at least have it for testing.</p>
<h2 id="chrome">Chrome</h2>
<p>I install <a href="https://www.google.com/chrome/">Chrome</a> mostly just for testing/debugging.</p>
<h2 id="office">Office</h2>
<p>We are running <a href="https://www.microsoft.com/en-us/microsoft-365/compare-all-microsoft-365-products?&activetab=tab:primaryr2">Microsoft 365 Business Standard</a>.</p>
<h2 id="notepad">Notepad++</h2>
<p>I <a href="https://notepad-plus-plus.org/downloads/">use npp</a> every day for editing all kinds of text files.</p>
<h2 id="windows-terminal">Windows Terminal</h2>
<p>The new <a href="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab">Windows Terminal</a></p>
<h2 id="visual-studio">Visual Studio</h2>
<p>Next is <a href="https://visualstudio.microsoft.com/">Visual Studio</a>. Since we are a startup, I'm giving Community edition a go. Community is more or less the same as Professional, and is free for 5 users in an organization with less than 1 million in revenue.</p>
<p>Here's the workloads and extensions I install:</p>
<ul>
<li>Workloads
<ul>
<li>ASP.NET and Web Development</li>
<li>Azure Development</li>
<li>Node.js Development</li>
<li>Data Storage and Processing</li>
<li>.NET Core Cross Platform Development</li>
</ul>
</li>
<li>Extensions
<ul>
<li><a href="https://visualstudio.github.com/">GitHub Extension for VS</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.OpenCommandLine">Open Command Line</a> by <a href="https://www.madskristensen.net/">Mads Kristensen</a> configured to open Windows Terminal</li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.CSSTools">CSS Tools 2019</a> again by Mads</li>
</ul>
</li>
</ul>
<h2 id="visual-studio-code">Visual Studio Code</h2>
<p>While I still prefer the full Visual Studio, I use Code for smaller projects, editing this blog, and such. <a href="https://code.visualstudio.com/">Download here</a>.</p>
<h2 id="nodejs-lts">nodejs LTS</h2>
<p>For Angular FE development among other things. <a href="https://nodejs.org/en/">Download here</a>.</p>
<h2 id="github-desktop">GitHub Desktop</h2>
<p>I've been using this less and less as the git tooling in VS and VSCode get better, but I still use it from time to time. <a href="https://desktop.github.com/">Download here</a></p>
<h2 id="git-for-windows">Git for Windows</h2>
<p><a href="https://git-scm.com/download/win">Download here</a></p>
<h2 id="azure-storage-explorer">Azure Storage Explorer</h2>
<p>I <a href="https://azure.microsoft.com/en-us/features/storage-explorer/">Storage Explorer</a> to manage Azure Storage accounts, transfer files, manage folders, etc.</p>
<h2 id="azure-cosmosdb-emulator">Azure CosmosDB Emulator</h2>
<p>This applies because we are using <a href="https://azure.microsoft.com/en-us/services/cosmos-db/">CosmosDB</a>. You can <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator#installation">download the emulator here</a>.</p>
<h2 id="ubuntu-via-windows-subsystem-for-linux-wsl">Ubuntu via Windows Subsystem for Linux (WSL)</h2>
<p>I use <a href="https://ubuntu.com/wsl">WSL</a> mostly for testing .NET Core on Ubuntu. I used to use it and putty for ssh, but now that ssh is baked into Windows 10, I don't need to.</p>
<h2 id="nuget-package-explorer">NuGet Package Explorer</h2>
<p>For inspecting nuget packages. <a href="https://github.com/NuGetPackageExplorer/NuGetPackageExplorer">Website</a></p>
<h2 id="paint.net-or-photoshop-or-photoshop-express">Paint .NET or PhotoShop or Photoshop Express</h2>
<p>I've used both <a href="https://www.getpaint.net/download.html">Paint.NET</a>, real Photoshop, and <a href="https://www.adobe.com/products/photoshop-elements.html">Photoshop Elements</a> over the years. Recently, I've found for most of what I</p>
<h2 id="inkscape">InkScape</h2>
<p>For manipulating SVG files, I use the <a href="https://inkscape.org/">InkScape vector graphics software</a></p>
<p>Since I'm starting a <a href="./posts/chemvm">new role with ChemVM</a>, I decided to document what I install on a new dev machine.</p>https://www.justinbuchanan.com/blog/posts/chemvmChemVM2020-06-19T00:00:00Z<p>Today marks the last day of a 9 year journey with csg. Next week, I'll be starting a new journey as the CTO of ChemVM Technologies. You can find out <a href="https://www.chemvm.com">more about us here</a>.</p>
<p>It's been a great ride a csg, and you should <a href="https://www.csgsolutions.com">check them out</a> if you need a technology partner for data analytics, business intelligence, custom software, and lots more.</p>
<p>Today marks the last day of a 9 year journey with csg. Next week, I'll be starting a new journey as the CTO of ChemVM Technologies. You can find out <a href="https://www.chemvm.com">more about us here</a>.</p>https://www.justinbuchanan.com/blog/posts/create-dotnet-new-templateCreating a Solution Template for the .NET Core CLI2020-06-05T00:00:00Z<p>Consistency is important in software development. From folder names to variable names,
the more consistent a codebase is, the more easy it is to work in.
At <a href="https://www.csgsolutions.com">csg</a> we aim to have a consistent
approach to different custom software applications we build for our
clients. One of the early ways we practice this is by starting each
new git repo with common set of files and folders. Until recently,
the workflow to accomplish this has been to clone what we call the
"Skeleton" repo for a particular project type (API, website, class library, etc.), and
then do a bunch of renames of namespaces, folders, etc. It turned out to be really
easy to take our existing "skeleton projects" and turn them
into <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/custom-templates">custom templates for dotnet-new</a>.</p>
<p>While there are many <a href="https://github.com/dotnet/templating/wiki/Available-templates-for-dotnet-new">freely available templates</a> for
dotnet-new, we find it useful to have a lot of the boilerplate we would build out directly in a template.</p>
<p>A typical skeleton structure we might use for a website use looks something like this:</p>
<ul>
<li>build
<ul>
<li>repo.props</li>
</ul>
</li>
<li>src
<ul>
<li>Skeleton.Classlib1</li>
<li>Skeleton.Classlib2</li>
<li>Skeleton.Website</li>
</ul>
</li>
<li>tests
<ul>
<li>Skeleton.TestProject1</li>
<li>Skeleton.TestProject2</li>
</ul>
</li>
<li>.gitignore</li>
<li>azure-pipelines.yml</li>
<li>build.ps1</li>
<li>Directory.Build.props</li>
<li>SkeletonWebsite.sln</li>
<li>version.json</li>
</ul>
<p>This structure is similar to (and was mostly ripped off from) some of the <a href="https://github.com/aspnet/">ASP.NET repo</a>
structures circa 2017. I won't go into what all these files are in this post, but most of the meat is in the src/ folder,
where various class libraries and other projects go. Some solutions have lots of projects,
some have only a few. The contents of the various files in the project might look something
like this:</p>
<pre><code class="language-csharp">using System;
namespace Skeleton.Api.Controllers
{
[Authorize]
[ProducesResponseType(401)]
[Route("api/[controller]")]
[ApiController]
public class WidgetController : ControllerBase
{
private readonly ISkeletonRepository _repo;
public WidgetController(ISkeletonRepository repo)
{
_repo = repo;
}
}
}
</code></pre>
<p>Note that the code contains classes, interfaces and other identifiers containing the word Skeleton. To turn this structure into a template, first I added a folder named <em>.template.config</em>, and inside place a file named <em>template.json</em> which looks like this:</p>
<pre><code class="language-json">{
"$schema": "http://json.schemastore.org/template",
"author": "Justin R. Buchanan",
"classifications": [ "ASP.NET", "Website", "Solution" ],
"identity": "Csg.Templates.AspNetCore.Website",
"name": "CSG ASP.NET Core Website Solution",
"sourceName": "Skeleton",
"preferNameDirectory": true,
"shortName": "csgaspnetweb",
"symbols": {
"title": {
"type": "parameter",
"datatype": "string",
"replaces": "PROJECT-TITLE",
"isRequired": true,
"description": "The display name used in assembly info and as the default website title"
}
},
"sources": [
{
"modifiers": [
{
"exclude": [
"\*\*/.git/\*\*",
"\*\*/.vs/\*\*"
]
}
]
}
]
}
</code></pre>
<p>The important bits above are <em>sourceName</em>, which is used to search and replace file contents, and <em>shortName</em>, which is used when creating an instance of this template from the CLI. After publishing this template, developers will be able to create instances using the dotnet cli as follows:</p>
<p><code>dotnet new csgaspnetweb -title "My Test Website" -output Test</code></p>
<p>The above command would produce a folder structure similar to above, but would have
renamed the word "Skeleton" in all file contents, file names, and folder names
with "Test", and renamed all instances of PROJECT-TITLE with "My Test Website".
In addition, it would ignore .git and .vs folders. Once a template is created the
way we want it, I <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/custom-templates#packing-a-template-into-a-nuget-package-nupkg-file">publish the template to our internal NuGet feed</a>
using Azure DevOps CI/CD pipelines.
Developers can then <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/custom-templates#installing-a-template">install or update</a>
their templates using <code>dotnet new -i [template-package-name]</code>.</p>
<p>Consistency is important in software development. From folder names to variable names,
the more consistent a codebase is, the more easy it is to work in.
At <a href="https://www.csgsolutions.com">csg</a> we aim to have a consistent
approach to different custom software applications we build for our
clients. One of the early ways we practice this is by starting each
new git repo with common set of files and folders. Until recently,
the workflow to accomplish this has been to clone what we call the
"Skeleton" repo for a particular project type (API, website, class library, etc.), and
then do a bunch of renames of namespaces, folders, etc. It turned out to be really
easy to take our existing "skeleton projects" and turn them
into <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/custom-templates">custom templates for dotnet-new</a>.</p>https://www.justinbuchanan.com/blog/posts/Authenticate-ASPNET-Core-Identity-Users-via-Active-Directory-or-LDAP-PasswordAuthenticate ASP.NET Identity Core Users via LDAP Password2017-03-24T00:00:00Z<p>In a project I was recently working on, I needed a way to store and manage user accounts in a stock <a href="https://github.com/aspnet/Identity/">ASP.NET Core Identity</a> Entity Framework Core based database, but validate user passwords against an existing Active Directory domain. In this situation, I could not leverage Kerberos/Windows Authentication because users were outside the Intranet, nor could I use ADFS or equivalent SSO services as it was beyond the scope of my project to deploy such a solution.</p>
<p>To achieve this, I created a simple UserManager wrapper class that overrides the base <a href="https://github.com/aspnet/Identity/blob/rel/1.1.0/src/Microsoft.AspNetCore.Identity/UserManager.cs#L611">CheckPasswordAsync</a> method with one that uses the <a href="https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard">Novell LDAP library for NETStandard 1.3</a> to perform an LDAP bind against a directory, and thus perform simple password validation.</p>
<p>I began by creating a UserManager class that inherits from Microsoft.AspNetCore.Identity.UserManager.</p>
<pre><code class="language-csharp">/// <summary>
/// Provides a custom user store that overrides password related methods to valid the user's password against LDAP.
/// </summary>
/// <typeparam name="TUser"></typeparam>
public class LdapUserManager<TUser> : Microsoft.AspNetCore.Identity.UserManager<TUser>
where TUser: class
</code></pre>
<p>Then I implement CheckPasswordAsync() using an LdapAuthentication class, which is just a loose abstraction around the Novell LDAP library.</p>
<pre><code class="language-csharp">/// <summary>
/// Checks the given password agains the configured LDAP server.
/// </summary>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
public override async Task<bool> CheckPasswordAsync(TUser user, string password)
{
using (var auth = new LdapAuthentication(\_ldapOptions))
{
string dn;
// This gives a custom way to extract the DN from the user if it is different from the username.
// It seems more like this would be a feature of the user store, but we can't get user store from userManager
// and all the methods we really need for sign-in are on user manager.
if (this.Store is IUserLdapStore<TUser>)
{
dn = await((IUserLdapStore<TUser>)this.Store).GetDistinguishedNameAsync(user);
}
else
{
dn = await this.Store.GetNormalizedUserNameAsync(user, CancellationToken.None);
}
if (auth.ValidatePassword(dn, password))
{
return true;
}
}
return false;
}
</code></pre>
<p>The meat of the LdapAuthentication class is in the ValidatePassword() method.</p>
<pre><code class="language-csharp">/// <summary>
/// Gets a value that indicates if the password for the user identified by the given DN is valid.
/// </summary>
/// <param name="distinguishedName"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool ValidatePassword(string distinguishedName, string password)
{
if (\_isDisposed)
{
throw new ObjectDisposedException(nameof(LdapConnection));
}
if (string.IsNullOrEmpty(\_options.Hostname))
{
throw new InvalidOperationException("The LDAP Hostname cannot be empty or null.");
}
\_connection.Connect(\_options.Hostname, \_options.Port);
try
{
\_connection.Bind(distinguishedName, password);
return true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return false;
}
finally
{
\_connection.Disconnect();
}
}
</code></pre>
<p>At this point, I just needed some basic configuration and DI config code to get things wired up in the Startup.cs of an ASP.NET Core app.</p>
<pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
services.Configure<Justin.AspNetCore.LdapAuthentication.LdapAuthenticationOptions>(this.Configuration.GetSection("ldap"));
services.AddLdapAuthentication<ApplicationUser>();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddUserManager<Justin.AspNetCore.LdapAuthentication.LdapUserManager<ApplicationUser>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
}
</code></pre>
<p>This expects configuration to come from an AppSettings.json section, which looks like this:</p>
<pre><code>"ldap": {
"Hostname": "dc1.example.com",
"Port": 389
}
</code></pre>
<p>This allows me to keep the user accounts in a database (in this instance, a MySQL database), but eliminates the need for the user to have a separate password. It’s important to note that in my case, users do not need to be able to change, reset, or otherwise manage their user account password through the web interface, as they have a separate existing process in place for that.</p>
<p>I intend on coming back at some point an implementing more of the UserManager methods that *can* be implemented via LDAP, but for now all I needed was to eliminate the need for users to create a separate account password for this app.</p>
<p>The full source code is <a href="https://github.com/jusbuc2k/Justin.AspNetCore.LdapAuthentication">available on GitHub</a>, or you can install <a href="https://www.nuget.org/packages/Justin.AspNetCore.LdapAuthentication">the NuGet package</a>:</p>
<pre><code>> Install-Package -Pre Justin.AspNetCore.LdapAuthentication
</code></pre>
<p>In a project I was recently working on, I needed a way to store and manage user accounts in a stock <a href="https://github.com/aspnet/Identity/">ASP.NET Core Identity</a> Entity Framework Core based database, but validate user passwords against an existing Active Directory domain. In this situation, I could not leverage Kerberos/Windows Authentication because users were outside the Intranet, nor could I use ADFS or equivalent SSO services as it was beyond the scope of my project to deploy such a solution.</p>https://www.justinbuchanan.com/blog/posts/migrage-cross-target-projectjson-using-dotnet-cliMigrating a Cross-targeted project.json .NET Core Library to csproj Using the .NET Core CLI2017-03-24T00:00:00Z<p>Today I migrated several of our internal C# libraries <a href="http://www.csgsolutions.com/services/software-development/">we use at CSG</a> that are using <a href="https://www.microsoft.com/net/core">.NET Core</a> from the project.json to csproj format using the <a href="https://docs.microsoft.com/en-us/dotnet/articles/core/tools/">.NET Core CLI tools</a>. Everything went well, but I ran into one snag with trying to build the NuGet packages. Here are my steps I went through to migrate and resolve the errors I encountered.</p>
<p>First, I started with deleting the <em>global.json</em> file that was being used to <a href="https://www.hanselman.com/blog/WorkingWithMultipleNETCoreSDKsBothProjectjsonAndMsbuildcsproj.aspx">pin the sdk/cli tooling to a pre-csproj version</a>. I opened the project in the command line and ran the migration command, which is <a href="https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-migrate"><em>dotnet migrate</em></a>.</p>
<p><a href="/blog/images/dotnet-migrate.png"><img src="/blog/images/dotnet-migrate_thumb.png" class="img-fluid" alt="dotnet-migrate" title="dotnet-migrate" /></a></p>
<p>So far so good. I went ahead and tried to build a Release build with a NuGet package by running <em>dotnet build –configuration Release</em>, which is what our <a href="https://docs.microsoft.com/en-us/dotnet/articles/core/tools/using-ci-with-cli">continuous integration</a> build script is doing to generate the NuGet packages.</p>
<p><a href="/blog/images/picture=dotnet-build.png"><img src="/blog/images/dotnet-build_thumb.png" class="img-fluid" alt="dotnet-build" title="dotnet-build" /></a></p>
<p>Well crap, the build command was failing with the following errors:</p>
<blockquote class="blockquote">
<p>error MSB4018: The "PackTask" task failed unexpectedly.<br />
error MSB4018: System.IO.FileNotFoundException: File not found: '...\bin\Release\net461\Csg.Data.Dapper.dll'.</p>
</blockquote>
<p>There were some various other flavors of this error involving the netstandard1.6 path instead of net461, but they were all similar. It appeared to be failing when trying to build the nupkg because of missing build output files. What was weirder, is that running the Build command (CTRL-SHIFT-B) in Visual Studio 2017 26228.4 was showing the same errors in the Output window, but the build was completing with a “Build: 1 succeeded, 0 failed, 0 skipped”. It wasn’t picking up on the fact that the <em>dotnet pack</em> command was failing. This seems like an unrelated problem with VS2017, so I went back to the command line build. I tried a view variations of <em>dotnet build</em> using the <em>–framework</em> argument, which led me to believe it was some issue with the multi-targeting being used in the project.</p>
<p>These projects are targeting <strong>both</strong> the full .NET Framework 4.6.1 and as well as NET Standard 1.6. Before the migration, the <em>frameworks</em> section of the project.json looked like this:</p>
<pre><code class="language-json">"frameworks": {
"netstandard1.6": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
},
"net461": {
}
}
</code></pre>
<p>It’s worth mentioning here that there is no support via the Visual Studio 2017 UI (Project properties page) for configuring multiple target frameworks <a href="https://youtu.be/qlVE5iDjBIg?list=PL0M0zPgJ3HSftTAAHttA3JQU4vOjXFquF&t=1690">as mentioned by Damian Edwards</a> in one of the recent <a href="https://live.asp.net/">ASP.NET Community Standup</a>’s. The equivalent csproj syntax looks like this:</p>
<pre><code class="language-xml"><PropertyGroup>
...
<Authors>Justin R. Buchanan</Authors>
<TargetFrameworks>netstandard1.6;net461</TargetFrameworks>
<DebugType>portable</DebugType>
...
</PropertyGroup>
</code></pre>
<p>Note the framework list is semi-colon delimited in a <TargetFrame<strong>works</strong>> element instead of <TargetFrame<strong>work</strong>>.</p>
<p>While I was in the csproj I noticed it had migrated this project.json <em>scripts</em> content:</p>
<pre><code class="language-json">"scripts": {
"postcompile": \[
"dotnet pack --no-build --configuration %compile:Configuration%"
\]
}
</code></pre>
<p>to this csproj equivalent:</p>
<pre><code class="language-xml"><Target Name="PostcompileScript" AfterTargets="Build" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
<Exec Command="dotnet pack --no-build --configuration $(Configuration)" />
</Target>
</code></pre>
<p>I removed the new <Target Name=”PostcompileScript”> tag entirely, and then manually ran <em>dotnet build</em> and then <a href="https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-pack"><em>dotnet pack</em></a>, and yay, it worked!</p>
<blockquote class="blockquote">
<p><strong>EDIT:</strong> I was reading over this again today and noticed the <em>Condition</em> on the <Target> that seems like it should have prevented me from having this error (althought it wouldn’t have generated a NuGet package). I’ll have to do more research on exactly when <em>$(IsCrossTargetingBuild)</em> evaluates to <em>true.</em> It seems like I would have still needed to add the new <em>dotnet pack</em> step outlined below though.</p>
</blockquote>
<p><a href="/blog/images/dotnet-build-yay.png"><img src="/blog/images/dotnet-build-yay_thumb.png" class="img-fluid" alt="dotnet-build-yay" title="dotnet-build-yay" /></a><br />
<a href="/blog/images/dotnet-pack-yay_1.png"><img src="/blog/images/dotnet-pack-yay_thumb_1.png" class="img-fluid" alt="dotnet-pack-yay" title="dotnet-pack-yay" /></a></p>
<p>The only change I had to make at this point was to to add an extra step to our <em>build.cmd</em> (used by our build server) to run the <em>dotnet pack</em> command. Previously we had not needed this because the <em>dotnet build</em> command was running the pack in the <em>postcompile</em> steps. Now it looks something like this:</p>
<pre><code>SET SOLUTION=Csg.Data.Dapper.sln
SET BUILD\_CONFIG=Release
...
dotnet build %SOLUTION% --configuration %BUILD\_CONFIG%
...
dotnet pack %SOLUTION% --no-build --configuration %BUILD\_CONFIG%
...
</code></pre>
<p>I’m not sure if this is a bug, or if I’m doing something else wrong, or both, but this got me past the error and I was able to continue migrating the rest of our libraries from project.json to csproj.</p>
<p>Today I migrated several of our internal C# libraries <a href="http://www.csgsolutions.com/services/software-development/">we use at CSG</a> that are using <a href="https://www.microsoft.com/net/core">.NET Core</a> from the project.json to csproj format using the <a href="https://docs.microsoft.com/en-us/dotnet/articles/core/tools/">.NET Core CLI tools</a>. Everything went well, but I ran into one snag with trying to build the NuGet packages. Here are my steps I went through to migrate and resolve the errors I encountered.</p>https://www.justinbuchanan.com/blog/posts/Return-Paged-Data-from-an-IQueryablelt;Tgt;Return Paged Data from an IQueryable2013-03-08T00:00:00Z<p>I finally broke down and wrote a standard extension method for <a href="http://msdn.microsoft.com/en-us/library/bb351562.aspx">IQueryable<T></a> that returns a single “page” of data from a source set. This method is terminal if it is in an expression tree in that it returns an <a href="http://msdn.microsoft.com/en-us/library/9eekhta0.aspx">IEnumerable<T></a> and not IQueryable<T>. This method works by calling Count() to get the total number of records (which it sends back in the output parameter itemCount), and then uses the normal .Skip() and .Take() method to return a single page. It should work against any IQueryable<T> including LINQ to SQL and Entity Framework sequences.</p>
<pre><code class="language-csharp">/// <summary>
/// Gets a single page of items from a sequence.
/// </summary>
/// <typeparam name="T">The data type of the result items.</typeparam>
/// <param name="query">The sequence</param>
/// <param name="pageNumber">The page number to retrieve, starting at 1.</param>
/// <param name="pageSize">The number of items in each page.</param>
/// <param name="pageCount">Provides the total number of pages available.</param>
/// <returns></returns>
public static IEnumerable<T> TakePage<T>(this IQueryable<T> query, int pageNumber, int pageSize, out int pageCount)
{
int itemCount;
return TakePage(query, pageNumber, pageSize, out pageCount, out itemCount);
}
/// <summary>
/// Gets a single page of items from a sequence.
/// </summary>
/// <typeparam name="T">The data type of the result items.</typeparam>
/// <param name="query">The sequence</param>
/// <param name="pageNumber">The page number to retrieve, starting at 1.</param>
/// <param name="pageSize">The number of items in each page.</param>
/// <param name="pageCount">Provides the total number of pages available.</param>
/// <param name="itemCount">Provides the total number of items availabe.</param>
/// <returns></returns>
public static IEnumerable<T> TakePage<T>(this IQueryable<T> query, int pageNumber, int pageSize, out int pageCount, out int itemCount)
{
if (pageNumber < 1)
throw new ArgumentException("The value for 'page' must be greater than or equal to 1", "pageNumber");
itemCount = query.Count();
pageCount = (int)Math.Ceiling((double)itemCount / (double)pageSize);
if (pageNumber > pageCount)
pageNumber = pageCount;
if (pageNumber > 1)
return query.Skip((pageNumber - 1) \* pageSize).Take(pageSize);
else
return query.Take(pageSize);
}
</code></pre>
<p>I finally broke down and wrote a standard extension method for <a href="http://msdn.microsoft.com/en-us/library/bb351562.aspx">IQueryable<t></t></a> that returns a single “page” of data from a source set. This method is terminal if it is in an expression tree in that it returns an <a href="http://msdn.microsoft.com/en-us/library/9eekhta0.aspx">IEnumerable<t></t></a> and not IQueryable<t>. This method works by calling Count() to get the total number of records (which it sends back in the output parameter itemCount), and then uses the normal .Skip() and .Take() method to return a single page. It should work against any IQueryable<t> including LINQ to SQL and Entity Framework sequences.</t></t></p>https://www.justinbuchanan.com/blog/posts/How-Not-to-Future-Proof-an-ApplicationHow Not to Future-Proof an Application2012-12-07T00:00:00Z<p>I was recently troubleshooting a reported application crash for a client along with a fellow engineer from the client (let’s call him Bob). A message box along the lines of “An Error Happened, Good Luck” showed up when a user clicked a certain button. Google searches for problems with this application typically turn up one post from 2003 that’s totally unhelpful.</p>
<p><a href="http://xkcd.com/979/"><img src="https://imgs.xkcd.com/comics/wisdom_of_the_ancients.png" class="img-fluid" alt="" /></a><br />
<a href="http://xkcd.com/979/">http://xkcd.com/979/</a></p>
<p>This application is a behemoth comprised of some VB6, .NET and who knows what else running against SQL Server 2000. Bob and I have some experience with this application, so we started a SQL Profiler trace to look at what was happening when the user clicked “The Button”. As it turns out, when clicked, it was executing a SQL statement that looked a lot like this:</p>
<p><code>SELECT \* FROM SomeDataTable WHERE SurrogateKey = ORDER BY SomeDataField</code></p>
<p>So if you know anything about SQL (<a href="http://msdn.microsoft.com/en-us/library/bb264565(v=sql.90).aspx">spend the next few hours here if you don’t</a>), this statement is wrong. Knowing the application, it looked suspiciously like there was code somewhere like this:</p>
<p><code>command = "SELECT \* FROM SomeDataTable WHERE SurrogateKey = " + SurrogateKeyParam + " ORDER BY SomeDataField"</code></p>
<p>SurrogateKeyParam was obviously empty for some reason. So Bob started running some queries to look at the data in SomeDataTable, which looked like this:</p>
<table class="table">
<thead>
<tr>
<th>SurrogateKey</th>
<th>CreateDate</th>
<th>DataFields...</th>
</tr>
</thead>
<tbody>
<tr>
<td>10000009</td>
<td>12/6/2012</td>
<td>...</td>
</tr>
<tr>
<td>10000010</td>
<td>12/6/2012</td>
<td>...</td>
</tr>
<tr>
<td>10000011</td>
<td>12/6/2012</td>
<td>...</td>
</tr>
</tbody>
</table>
<p>I halfway jokingly said to him, “Surely that surrogate key isn’t too big for some reason”. I think we both laughed in a scary “That might really bit it” sort of way, and then proceeded to run the numbers in our heads to see if 10,000,000 crossed some computer science wizard boundary somewhere. It was much too big to have crossed Int16 or UInt16 recently, and well below <a href="http://msdn.microsoft.com/en-us/library/system.int32.maxvalue.aspx">Int32’s maximum value</a>. So we went back to the data from the day when this issue was first reported. It looked something like this:</p>
<table class="table">
<thead>
<tr>
<th>SurrogateKey</th>
<th>CreateDate</th>
<th>DataFields...</th>
</tr>
</thead>
<tbody>
<tr>
<td>9999998</td>
<td>12/5/2012</td>
<td>...</td>
</tr>
<tr>
<td>9999999</td>
<td>12/5/2012</td>
<td>...</td>
</tr>
<tr>
<td>10000000</td>
<td>12/5/2012</td>
<td>...</td>
</tr>
<tr>
<td>10000001</td>
<td>12/5/2012</td>
<td>...</td>
</tr>
</tbody>
</table>
<p>Based on the title of the post, you may already know where this is going. The issue was first reported on 12/5, and the values went from 7 to 8 digits on that day. We were both getting a “That can’t be a coincidence” feeling at this point, and Bob, in his East Coast accent, said something to the effect of “That can’t really be it”. We have both known there has to be some unplanned obsolescence in this application somewhere, and we were both hoping this wasn’t it.</p>
<p>So off to the “Test” environment we went. “Test” was well below reaching 8 digits for this value, and clicking “The Button” worked without a problem. Since the surrogate key values are allocated from a sequence table, we artificially set the value up to 9,999,999 and then clicked “The Button”. BAM! The “An Error Happened, Good Luck” message appeared. Confirmation of our worst fear, somewhere in the vast expanse of the GUI code mess that is this application, there was a variable or statement that was arbitrarily limiting the value of SurrogateKey to a length of 7 characters for who-knows-what reason. However, it wasn’t just trimming the value, somehow it was ending up NULL or empty.</p>
<p>Since we don’t have the source, we can only guess this is the result of incorrect data types and/or maximum lengths on an <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681510(v=vs.85).aspx">ADO Recordset</a>, or worse (I guess) an <em>= LEFT(SurrogateKey,7)</em> is somewhere in the code. Who knows what it is really.</p>
<p>So after doing a quick search to see if anyone else was hiring so we could both quit before the helpdesk called back to check on our progress, we realized the data in this table is only used temporarily and then deleted. Nothing else outside the process that “The Button” is used for references the SurrogateKey column. Our fix was as easy as writing the following query:</p>
<p><code>UPDATE SequenceTable SET SurrogateKey=1 WHERE TableName=’SomeDataTable’</code></p>
<p>We also made the necessary sacrifices to the volcano in the event this breaks something, and may the <a href="http://en.wikipedia.org/wiki/Lords_of_Kobol">Lords of Kobol</a> help us when (not if), we see this error on a table that needs <a href="http://en.wikipedia.org/wiki/Referential_integrity">referential integrity</a>. In the past, tinkering in the database manually has caused numerous problems, but we had no other resolution.</p>
<p>So next time you are thinking to yourself, “I’ll just shove these Int32 values into 7 character strings”, don’t. Plan for your application to be used 5 years past the “Surely they will upgrade by now” or “surely they will never get to X” date. This one is going on 6 years past.</p>
<p>I was recently troubleshooting a reported application crash for a client along with a fellow engineer from the client (let’s call him Bob). A message box along the lines of “An Error Happened, Good Luck” showed up when a user clicked a certain button. Google searches for problems with this application typically turn up one post from 2003 that’s totally unhelpful.</p>https://www.justinbuchanan.com/blog/posts/ASPNET-MVC-HtmlHelper-Extension-Method-for-Tab-HighlightsASP.NET MVC HtmlHelper Extension Method for Menu Highlighting2012-12-04T00:00:00Z<p>I built an <a href="http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx">extension method</a> on the ASP.NET MVC HtmlHelper class to handle the creation of navigation menu links (tabs) that have a different CSS class applied to them if they are active (i.e. the current page). I had been doing this manually in the master layout (_Layout.cshtml) view with a bunch of <em>if</em> blocks. Of course you can roll out a <a href="https://github.com/maartenba/MvcSiteMapProvider">full-fledged sitemap</a> to handle this, but I didn’t want to.</p>
<pre><code class="language-csharp">/// <summary>
/// Extension method for <see cref="HtmlHelper"/> to support highlighting the active tab on the default MVC menu
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="linkText">The text to display in the link</param>
/// <param name="actionName">Link target action name</param>
/// <param name="controllerName">Link target controller name</param>
/// <param name="activeClass">The CSS class to apply to the link if active</param>
/// <param name="checkAction">If true, checks the current action name to determine if the menu item is 'active', otherwise only the controller name is matched</param>
/// <returns></returns>
public static MvcHtmlString MenuLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string activeClass, bool checkAction)
{
string currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
string currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
if (string.Compare(controllerName, currentController, StringComparison.OrdinalIgnoreCase) == 0 && ((!checkAction) || string.Compare(actionName, currentAction, StringComparison.OrdinalIgnoreCase) == 0))
{
return htmlHelper.ActionLink(linkText, actionName, controllerName, null, new { @class = activeClass });
}
return htmlHelper.ActionLink(linkText, actionName, controllerName);
}
</code></pre>
<p><em>activeClass</em> sets the CSS class name that will be applied, and setting <em>checkAction</em> to true applies the class only if the action name and controller name match.</p>
<p>So my in my _Layout.cshtml view, I changed all the Html.ActionLink calls to Html.MenuLink and added the <em>active</em> and <em>checkAction</em> parameters.</p>
<pre><code class="language-html"><nav>
<ul id="menu">
<li>@Html.MenuLink("Home", "Index", "Home", "active", true)</li>
<li>@Html.MenuLink("About", "About", "Home", "active", true)</li>
<li>@Html.MenuLink("Contact", "Contact", "Home", "active", true)</li>
<li>@Html.MenuLink("Something Else", "Index", "Something", "active", false)</li>
</ul>
</nav>
</code></pre>
<p>The Home, About and Contact actions are all handled by the HomeController, and since they are distinct menu choices, we set <em>checkAction</em> to true. The Something Else option, on the other hand, should be highlighted anytime we hit an action on the SomethingController.</p>
<p>One final tweak was to add an overload to default the <em>checkAction</em> parameter to <em>true.</em></p>
<p>public static MvcHtmlString MenuLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string activeClass)
{
return MenuLink(htmlHelper, linkText, actionName, controllerName, activeClass, true);
}</p>
<p>And the updated view code:</p>
<pre><code class="language-html"><nav>
<ul id="menu">
<li>@Html.MenuLink("Home", "Index", "Home", "active")</li>
<li>@Html.MenuLink("About", "About", "Home", "active")</li>
<li>@Html.MenuLink("Contact", "Contact", "Home", "active")</li>
<li>@Html.MenuLink("Something Else", "Index", "Something", "active", false)</li>
</ul>
</nav>
</code></pre>
<p>I built an <a href="http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx">extension method</a> on the ASP.NET MVC HtmlHelper class to handle the creation of navigation menu links (tabs) that have a different CSS class applied to them if they are active (i.e. the current page). I had been doing this manually in the master layout (_Layout.cshtml) view with a bunch of <em>if</em> blocks. Of course you can roll out a <a href="https://github.com/maartenba/MvcSiteMapProvider">full-fledged sitemap</a> to handle this, but I didn’t want to.</p>https://www.justinbuchanan.com/blog/posts/Application-Specific-Passwords-for-Dovecot-and-PostfixApplication-Specific-Passwords-for-Dovecot-and-Postfix2012-12-02T00:00:00Z<p>This is the first part of a series I will be doing on how I implemented one-time password support for remote access to resources inside my home network such as my webmail client, along with supporting application and device specific passwords for use on my mobile phone, tablet, etc.</p>
<p>I always hate the feeling of using any of my username and password combinations on sketchy public computer somewhere. You know the kind I am talking about, those computers at hotels running Windows XP and IE6, signed as "Adminstrator", with every toolbar and add-on installed from a 9 year old version of Real Player to three different versions of some Internet poker game. There's bound to be a <a href="http://en.wikipedia.org/wiki/Keystroke_logging">key logger</a> in there someplace.</p>
<p>One time use passwords have been around for a long time to mitigate this type of scenario. As the name suggests a one-time password, is valid only once. In theory if someone sees or captures that password, it's worthless to them. Typically one time passwords are accompanied by a normal password, or a PIN number. This mostly satisfies <a href="http://en.wikipedia.org/wiki/Two-factor_authentication">Two Factor Authentication</a>, which requires something you know (the password or PIN), and something you have (the phone giving you the password). Google started offering one-time-password support for Google accounts through the 2-step verification system and the Authenticator app.</p>
<p>So we have three different surfaces to protect:</p>
<ul>
<li><a href="http://httpd.apache.org/">Apache</a> HTTP access to the <a href="http://roundcube.net/">Roundcube</a> webmail client.</li>
<li><a href="http://www.postfix.org/">Postfix</a> SMTP access to send mail from an external e-mail.</li>
<li><a href="http://www.dovecot.org/">Dovecot</a> IMAP access to retrieve mail from an external e-mail client.</li>
</ul>
<p>We want to be able to use our one-time password to access #1, but since an e-mail client may login many times during a single session, #2 and #3 are better served by an application specific password that is sufficiently random but never changes.</p>
<p>So I set out by sketching out a few requirements:</p>
<ol>
<li>Make use of my existing e-mail platform (Ubuntu 12.04 + Postfix + Dovecot + RoundCube on Apache).</li>
<li>Close any existing access points into home network via simple username/password combinations.</li>
<li>Support application/device specific passwords for IMAP and SMTP clients (thunderbird, etc.).</li>
<li>Support one-time passwords to access RoundCube webmail.</li>
<li>Phone app to generate one-time passwords.</li>
<li>Backup codes that can be printed to use in the case where the app is not inaccessible.</li>
</ol>
<h2 id="application-specific-passwords">Application Specific Passwords</h2>
<p>Since the first step is to prevent logins to IMAP and SMTP from outside the firewall with passwords we may be typing in on public computer, we need to provide secure passwords that will only be entered once into a device or application to configure. We don’t need to remember these passwords, so we can revoke them and re-configure an application or device at anytime.</p>
<p>Dovecot is configured to authenticate users against <a href="http://en.wikipedia.org/wiki/Pluggable_authentication_module">PAM</a>, and PAM is configured to authenticate users with <a href="http://modauthkerb.sourceforge.net/">mod-auth-kerb</a>. Postfix is configured to authenticate via <a href="http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL">SASL to Dovecot</a>. So ultimately, there is a single username/password for all users through my <a href="https://help.ubuntu.com/community/Kerberos">Kerberos</a> database.</p>
<p>Dovecot separates the concept of a user database and password database, so I can keep my existing user database (Linux passwd, LDAP, etc), and just alter the password database. To add additional password validation options to Dovecot, you simply add more passdb options to the configuration file. One of those options happens to be a MySQL, so I went ahead and made a simple database and table to store our application specific passwords.</p>
<pre><code>CREATE TABLE \`dovecot\_passwords\` (
\`username\` varchar(100) NOT NULL,
\`appname\` varchar(50) NOT NULL,
\`password\` varbinary(256) NOT NULL,
PRIMARY KEY (\`username\`,\`appname\`)
)
</code></pre>
<p>You will notice username and appname make the unique key here, since we want to have multiple passwords for the same account. The data in this table might look something like this:</p>
<table class="table">
<thead>
<tr>
<th>username</th>
<th>appname</th>
<th>password</th>
</tr>
</thead>
<tbody>
<tr>
<td>justin</td>
<td>K9 Mail on Phone</td>
<td>******</td>
</tr>
<tr>
<td>justin</td>
<td>Thunderbird on Desktop</td>
<td>******</td>
</tr>
<tr>
<td>sarah</td>
<td>iPhone</td>
<td>******</td>
</tr>
</tbody>
</table>
<p>The value in the password field is the MD5 hash of the password without any whitespace (<a href="http://crackstation.net/hashing-security.htm">Yes, it should be salted and maybe using SHA1 instead</a>). In order to make the application specific passwords more secure, I’m using rather long passwords, and so when I generate them I usually format them in blocks of four separated by spaces, such as xRtg Dbea 4d9g aP44. This is easier to type into a mobile keyboard while glancing back and forth between the device and the keyboard. The password database will need to ignore the whitespace, because we don’t care either way if it is there. For now I'll just manage entries in this table manually, but later I plan on writing a fancy CLI or GUI tool. So to insert new records in this table, I generate a random password, and do an insert:</p>
<p><code>INSERT INTO dovecot\_passwords (username, appname, password) VALUES( 'justin', 'smartphone', MD5('xRtgDbea4d9gaP44') );</code></p>
<p>Now I can configure Dovecot to check this password database instead of PAM by changing my passdb entry to use the SQL driver instead of PAM.</p>
<pre><code>#/etc/dovecot/dovecot.conf
passdb {
args = /etc/dovecot/dovecot-sql-other.conf
driver = sql
}
</code></pre>
<p>And the associated SQL config file:</p>
<pre><code>#/etc/dovecot/dovecot-sql-other.conf
driver = mysql
connect = host=localhost dbname=mail\_db user=dovecot password=\*\*\*\*\*\*\*\*
default\_pass\_scheme = PLAIN
password\_query = SELECT NULL AS password,'Y' as nopassword, username AS user
FROM dovecot\_passwords
WHERE username = '%u' AND password=MD5(REPLACE('%w',' ',''))
</code></pre>
<p>You can read more about how this configuration file works on the Dovecot <a href="http://wiki2.dovecot.org/AuthDatabase/SQL">Wiki page for SQL passdb</a>, but essentially my query is removing any whitespace from the supplied password, and matching the MD5 hash. To really make this secure, we should be adding a password salt into the mix and probably using SHA1 for the hash algorithm. It is worth mentioning, that if you want to support regular username/password authentication via PAM for users on the internal network, but the application specific passwords everywhere else, this is possible by adding the <a href="http://linux.die.net/man/8/pam_access">pam_access module</a> into your PAM configuration for Dovecot.</p>
<p>So now we have satisfied requirements #1, #2, and #3. Dovecot (and Postfix by means of SASL) will now authenticate users against the custom password database, and will not authenticate users with their old username/password.</p>
<p>Next up: Implementing #4, #5, #6 to support One-time passwords.</p>
<p>This is the first part of a series I will be doing on how I implemented one-time password support for remote access to resources inside my home network such as my webmail client, along with supporting application and device specific passwords for use on my mobile phone, tablet, etc.</p>https://www.justinbuchanan.com/blog/posts/I-Broke-Remote-Access-to-Hyper-V-ServerI Broke Remote Access to Hyper-V Server2012-07-14T00:00:00Z<p>In the process of setting up a new Hyper-V 2008 R2 server, I accidentally disabled "Host Access" to both network cards, thus killing remote access to the server (which is in my basement). Since I'm running <a href="http://www.microsoft.com/en-us/server-cloud/hyper-v-server/default.aspx">Hyper-V Server</a> which has no full GUI like Server Core installs, I don't have access to the normal Network Connections GUI to unbind the virtual switch protocol from the network cards.</p>
<p>I did some searching around the web, and all the solutions I found involve <a href="http://archive.msdn.microsoft.com/nvspbind">downloading some scripts or tools</a>, and since I'm too lazy to put one of these tools on a USB drive and walk downstairs to run them, I wanted a solution that I could run from the command line remotely (as I have access to the server via Intel AMT's VNC KVM). I finally found what I was looking for <a href="http://eniackb.blogspot.com/2009/10/hyper-v-error-error-applying-new.html">on this blog post at ENIAC KB</a>.</p>
<p>So, the steps are simple:</p>
<ol>
<li><p>Remove the virtual switch protocol from all network adapters:</p>
<p><code>netcfg -u vms\_pp</code></p>
</li>
<li><p>Reboot</p>
<p><code>shutdown /r</code></p>
</li>
<li><p>Re-install the virtual switch protocol (which will leave it disabled by default):</p>
<pre><code>netcfg -l c:\\windows\\winsxs\\amd64\_wvms\_pp.inf\_31bf3856ad364e35\_6.1.7600.16385\_none\_beda85050b13680c\\wvms\_pp.inf -c p -i vms\_pp
</code></pre>
<p><img src="../images/071412_1729_IBrokeRemot1.png" class="img-fluid" alt="" /></p>
</li>
</ol>
<p>So if you broke remote access to your Hyper-V server under server core, and you can still get access to the CLI either through a remote KVM or at the physical console, you can uninstall the Virtual switch protocol, reboot, re-install, and continue your network configuration from VMM or the Hyper-V Console remotely.</p>
<p>In the process of setting up a new Hyper-V 2008 R2 server, I accidentally disabled "Host Access" to both network cards, thus killing remote access to the server (which is in my basement). Since I'm running <a href="http://www.microsoft.com/en-us/server-cloud/hyper-v-server/default.aspx">Hyper-V Server</a> which has no full GUI like Server Core installs, I don't have access to the normal Network Connections GUI to unbind the virtual switch protocol from the network cards.</p>