Asp.Net Core + Angular 2/4: Saga Continues

Dedicated time to code is limited.  Each month, I try to find blocks of programming time between emergency shifts, and after completing fpnotebook.com content updates. This past year I was also distracted by the Microsoft Data Science curriculum.

Coding projects generally center around medical apps for the site.  Small, self-limited projects that can be completed in a couple of weeks are ideal.  However, most projects require months to complete and it can be difficult to frequently leave and return to these projects, each time spending time to reacquaint myself with the code.  In the meantime, frameworks update, at times with breaking changes.

This month I returned to one of my most challenging projects of recent time: Integrating an angular 2/4 application into asp.net core.  Pluralsight, Lynda.com and Udemy have covered most topics I need, related to angular and asp.net core (including their combination).  In addition, Angular and Asp.net Core both have excellent online documentation.   Microsoft has even created combined SPA project templates for angular within asp.net core projects (Javascript Services).

But these lessons and documentation do not cover my approach well, which I describe in this post.  I think Javascript Services, which embeds the angular app within asp.net core MVC is not the right approach (at least for me), as they do not preserve the angular cli tool chain nor allow for testing angular in isolation of asp.net core.

So the last 2 days, I had time to reacquaint myself with this project and experience frustrations that brought any chance of productivity to a screeching halt.   Day 1 was  spent on deployment to IIS with sql database (one db on development machine, one db on server) – which is not covered well in any video series I have seen.  Many demo videos use Auth0 for authorization and Firebase for database.  But authorization and database are some of the key reasons I use the asp.net core framework.  Why defer that functionality?

Elsewhere, I cover deployment and database.  Despite keeping these blogs for my own reference, it still takes hours to get the whole publish process working.  That is when I found IIS related errors despite my angular + asp.net core working when built on my development machine or on the production server when using local host.  The problem I have had previously, and had again, was the issue with angular base href statement in the index.cshtml file.  My key finding was that the base href works fine as long as it remains “~/” and not a subdirectory (e.g. angular_dist).  Previously, my angular cli project would build its files and send them to a subdirectory of wwwroot.  I did this to prevent overwriting the other assets in the main directory not related to angular.  However, the cli build command has options allowing to not delete files in the destination directory and to not hash file names.

Now I am using the following command line to build angular destination files directly into the asp.net core wwwroot directory:

ng build --prod --extract-css=false --output-hashing=none
     --delete-output-path=false 
     --output-path="../backend/wwwroot/"

 

Posted in Uncategorized

Cryptic Errors in Angular + Asp.Net Core

This is more a note to self, but might help others.

My current application set-up is:

  1. asp.net core backend with web api
  2. angular cli frontend
  3. Build the frontend (ng build) generates output into the wwwroot folder of the backend/asp.net project.

With angular-cli development build, the frontend calls a fake a api based on finding the environment variable set to development.

With the angular-cli production build, the frontend calls the real api (from the wwwroot directory inside the asp.net core project, it is just “/api”.

I spent the better part of a day, trying to get the angular cli production build to work inside the asp.net core wwwroot directory.  First, I could not get the environ variable to change from development to production.  Then I realized the browser was caching the page (this happens so often to me – yet I still forget to clear the cache).  Then I realized the production build worked without error but I kept seeing multiple console errors Uncaught SyntaxError: Unexpected token <  and the angular app refused to load.

The error was cryptic.  I assumed since this worked in development build, that something in the production file processing was awry (e.g. uglify) or a disallowed character had been inserted (e.g. BOM).  I searched online and of course Stack Overflow, which lead to updating Node and Angular-cli, but of course this did not fix the problem.

I snacked. I napped.  Stared at screen.  Answered emails.  rebuilt again – just in case.  stared at screen.

Then I noticed the filenames in the angular-cli destination directory.  In angular development build, the files are called  for example, “inline.bundle.js”, but in the default production build, there is cache busting enabled – so the files are named “inline.ajdsfk2374sf.bundle.js”.   In addition, the development build outputs the css to a js file, but in production build the css is output to a css file.

This is not a problem if you use the generated index.html file, but I have a asp.net mvc default view – Index.cshtml file:

 

<app-root>Loading...</app-root>

@section scripts {
 http://~/angular_dist/inline.bundle.js
 http://~/angular_dist/scripts.bundle.js




http://~/angular_dist/styles.bundle.js

http://~/angular_dist/vendor.bundle.js
 http://~/angular_dist/main.bundle.js

}

 

Why was the error Uncaught SyntaxError: Unexpected token <“?

In any event, the solution is fairly simple:

ng build --prod --ec=false --oh=media
which keeps the script files and css file the same as in development.
Had the original error read – “file not found”, you would not be reading this.  Cryptic errors and a day distracted.
Posted in Uncategorized

Asp.Net Core Testing Repositories and Mocking EF

I wasted the better part of the day implementing simple tests.   Even the most mundane, basic steps that have typically taken no time, were prolonged.  I remember an automated tool inside Visual Studio in 2010 or so, when you could right click on a project or class (context menu) in solution explorer, and select “Create Unit Tests”, and not only would it create a test project with the associated project references and accessors for private objects/methods, but would also offer a dialog to select which methods to create unit test coverage for.   That is not my current experience, which is mostly DIY.

First creating a new test project, did not seem to appear correctly in the solution explorer, under solution items; I had to recreate it several times.  Then I could not get my asp.net core to load inside the test project (which I suspect was being saved as a standard project, despite choosing core).  Then I could not get Moq to load.  I could not find the correct EntityFramework core reference for the test project.  I tried both xunit and mstest projects.  I tried CLI and from inside VS.

Finally, I it is working, and I am not certain if I could repeat my successful steps without some repeat mis-steps again.  In solution explorer, right-click the project => add new project => dotnet core => xunit project.

My resulting .csproj file looks like this:

 

<Project Sdk="Microsoft.NET.Sdk">

 <PropertyGroup> 
 <TargetFramework>netcoreapp1.1</TargetFramework>
 </PropertyGroup>

 <ItemGroup>
 <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="1.1.2" />
 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
 <PackageReference Include="Moq" Version="4.7.10" />
 <PackageReference Include="xunit" Version="2.2.0" />
 <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
 </ItemGroup>

 <ItemGroup>
 <ProjectReference Include="..\backend\backend.csproj" />
 </ItemGroup>

</Project>

 

The next step was to implement repository testing.  This was an even better exercise in frustration; I nearly gave up a half dozen times.   Ultimately, this link on Microsoft Documentation site is the overall approach:  Entity Framework Testing with a Mocking Framework (EF6 onwards), but this will not work fully as written for asp.net core (esp. for async).  I was able to modify the MS documentation with this Stack Overflow answer.  Finally, I found Armen Shimoon’s Mocking DbSet Helpers which really cleaned up the code.

I put these pieces together as follows, starting with Armen’s piece, but adding async functionality :

 /// <summary>
 /// From http://dotnetliberty.com/index.php/2016/02/22/moq-on-net-core/
 /// </summary>
 /// 
 public static class DbSetMock
 {
 public static Mock<DbSet<T>> Create<T>(params T[] elements) where T : class
 {
 return new List<T>(elements).AsDbSetMock();
 }
 }

 public static class ListExtensions
 {
 public static Mock<DbSet<T>> AsDbSetMock<T>(this List<T> list) where T : class
 {
 IQueryable<T> queryableList = list.AsQueryable();
 Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
 dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
 dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
 dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
 dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(queryableList.GetEnumerator());


 dbSetMock.As<IAsyncEnumerable<T>>()
 .Setup(m => m.GetEnumerator())
 .Returns(new TestAsyncEnumerator<T>(queryableList.GetEnumerator()));

 dbSetMock.As<IQueryable<T>>()
 .Setup(m => m.Provider)
 .Returns(new TestAsyncQueryProvider<T>(queryableList.Provider));


 return dbSetMock;
 }


 }

Then here is the async functionality code:

 /// <summary>
 /// From https://stackoverflow.com/questions/40476233/how-to-mock-an-async-repository-with-entity-framework-core#answer-40491640
 /// </summary>
 /// <typeparam name="TEntity"></typeparam>
 internal class TestAsyncQueryProvider<TEntity> : IAsyncQueryProvider
 {
 private readonly IQueryProvider _inner;

 internal TestAsyncQueryProvider(IQueryProvider inner)
 {
 _inner = inner;
 }

 public IQueryable CreateQuery(Expression expression)
 {
 return new TestAsyncEnumerable<TEntity>(expression);
 }

 public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
 {
 return new TestAsyncEnumerable<TElement>(expression);
 }

 public object Execute(Expression expression)
 {
 return _inner.Execute(expression);
 }

 public TResult Execute<TResult>(Expression expression)
 {
 return _inner.Execute<TResult>(expression);
 }

 public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression)
 {
 return new TestAsyncEnumerable<TResult>(expression);
 }

 public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
 {
 return Task.FromResult(Execute<TResult>(expression));
 }
 }

 internal class TestAsyncEnumerable<T> : EnumerableQuery<T>, IAsyncEnumerable<T>, IQueryable<T>
 {
 public TestAsyncEnumerable(IEnumerable<T> enumerable)
 : base(enumerable)
 { }

 public TestAsyncEnumerable(Expression expression)
 : base(expression)
 { }

 public IAsyncEnumerator<T> GetEnumerator()
 {
 return new TestAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
 }

 IQueryProvider IQueryable.Provider
 {
 get { return new TestAsyncQueryProvider<T>(this); }
 }
 }

 internal class TestAsyncEnumerator<T> : IAsyncEnumerator<T>
 {
 private readonly IEnumerator<T> _inner;

 public TestAsyncEnumerator(IEnumerator<T> inner)
 {
 _inner = inner;
 }

 public void Dispose()
 {
 _inner.Dispose();
 }

 public T Current
 {
 get
 {
 return _inner.Current;
 }
 }

 public Task<bool> MoveNext(CancellationToken cancellationToken)
 {
 return Task.FromResult(_inner.MoveNext());
 }
 }

 

Finally, here were the repository tests:

 static DbContextOptions<ApiFpn2DbContext> _options = new DbContextOptionsBuilder<ApiFpn2DbContext>()
.UseInMemoryDatabase(databaseName: "ApiFpn2DbContext_testDatabase")
.Options;

 [Fact]
 public async void AddAsyncTest()
 {
 var mockSet = new Mock<DbSet<UserProfile>>();

 var mockContext = new Mock<ApiFpn2DbContext>(_options);
 mockContext.Setup(m => m.UserProfiles).Returns(mockSet.Object);

 var service = new UserProfileRepository(mockContext.Object);
 var result = await service.AddAsync(new UserProfile {
 Id="1",
 Username="user1"
 });
 mockContext.Object.SaveChanges();

 mockSet.Verify(m => m.AddAsync(It.IsAny<UserProfile>(), new CancellationToken()), Times.Once());
 mockContext.Verify(m => m.SaveChanges(), Times.Once());
 }

 [Fact]
 public async Task GetAllUserProfilesAsync()
 {
 var userProfiles = new UserProfile[] { new UserProfile { Id = "user1", Username = "user1" } };
 Mock<DbSet<UserProfile>> userDbSetMock = DbSetMock.Create(userProfiles);

 var mockContext = new Mock<ApiFpn2DbContext>(_options);
 mockContext.Setup(c => c.UserProfiles).Returns(userDbSetMock.Object);

 var service = new UserProfileRepository(mockContext.Object);

 var results = await service.GetAsync();
 var data = results.Data;
 Assert.NotNull(data);
 Assert.Equal(1, data?.Count);
 Assert.True(results.Success);
 Assert.Equal(userProfiles[0].Username, data[0].Username);
 }

 }

 

After all that, I found this Github Issue Report for Entity Framework: Async MOQ testing with EntityFramework Core.  I was wondering why EF did not have better testing helpers, as the ones above based on Armen Shimoon’s code.  Ultimately, the EF team does not seem to recommend mocking EF.    So, how then do you test Repositories?  They argue that EF uses a repository pattern already, so why add a second one on top?

Julie Lehrman has a Pluralsight video Entity Framework in the Enterprise: Understanding EF Encapsulation and the great Repository Debates,  in which she reviews the architecture patterns, and when to use a Repository.  My understanding from this video series, is that she will still, for certain simple cases, use a classic repository (basic CRUD functionality).  This mapping is often done via generic repository classes.

However, she seems to highlight business use case specific persistence classes/methods (e.g. Read users with associated Notes), instead of writing  simple wrappers around EF CRUD  (1:1  maps of Create, Read, Update and Delete between the repository and EF).   This makes sense – why recreate what EF already does. She makes a similar argument regarding Unit Of Work objects; why recreate logic already contained in the EF data context object.

Finally, as a related concept, Julie Lehrman says she tends to return IEnumerable from her persistence objects instead of IQueryable, in order to lock down functionality and business logic for specific cases.  Instead of broad reuse (all but the kitchen sink), the focus is on solving specific real needs in the software.  When new use cases arise, write new persistence classes/methods.

I think my repositories have already morphed into business specific logic, rather than simply wrapping EF Crud functionality.  Even if we call these classes something other than Repositories, they are still persistence objects that are not simply EF wrappers and have unique functionality that should be unit tested.  So again, how do you unit test persistence objects, if you do not mock Entity Framework?  I may be misunderstanding the EF team’s response in this Github Issue Report for Entity Framework:, but counter to their argument, I think there is a strong use case for making this testing less cumbersome.

 

Posted in Uncategorized

Angular 2/4 Dynamic Content Woes

I have been working for sometime on an angular version of my fpnotebook.com website. I migrated from an Angular 1 version  to an Angular 2 (late beta) version.  I have been setting up a backend using asp.net core, and thought I would bring the Angular 2 beta version up to the Angular 4 release.  Overall, the upgrade process was starting off fairly smooth with instructions like these. That’s when I noticed the absence of dynamic content tools in Angular 4.

Side note: AngularJs (version 1) is now just called Angular, not Angular 2 or Angular 4 – just Angular.  But try web searching for Angular – finding relevant version specific content has become difficult.  So I am referring to it as Angular 2/4.

My fpnotebook.com content is medical information organized into 31 books (e.g. cardiology), 722 chapters (e.g. blood pressure) and 6407 pages (e.g. hypertension).  Each page is stored in folders using a book/chapter/page hierarchy,  for example: http://www.fpnotebook.com/CV/Htn/Hyprtnsn.htm.

For the angular app, I keep each page in a json file.  Pages are composed of outlines, and each block of the outline (think roman numerals I, II, III) are stored in an array of page blocks, like this:

{
"Heading": "Risk Factors",
"Content": "<ol><li>See <a href='#/library/CV/Prevent/CrdcRsk' class='LinkPage' data-cui='C0580320'>Cardiac Risk Factor</a>s</li></ol>"
},

Each of these blocks is the template for a component, and up until full release version of angular 2, I could dynamically insert this outline html content and have it be JIT (just-in-time) compiled and function as Angular code, including the links as RouterLinks.  Worked great.

And then came the push for smaller Angular distributions and ahead-of-time compilation (AOT), and away went dynamic content and JIT compilation.  The html can still be inserted into a component, but the html is no longer compiled.  The outline still looks like an outline, but it is not integrated with angular.  This means that RouterLinks, custom components, component events and data, do not work.

I thought there must still be a way, surely with all the old directive functionality that I could not previously understand;  surely there must be a way to do this.  And it would seem there are ways to dynamically insert components with the ComponentFactoryResolver, but I could not find a way to insert a template and have it compiled dynamically by Angular.

I then found this blog entry: Forget $compile in Angular 2, in which the component template html is modified as DOM elements. In effect you use query selectors (similar to jquery css selectors) to find html elements and  attach javascript event listeners directly.  This actually works,  but I initially resisted it.  Going outside of Angular to manipulate the DOM directly is not ideal.

So, I looked for various ways to use Angular facilitated approaches to dynamically create the equivalent to RouterLinks.   I tried various alternatives to using ElementRef, such as @ContentChildren(), but these would not work, since I still had uncompiled html.   I was however able to use the Angular Renderer2 service.

So, given the json format above, and a page component with markup like this:

 <app-page-block-html [innerHTML]="block.Content"></app-page-block-html>

Side Issue: Curiously, Angular removes data elements (e.g. data-cui=”C123456″) as part of its sanitize process of [innerHtml], and this breaks part of my functionality.  I’m not sure why the Angular team chose to black-list data elements.  How can you XSS attack with a data attribute?  However, there is a work around using a pipe here.   Hopefully the Angular team will reconsider – by disallowing innocuous attributes like the data attribute, they force work-arounds (e.g. bypass security methods) that open up larger security holes.

The following component code would load this dynamically with working links:

import { Component, OnInit, Input, Renderer2, ViewChild, ElementRef, ContentChildren, QueryList, Directive } from '@angular/core';
import { Router } from "@angular/router";

@Component({
 selector: 'app-page-block-html',
 templateUrl: './page-block-html.component.html',
 styleUrls: ['./page-block-html.component.less']
})

export class PageBlockHtmlComponent implements OnInit {
 
 private clickListeners: Function[] = [];

 constructor(private router: Router,private el:ElementRef, private renderer: Renderer2) { }

 ngAfterViewInit() { // for searching a components template
 const anchorNodes:NodeList = this.el.nativeElement.querySelectorAll('a[href]:not(.LinkRef)'); //or a.LinkPage

 const anchors:Node[] = Array.from(anchorNodes); //or Array.prototype.slice.call(anchorNodes);

 anchors.forEach(anchor => {
      let listener = this.renderer.listen(anchor,'click',e=>{
           e.preventDefault();
           let href = e.srcElement.getAttribute('href');
           this.router.navigateByUrl(href);
      });
 this.clickListeners.push(listener);

 }

 

So another hurdle circumvented with a process that works well despite my wishing there was a more best-practice way.  All due to the sacrifice of JIT and dynamic content for the speed/footprint of Angular with AOT.

 

Posted in Uncategorized

angular spa, asp.net core and authentication – Part 2, Authenticating with MVC

In Part 1, I discussed my rationale for the following set-up using asp.net core MVC for authentication for an  angular single page application (SPA) frontend and an asp.net core backend.  In this post, I’m going to build on concepts from Michel Dymel’s two project set-up, as well as parts of the MS Javascriptservices SPA template project.  I am setting this up on Windows, so I’ll be using Visual Studio 2017 Community Edition for backend editing, and VS Code for frontend.

Step 1: Asp.Net Core Backend/Server Project

  1. Within Visual Studio 2017, Create a new asp.net core project, inside a new solution
  2. Choose to create an MVC/API application with User Authentication (along with Git)
  3. If adding this to another git repo, then add a .gitignore file manually for VS project
  4. The backend project should remain the default project (bold in solution explorer)
  5. In project properties, under debug tab, note the App URL (http://localhost:port)
    1. The app url is used below in setting the proxy

newMvcApp2017-1

 newMvcApp2017-2

Step 2: Angular-Cli Frontend project

  1. Add a new netCore class library project inside the solution created above
    1. Delete the default class1.cs that is automatically created
  2. Open a powershell window here within this new project directory
  3. Prepare to use node/npm/angular-cli
    1. Install or update node (check version with “node -v”)
    2. Update angular-cli
      1. npm uninstall -g @angular/cli
      2. npm cache clean
      3. npm install -g @angular/cli@latest
  4. Create a new angular project via the command-line interface (CLI)
    1. ng new [projectname] –routing –style scss –prefix [myPrefix]
      1. choose your own projectname (e.g. frontend) and prefix (for components, directives)
      2. for style, select scss or less (css is the default)
      3. If  routing flag is specified, angular will automate routing set-up
    2.  Set a proxy configuration pointing to the asp.net core backend as above
      1. This uses Michal Dymel’s set-up 
      2. This will only be used for development (npm start)
      3. Create a “proxy.conf.json” file in the main frontend directory:
      4. {
          "/api": {
            "target": "http://localhost:61234",
            "secure": false
          }
        }
      5. Edit the start command in “package.json”
        1.   “start”: “ng serve –proxy-config proxy.conf.json”
        2. To use the proxy, run “npm start”, NOT “ng serve”
    3. Set up the production build pipeline for the angular app
      1. On “ng Build”, the angular app distribution is written to wwwroot
      2. In the angular-cli.json file, edit “OutDir”
      3.  “outDir”: “../backend/wwwroot/angular_dist/”
        1. Writing to wwwroot will clear the directory (angular-cli wipes it)
        2. Therefore, better to write to a subdir

Step 3: Other Angular Frontend Customizations

Now, for a compromise.  I want a fast set-up for the server login without much customization.   I typically use Bootstrap with angular, but instead of using jquery, I use ng-bootstrap, and I’ve started using Bootstrap 4, which is still in alpha version as I write this blog entry.

However,  Asp.net uses Bootstrap 3 and JQuery as its default, so I’m going to compromise and use this set-up for my app (Bootstrap 3, jquery).  I will be using the Sass version of Bootstrap.  Finally, the bootstrap css, and script libraries (jquery, bootstrap) should only be loaded once (client or server).  I need to load them either in the angular-cli.json or in the server _layout.cshtml.  Since I will frequently run the angular app in memory, outside of the asp.net app, I will want the scripts to be loaded via the angular-cli.json.  I’ll need to therefore make sure that the layout.cshtml used to hold the angular app does not load these scripts also.

Adding Boostrap V3

  1. npm install –save bootstrap-sass font-awesome jquery
  2. npm install @types/jquery –save-dev
  3. create empty file in “src/: _variables.scss” and add the following:
$icon-font-path: '../node_modules/bootstrap-sass/assets/fonts/bootstrap/';
$fa-font-path:'../node_modules/font-awesome/fonts';
  1. add to styles.scss file:
@import 'variables';
@import '../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap';
@import '../node_modules/font-awesome/scss/font-awesome';

Finally set styles and scripts objects in  the “angular-cli.json file:”

"styles": ["styles.scss"],
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
 "../node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js"
],

Step 4: AspNet MVC Index View to show the angular Spa

Change the “Backend\Views\Home\Index.cshtml” to contain the following code:

@{
 ViewData["Title"] = "Angular App";
 Layout = "_Layout_ngEmbed";
}

Loading...

@section scripts {
http://~/angular_dist/inline.bundle.js
http://~/angular_dist/polyfills.bundle.js
http://~/angular_dist/styles.bundle.js
http://~/angular_dist/vendor.bundle.js
http://~/angular_dist/main.bundle.js
}

Notice that the Layout is being set to a new file “Layout_ngEmbed.cshtml ” (instead of using the default _Layout.cshtml).  We need to customize a couple of items in the Layout file, specific for pages that have an embedded angular app:

  1. In the shared folder, copy “_Layout.cshtml” to a new file and name it “_Layout_ngEmbed.cshtml”
  2. Delete script files that will instead be loaded by the angular app
    1. Delete all links to the bootstrap.css
    2. Delete all script tags to bootstrap.js and jquery.js
  3. In the head section, add a base href tag (angular will need this):

Now, to show the frontend angular code embedded inside the backend MVC app:

  1. at the powershell prompt, type “ng build”
  2. In Visual Studio, in the backend app, “Ctrl F5” (run without debug)

To run the angular app alone, in memory, but still access the api:

  1. at the powershell prompt, “npm serve” (this will run “ng serve” with proxy)
  2. Note that the backend needs to be running (Ctrl-F5) for Api to work

Next Steps

That is it for a basic set-up.  The angular app can be run on its own to allow for rapid development and can still call the Api even when not embedded.  When embedded in the MVC app, login is possible and that single asp.net core MVC project (backend) can be deployed to a server.

Some additional to-do items:

  1. Login and call protected Apis either with tokens or cookies
  2. Login and authorize api access via claims or roles
  3. apply user information to app content (e.g. username as author)
  4. Build backend admin pages in MVC
  5. Automate frontend “ng build” as part of backend pre-build of the project
Posted in Uncategorized

angular spa, asp.net core and authentication – Part 1, The Idea

An increasingly common Single Page Application (SPA) client with server API backend solution is angular 2/4 with asp.net core API.  I especially like the approach by Michal Dymel where he creates 2 projects, asp.net core server and angular client.  Each project has its own tool set: I use Visual Studio Community Edition for the asp.net core server, and use angular command line interface (CLI) and Visual Studio Code for the client.  The angular cli allows for quick scaffolding of client projects, as well as components, directives, services, classes, routing…   When the angular-cli is built (ng build), the files are copied to a destination set in the configuration, and in this case to asp.net core wwwroot folder.   Works great.

However, authentication and authorization continue to be road blocks for me.  I have a server and can write code, manage databases and do not want to offload to a Saas solution.  Maybe I’ll implement an Identity Server solution at some point, but for now I want quick, light-weight set-ups, that do not get in the way of the core applications I want to write.

When I used Asp.net MVC, the authentication solution was available out of the box – simple and easy.   Tokens (JWT) are now the rage for spa client-server, but with this I need to write all my own authentication/login in my client for each client app, and then get the JWT token, client claims to my api calls…

I have looked at microsoft javascript services, Single Page Application (SPA) templates. The team that creates this is lead by Steve Sanderson of KnockoutJs fame.   They combine asp.net core with a SPA using your choice of  various frontend frameworks (angular, react…)  I like the idea, but I like Dymel’s 2 project solution  better since the angular-cli tool chain is kept intact, and you can use the most up to date version of the client frameworks.   With Dymel’s 2 project solution, the client build output still ends up in the wwroot folder.

One possible modification to the 2 project solution could be running the client application inside of a MVC view (this is how the MS javascriptservices template is organized).  This would allow me to use MVC for the login/authentication, anti-forgery tokens, and create a backend MVC admin portal, while the remainder of the application is all angular client and asp.net core api.  These calls could all rely on the login, as could the authorization which could be role based instead of claims based.  There may still be a CSRF attack risk, and I might still need to work tokens into the mix.

We’ll see how this works.  I plan to blog my experience implementing this in my next post.

Posted in Uncategorized | 1 Comment

Alice in Wonder Server

Everything is more complicated.   Monthly, I log the changes in medicine, and change some of the same topics over and over again.  Cardiac arrest, for example,  has been honed from a cocktail of medications to high quality chest compressions and early defibrillation.

On the programming side there are the pain points with asp.net core and angular 2. But nowhere am I confused more than in server management.   When divided into overall categories (basic configuration, users and group policies, IIS), and taught in tidy lectures on the web, it seems to make sense.  But then seemingly simple things break, and despite all those lectures, I cannot solve the most basic of server issues.  I would be lost without  Rackspace support.

So, I have tried to improve the situation and make server admin less of an Alice in Wonderland experience.  Pluralsight does have hands-on courses in server management.  I have started working through some of these (e.g. this and this).

These courses too have their frustrations, and I’m logging my fixes for problems I ran across while completing the windows server with powershell course.

  • VMWare Player is free for non-commercial use and works well for these courses
  • Microsoft windows server evaluation ISOs are available for 3-6 month trials
    • Download the ISO for Windows Server 2012 R2, and use Datacenter with GUI
    • Download the ISO for Windows 10 Enterprise
  • On installing VMWare Virtual Machines
    • Choose will select ISO later (otherwise requires a MS product key)
    • Leave the VM directories as default (too hard to change)
    • Once Server is installed, install VMWare Tools
      • Change VM Settings CD/DVD from ISO file to autodetect
      • When small notification appears “Select what to do…”  Click
  • Connections between VM servers has several hiccoughs
    • Turn off Norton firewall when making the initial connection
    • In VM Settings, change Network Adapter from NAT to Bridged (Automatic)
      • Powershell update-help seems to need NAT to work
  • Specific to the Windows Server with Powershell Course
    • In Chapter 1, Demo: Configure DC1
      • Server Administrator login username is Administrator
      • When adding AD users, credentials = administrator@wiredbrain.priv
      • These same AD credential username (email) is used in Chapter 2
        • Add-Computer -DomainName wiredbrain.priv
        • Enter-PSSession
    • In Chapter 2, Demo: Enabling Remote Management was painful
      • Get-DhcpServer4Lease did not work from Client1 (but worked on DC1)
      • Took hours to get “Enter-PSSession”
        • Used the administrator@wiredbrain.priv for username
        • Disable firewall
        • DC1 and Client1 VM Network router set to Bridged
        • Set WinRM Service to Automatic and Start
  • Other Issues
    • VM domain seems to interfere with the house network including internet
      • Power off the VMs when not in use

 

 

Posted in Uncategorized