Category: .NET Core

TILT-AMS – about my software-part 21

One of the most related are data that fill the database for developer – and do not fill into production

AMS ( About My Software) could help . It generates an unique class that inherits

public class AboutMySoftware
{

public string Authors { get; set; }

public bool IsInCI { get; set; }

public string SourceCommit { get; set; }

public string CISourceControl { get; set; }

public string AssemblyName { get; set; }

public DateTime DateGenerated { get; set; }

public string CommitId { get; set; }

public string RepoUrl { get; set; }

}
    

The IsInCI recognizes if it is build on CI( deployed to prod lately ) or without (in the dev PC)

So I use like this

bool IsBuildFromCI = new XAboutMySoftware_78102118871091131225395110108769286().IsInCI;
if (IsBuildFromCI)
{
    hc.AddSqlServer(builder.Configuration["ConnectionStrings:DefaultConnection"],name:"database SqlServer");
}
else
{
    hc.AddSqlite(cnSqlite, name: "database Sqlite");
}

if (!IsBuildFromCI)
{
    using (var scope = app.Services.CreateScope())
    {
        if (File.Exists("Tilt.db"))
            File.Delete("Tilt.db");

        var dbcontext = scope.ServiceProvider.GetRequiredService<ApplicationDBContext>();
        dbcontext.Database.EnsureCreated();

        //seed db
        dbcontext.TILT_URL.Add(new TILT_URL()
        {
            Secret = "Andrei",
            URLPart = "TestAddWithNoData"
        });
        dbcontext.TILT_URL.Add(new TILT_URL()
        {
            Secret = "test",
            URLPart = "ClickToSeeMyTILTS"
        });
        await dbcontext.SaveChangesAsync();
}

Tools used

Visual Studio

AMS ( About My Software) – https://github.com/ignatandrei/RSCG_AMS/

TILT-Angular 14 and small updates-part 20

It is always good to have the latest version of NuGet packages – if it does not break the application, of course. Easy task when you have some automated test -and Visual Studio is doing this for you.

However, to update an Angular application where the version is fixed – a nightmare. I will do in a full time.

Also, being deployed to Azure, a few clicks on AppInsights and you have monitoring the application without instrumenting the code.

Also, added a feature to the application – you can add now a link to your TILT. This small modification went also when to display the TILT – keep remembering that any modification that you will do to the model will reflect in more than 1 place in the GUI.

Also, modifying the interface – show first the TILTs in a list, rather than in a calendar format.

Now the Angular 14 is on market – see https://blog.angular.io/angular-v14-is-now-available-391a6db736af. I was impressed by Title and NgMOdel onPush

So – update the cli ( npm update -g @angular/cli ) and crating a new app (ng new ) and adding Angular (ng add @angular/material)

So now it is time to bring the code to

  1. Fix the versions

  2. Add the code from the Ang13 app

  3. Add the title

For 1:

Fix the versions in package.json

Delete the npm_modules

npm i

For 2: I use WinMerge with a custom filter to exclude node_modules

Added missing npm packages from the previous application

Fix again the versions

For 3:

This is the code for TILT:

import { Injectable, NgModule } from '@angular/core';
import {
  RouterModule,
  RouterStateSnapshot,
  Routes,
  TitleStrategy,
} from '@angular/router';
import { LoginUrlGuard } from './login-url.guard';
import { LoginUrlComponent } from './login-url/login-url.component';
import { MyTiltComponent } from './my-tilt/my-tilt.component';
import { OnePublicTiltComponent } from './one-public-tilt/one-public-tilt.component';
import { PublicTiltsComponent } from './public-tilts/public-tilts.component';
import { TiltMainComponent } from './tilt-main/tilt-main.component';

const routes: Routes = [
  {
    path: 'tilt/public',
    component: PublicTiltsComponent,
    title: 'List of public tilts',
  },
  { path: 'tilt/public/:id', component: OnePublicTiltComponent },
  { path: '', redirectTo: '/tilt/public', pathMatch: 'full' },
  {
    path: 'tilt/my',
    component: MyTiltComponent,
    canActivate: [LoginUrlGuard],
    title: 'My tilts',
  },
  {
    path: 'loginURL',
    component: LoginUrlComponent,
    title: 'Login to add a tilt',
  },
];

@Injectable()
export class TemplatePageTitleStrategy extends TitleStrategy {
  override updateTitle(routerState: RouterStateSnapshot) {
    const title = this.buildTitle(routerState);
    if (title !== undefined) {
      document.title = `TILT! - ${title}`;
    } else {
      var arr = routerState.url.split('/');
      if(arr.length==0)
        document.title = `TILT! - AAA`;
      else
        document.title = `TILT! - tilts for ` + arr[arr.length-1];
    }
  }
}

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [{provide: TitleStrategy,  useClass: TemplatePageTitleStrategy}],
})
export class AppRoutingModule {}

Tools used

npm

ng

Visual Studio Code

WinMerge

TILT-Server Timing in Browser-part 19

For see fast what is happening with your server, you can use the Server Timing API.

One of the implementations for .NET is https://github.com/tpeczek/Lib.AspNetCore.ServerTiming .

Not a big deal – implemented separately with AOPMethodsCommon – but I think it is a good idea to use it.

The implementation was straightforward

builder.Services.AddScoped<ServerTiming>();
var app = builder.Build();
app.UseServerTiming();

And then use DI to get the instance of the class.

With this occasion , look how is different calling same method twice

vs

If you do not realize, there are 50 ms vs 1 ms . That difference is from caching

private async Task<TILT_Note_Table[]?> privateLatestTILTs(string urlPart, int numberTILTS)
{
    if (cache.TryGetValue<TILT_Note_Table[]>(urlPart, out var result))
    {
        return result;
    }
//code
}

Nice, right ? See the timing right in your browser.

Tools used

https://github.com/tpeczek/Lib.AspNetCore.ServerTiming

https://github.com/ignatandrei/AOP_With_Roslyn/

TILT-caching- part 17

If you want to read about, see https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside

So , the public TILTS must be cached. Also, when a user makes a new TILT, the cache should be destroyed

The code for Memory Cache is very simple:

  1. Add to services
builder.Services.AddMemoryCache();
  1. Add an MemoryCache cache to the constructor
public MyTilts(IMemoryCache cache, 
  1. add caching to the function
 if (cache.TryGetValue<TILT_Note_Table[]>(urlPart, out var result))
            {
                return result;
            }
            
//code to retrieve
cache.Set(urlPart, ret,DateTimeOffset.Now.AddMinutes(10));
return ret;
  1. add destroy cache
await insert.InsertTILT_Note(noteOrig);
note.CopyFrom(noteOrig);
cache.Remove(url);   
  1. Modify tests to see this feature

TILT- cosmetic–part 16

The user must know something about the site. One of easy way is to display an intro – and I have choosed https://github.com/shipshapecode/shepherd

Also

  • display number of chars when putting a TILT

  • display a text area instead of an input
  • display links to my TILTS

Added also https://codescene.io/ . Can be valuable – but I should understand more how to use it.

Display latest date when it was deployed / compiled with AMS and the repo name. Added also links to Swagger and Blockly Automation

To see the progress , it is good to have a calendar.Discovered angular-calendar – to show events.

The exemaple at https://mattlewis92.github.io/angular-calendar/#/kitchen-sink is pretty self explanatory.

However, another 3 hours passed to have the display.

The ( quasy – final ) result can be seen below ( taken from http://tiltwebapp.azurewebsites.net/AngTilt/tilt/public/ignatandrei )


Tools

Tools Used

https://github.com/shipshapecode/shepherd

VSCode

https://github.com/ignatandrei/RSCG_AMS

Visua Studio

angular-calendar

TILT- GUI–part 15

Now the easy way for me is to create a web interface with Angular.

Nothing too complicated. This is how it looks for the TILTS at https://tiltwebapp.azurewebsites.net/AngTilt/tilt/public

Now , if I am going to a TILT Url , I can see the TILTs in the browser: https://tiltwebapp.azurewebsites.net/AngTilt/tilt/public/ignatandrei

For creating new TILTS , I can use the web interface https://tiltwebapp.azurewebsites.net/AngTilt/tilt/my

I enter a user name and a pasword and I can start adding the TILTS.

Tools Used

VSCode

Angular

TILT–CodeCoverage–part 14

The code coverage should be simple – just run tests and that’s all, right ?

For a reason, the coverlet console , dotnet-coverage ,dotnet test do not work – means that code coverage generated was 0% ( I have verified with dotnet-reportgenerator-globaltool )

The only that worked was altCover and this is the code into the yml:

dotnet test --no-build src/backend/Net6/NetTilt/NetTilt.sln  /p:AltCover=true /p:AltCoverAssemblyExcludeFilter="Humanizer|Moq|NUnit3|System|DB2GUI|AltCover|NetTilt.Tests" 

It was a good exercise. And now I have this: codecov

And for some tests written already, the code coverage is 46 %. A good one, I think …

Tools used

https://codecov.io

Moq

NUnit3

AltCover

Visual Studio

TILT–Analyzing code–part 13

I want a static analysis tool that can be used to check the quality of the code. SonarCloud.io is a great tool for this.

You can find the instructions for the tool here: https://sonarcloud.io/dashboard/index/organization/sonarcloud/project/sonarcloud-project-id

It was easy to set up – and it is free. You can see the results here: https://sonarcloud.io/summary/overall?id=ignatandrei_TILT

This is the result

Two were a false positive

var c = this.User?.Claims.ToArray();
if ((c?.Length ?? 0) == 0)
    return -1;
return c.Length;

and one was a problem ( comparing bool with null).

There was a security hotspot – based on Configuring in EF . No problem here.

Solving most of code smells were ok.

I have added also a badge Maintainability Rating

Tools used

https://sonarcloud.io

GitHub Actions

TILT- Tests- part 12

First, it is a decision between NUnit and XUnit. I took this time NUnit. Also, I take LightBDD to show data.

Let’s say I want to verify the rule that the user cannot make more than 1 TILT per day.

In order to do 1 TILT per day

  1. User must be authenticated and have have an URL registered into the database

  2. Code must verify that is no TILT for today ( i.e UTC Date)
  3. Code must insert the TILT into the database

I can work with a real database, but let’s see how we can Mock it – and run without database

This is the setup

namespace NetTilt.Tests;

[FeatureDescription(@"Test add a new TILT")]
[Label("FakesMocks")]
public partial class TestAdd
{
    ServiceProvider? serviceProvider;
    
    [SetUp]
    public void Setup()
    {

    }
    [Scenario]
    public async Task NewTilt() //scenario name
    {
       await Runner
            .AddSteps(_ => Given_No_TILT_For_URL())
            .AddAsyncSteps(_ => Then_Can_Add_A_New_TILT())
            .RunAsync();
    }
    [Scenario]
    public async Task Existing_TILT_Start_Of_The_Day() 
    {
        var minutes = DateTime.UtcNow.Subtract(DateTime.UtcNow.Date).TotalMinutes;
        minutes--;
        await Runner
              .AddSteps(_ => Given_Today_Is(DateTime.UtcNow))
             .AddSteps(_ => Given_Exists_One_TILT_ForDate(DateTime.UtcNow.AddMinutes(-minutes)))
             .AddAsyncSteps(_ => Then_Can_NOT_Add_A_New_TILT())
             .RunAsync();
    }
    [Scenario]
    [TestCase(2)]
    [TestCase(20)]
    [TestCase(1)]
    public async Task ExistingTILT_DaysAgo(int days) //scenario name
    {
        await Runner
              .AddSteps(_ => Given_Today_Is(DateTime.UtcNow))
             .AddSteps(_ => Given_Exists_One_TILT_ForDate(DateTime.UtcNow.AddDays(-days)))
             .AddAsyncSteps(_ => Then_Can_Add_A_New_TILT())
             .RunAsync();
    }
    [Scenario]
    [TestCase(1,false)]
    [TestCase(2, false)]
    [TestCase(20, false)]
    [TestCase(100, false)]
    [TestCase(200, false)]
    [TestCase(4*60, false)]
    [TestCase(5 * 60, false)]
    [TestCase(6 * 60, false)]
    [TestCase(7 * 60, false)]
    [TestCase(8 * 60, false)]
    [TestCase(9 * 60, false)]
    [TestCase(10 * 60, false)]
    [TestCase(11* 60, false)]
    [TestCase(12 * 60, false)]
    [TestCase(23 * 60, false)]
    [TestCase(23 * 60+58, false)]
    [TestCase(24 * 60 + 1, true)]
    public async Task ExistingTILT_MinutesAgo(int minutes, bool canAdd) //scenario name
    {
        var run =  Runner
              .AddSteps(_ => Given_Today_Is(DateTime.UtcNow))
              .AddSteps(_ => Given_Exists_One_TILT_ForDate(DateTime.UtcNow.Date.AddDays(1).AddMinutes(-minutes)));

        if (canAdd)
            run = run
             .AddAsyncSteps(_ => Then_Can_Add_A_New_TILT());
        else
            run = run
             .AddAsyncSteps(_ => Then_Can_NOT_Add_A_New_TILT());

        await run.RunAsync();
    }
    [Test]
    public async Task TestAddOneTilt()
    {
        var myTilt= serviceProvider.GetRequiredService<IMyTilts>();
        var data= await myTilt.AddTILT(new TILT_Note_Table(), null);
        Assert.IsNotNull(data);
    }
}

And this is the output of the tests in markdown

Results of tests (Passed:65)

TestAdd

Existing TILT Start Of The
Day

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
00:01:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT DaysAgo [days:
“2”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “04/29/2022
06:52:44”]
Passed
3 THEN Can Add A New TILT Passed

ExistingTILT DaysAgo [days:
“20”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “04/11/2022
06:52:44”]
Passed
3 THEN Can Add A New TILT Passed

ExistingTILT DaysAgo [days:
“1”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “04/30/2022
06:52:44”]
Passed
3 THEN Can Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“1”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
23:59:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“2”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
23:58:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“20”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
23:40:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“100”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
22:20:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“200”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
20:40:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“240”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
20:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“300”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
19:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“360”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
18:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“420”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
17:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“480”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
16:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“540”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
15:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“600”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
14:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“660”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
13:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“720”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
12:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“1380”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
01:00:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“1438”] [canAdd: “False”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “05/01/2022
00:02:00”]
Passed
3 THEN Can NOT Add A New TILT Passed

ExistingTILT MinutesAgo [minutes:
“1441”] [canAdd: “True”]

Number Name Status Comments
1 GIVEN Today Is [date: “05/01/2022
06:52:44”]
Passed
2 AND Exists One TILT ForDate [date: “04/30/2022
23:59:00”]
Passed
3 THEN Can Add A New TILT Passed

NewTilt


Number Name Status Comments
1 GIVEN No TILT For URL Passed
2 THEN Can Add A New TILT Passed

Tools used

Nunit

LightBdd

Microsoft.Extensions.DependencyInjection

Microsoft.NET.Test.Sdk Moq

NUnit

Visual Studio

TILT–Telemetry–part 11

I want to see what is happening in my application – i.e. having the Stack Trace for any kind of errors.

I have add with

    [AutoMethods(CustomTemplateFileName = "../AutoMethod.txt", MethodPrefix = "auto", template = TemplateMethod.CustomTemplateFile)]
    [AutoGenerateInterface]
    public partial class AuthUrl : IAuthUrl
    {

        [AOPMarkerMethod]
        private async Task<string?> privateLogin(string url, string secret)
        {
//code

And inside the method

var act=Activity.Current;
using var span = MyActivitySource.StartActivity("{{mi.NewName}}", ActivityKind.Client,act?.Context??default(ActivityContext));
{
try{
                //call original method
            }
            catch(Exception ex){
                span?.RecordException(ex);
                span?.SetTag("exceptionMessage",ex.Message);
                span?.SetStatus(Status.Error);
                throw;
            }
            finally{
                span?.Stop();
                
            }

The final result is ( showing an error into the database)


Tools used

AppInsights

Powershell ( AOPMethods.ps1)

OpenTelemetry.Api

OpenTelemetry.Contrib.Instrumentation.EntityFrameworkCore

OpenTelemetry.Extensions.Hosting

Azure.Monitor.OpenTelemetry.Exporter

OpenTelemetry.Instrumentation.AspNetCore

OpenTelemetry.Instrumentation.Http

OpenTelemetry.Instrumentation.SqlClient

Visual Studio

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.