Visual Studio Task List Feature

Visual Studio has a handy feature, Task List. Click on View->Task List.

Task list has tokens that are used to track code comments. This also acts as a shortcut to navigate to relevant code section. This list comes with 3 default tokens; TODO, HACK and !UnresolvedMergeConflict.

We can add custom tokens, if we want. Here is how;

Open Tools -> options -> Environment, you will see Task List.

Add a new custom token;

To make this feature working, All you need to do is to add comments in your code;

    /*
        HACK: I don't need serviceProviderId parameter here. The only reason I am adding this becuase this comes
        from a link in razor page list and I need to keep serviceProviderId and projectId in session. 
        Session starts here for now.
     */
    [HttpGet]
    [Route("ProjectTask/ProjectTaskList/{projectId:Guid}")]
    public async Task<IActionResult> ProjectTaskList(Guid projectId)
    {
        var result = await _httpFactoryService.GetProjectActionAsync(projectId);
        return View(result);
    }

Reference

Using the Task List

JSON Circular Reference Loop Error running Raw SQL in Web API using EF Core

I had a complex stored procedure that I needed to run using EF core in a Web API project. I cannot use LINQ to represent this query. I have followed all best practices outlined here;

Everything worked great except raw sql endpoint. It started giving me “Circular Reference loop error”. To keep thing simple, I am returning DTO from endpoint not the entity.

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'task' with type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Collections.Generic.IEnumerable`1[FM.Service.Shared.DTO.TranMasterViewDto],FM.Service.LedgerTranViewService+<GetTransactionForProjectActionAsync>d__4]'. Path 'stateMachine.<>t__builder'
......

Here is my configuration before and after the fix;

Newtonsoft Configuration in program.cs file before the fix;
}).AddNewtonsoftJson()
Newtonsoft Configuration in program.cs file after the fix;
}).AddNewtonsoftJson(
    options => 
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)

The error is gone and I am getting this results.

{
    "stateMachine": {
        "<>1__state": 0,
        "<>t__builder": {},
        "projectActionID": "82ee5154-971a-ed11-90e6-00155d717606",
        "trackChanges": false,
        "<>4__this": {}
    },
    "context": {},
    "moveNextAction": {
        "method": {
            "name": "MoveNext",

Wait…This is not what I expected. Why I am getting Tasks result where I need to see my Dto results.

It turns out that I am not returning results from my Async method but the task;

public async Task<IActionResult> GetTransactionForProjectActionAsync(Guid projectActionId)
{
   return Ok(_service.LedgerTranViewService.GetTransactionForProjectActionAsync(projectActionId, trackChanges: false));
        }

Fixing the return type has solved all of my problems;

return Ok(_service.LedgerTranViewService.GetTransactionForProjectActionAsync(projectActionId, trackChanges: false).Result);
        }
[
    {
        "id": 20221,
        "projectActionID": "82ee5154-971a-ed11-90e6-00155d717606",        
        "tranMasterDetail": [
            {
                "tranMasterId": "9358b0c5-6d30-ed11-90e8-00155d717606",
                "ledgerID": "63302216-0946-ea11-ac82-f81654967f7a",
                "tranDescription": "Rent paid",
                "tranDate": "2022-01-03T00:00:00",
                "tranFlag": 0,
                "tranAmount": 1300.00
            }
        ]
    }
]

Remove Newtonsoft ReferenceLoopHandler from program.cs file.

}).AddNewtonsoftJson()

Hope this will help someone.

Reference

https://stackoverflow.com/questions/62985907/avoid-or-control-circular-references-in-entity-framework-core

Resolve the issue of request matched multiple endpoints in .NET Core Web API

If there are two endpoint with same route, .NET Core Web API will throw request matched multiple endpoints error. Here is an example;

// api/menus/{menuId}/menuitems
[HttpGet("{menuId}/menuitems")]
public IActionResult GetAllMenuItemsByMenuId(int menuId)
{            
    ....
}

// api/menus/{menuId}/menuitems?userId={userId}
[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItemsByMenuAndUser(int menuId, int userId)
{
    ...
}

This is impossible because the actions are dynamically activated. The request data (such as a query string) cannot be bound until the framework knows the action signature. It can’t know the action signature until it follows the route. Therefore, we can’t make routing dependent on things the framework doesn’t even know yet.

Long and short, we need to differentiate the routes in some way: either some other static path or making the userId a route param. However, we don’t actually need separate actions here. All action params are optional by default. Therefore, we can just have:

[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItemsByMenu(int menuId, int userId)

And then we can branch on whether userId == 0 (the default). That should be fine here, because there will never be a user with an id of 0, but we may also consider making the param nullable and then branching on userId.HasValue instead, which is a bit more explicit.

We can also continue to keep the logic separate, if we prefer, by utilizing private methods. For example:

[HttpGet("{menuId}/menuitems")]
public IActionResult GetMenuItems(int menuId, int userId) =>
    userId == 0 ? GetMenuItemsByMenuId(menuId) : GetMenuItemsByUserId(menuId, userId);

private IActionResult GetMenuItemsByMenuId(int menuId)
{
    ...
}

private IActionResult GetMenuItemsByUserId(int menuId, int userId)
{
    ...
}

Have fun.

Read more here.

Swagger configuration

Two steps that i needed for this in .NET 6.

Add this to program.cs file;

// Register swagger generator, you can define multiple documents here
services.AddSwaggerGen(s =>
{
	s.SwaggerDoc("v1", new OpenApiInfo
	{
		Title = "FOO API",
		Version = "v1"
	});

	var xmlFile = $"{typeof(Presentation.AssemblyReference).Assembly.GetName().Name}.xml";
	var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
			s.IncludeXmlComments(xmlPath);
		});

Edit project .csproj file and add / change these nodes:

<PropertyGroup>

    <!-- 
    Make sure documentation XML is also included when publishing (not only when testing)
    see https://github.com/Azure/service-fabric-issues/issues/190
    -->
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DocumentationFile>bin\$(Configuration)\$(AssemblyName).xml</DocumentationFile>
  </PropertyGroup>

This also works with .NET Core 3.1. more info can be found here.

Angular13 and .NET 6 – Getting started

We would need to install Visual Studio 2022.

https://visualstudio.microsoft.com/

Install .NET 6 SDK

This can be downloaded either from Microsoft official URL;

https://dotnet.microsoft.com/en-us/download/dotnet/6.0

Or from the GitHub official release page;

https://github.com/dotnet/core/tree/main/release-notes/6.0

Check the SDK version by opening a command prompt;

> dotnet –help
> dot net –version

Install NVM

If we need to work with different Node.js version, we would need to install nvm.

To prepare for angular development, we would need following components;

  1. Nvm – Node Version Manager. Its is a tool that allows us to download install Node.js. It allows us to pick and choose the Node.js version.
  2. Node.js – Its is a platform for running Javascript applications.

To install node version manager for windows (nvm), click here;

https://github.com/coreybutler/nvm-windows/releases

Scroll to Assets tab and download either nvm-setup.zip or nvm-setup.exe.

If download is for nvm-setup.zip, Unzip download zip file and run nvm-setup.exe. Select Symlink for Node.js. When finished, run this command;

> nvm –version

To install node.js, use this;

//installs the latest version of node.js
> nvm install latest              

//this will install specific version of node.js
> nvm install <<version number>> 

If we have multiple versions of node.js and wanted to use a specific version in our environment, try this in elevated command prompt;

> nvm use 18.8.0

Install Angular CLI;

npm is alredy installed with Visual Studio 2022 installation. Time to install Angular CLI;

> npm install -g @angular/cli@13.0.1

To install latest version of angular cli, use this;
> npm install -g @angular/cli

If there are Cert error like this;

npm error code SELF_SIGNED_CERT_IN_CHAIN
npm error request to https://registry.npmjs.org/@types%2Fjquery failed, reason: self-signed certificate in certificate chain

Then disable Strict SSL mode by running this comand (make it true when done if you want to keep strict SSL mode with Github);

npm set strict-ssl false

https://stackoverflow.com/questions/29141153/nodejs-npm-err-code-self-signed-cert-in-chain

When finished, run following command to check the version;

> ng –version

In my case, I got this error message;

Since I have installed node.js latest version v18.8.0 but Angular 13 doesn’t’ support this. To resolve, head to this link;

https://nodejs.org/en/

So version 16.17.0 is the LTS version. Download and use this version using nvm;

> nvm install 16.17.0
> nvm use 16.17.0

I tried to use ng –version command on my computer but it didn’t work. I needed to re-run this command for angular cli installation;

> npm install -g @angular/cli@13.0.1

restart your computer and run this command again to check Angular CLI version;

> ng --version

This time installation is successful with this message;

Path Variables

If nvm doesn’t work, add it to the environment variable. Press win+I on windows 11. Under About -> “Device specifications” box, click on “Advanced system settings” and select environment variables.

Add nvm.exe to “User variables for admin” section. Here are the values;

Restart your computer. Open command window and run following command any where;

> nvm --version

This should work.

Check All versions

> nvm –-version
> npm –-version
> node –version
> ng –version</p>

If all commands run successfully, We are ready to rock-n-roll with Angular 13 and .NET 6.

Creating test project using Visual Studio 2022

Microsoft has a template, ASP.NET Core with Angular, to create .NET core project with Angular. It’s a single project template with front-end and back-end project. We will not be using this template for our test project. We will create two projects, front-end and back-end and connect those projects.

Create front-end project, e.g. Foo, using “Standalone Typescript Angular Project” template. Create back-end web API project, e.g. FooAPI, within same solution. Double click on launchsettings.json file and change ports to 5001 for https and 5000 for http.

On front-end project, under /src/proxy.conf.js, make sure the port is configured to be 5001. This is the port kestrel web server is listening for incoming requests.

const PROXY_CONFIG = [
  {
    context: [
      "/weatherforecast",
    ],
    target: "https://localhost:5001",
    secure: false
  }
]

module.exports = PROXY_CONFIG;

Angular development port configuration are in /.vscode/launch.json file. If you don’t see it, it might be hidden. Usually it’s mapped to HTTPS on port 4200.

Last step is to setup startup project for this multi-project solution. Right click on solution and click on “Set startup project”. Change startup project from “single startup project” to “multiple startup projects” and select “start” for each project. Move FooAPI project on top so it can start first.

Do a quick test run of these multi-projects in Debug mode by pressing F5. Visual Studio will launch 3 process;

  1. ASP.NET Core Server (Kestral or IIS Express)
  2. Angular Live Development Server (using “ng serve” command from the Angular CLI)
  3. Web Server (Google or Edge)

We will be seeing this basic page;

Angular component performing a simple data fetching task from ASP.NET Core Web API project. A small but good working example without any boilerplate code / extra fluff.

A sample diagram how these 3 process interact with each other;

All components are working as expected.

Update Angular Version

To update angular version within project workspace, run this;

ng update @angular/core@17 @angular/cli@17

Angular version information is located in package.json. To see which application is targeting which Angular project, refer to package.json file.

If you want to uninstall Angular, follow this