Angular2: Retrieve data property from Angular2 routes

Standard

Quick hack to retrieve data value from routes is by using NavigationEnd event. Example below is to show page header or breadcrumb title by using data attribute on angular2 routes, we setup title property within data attribute on route and then access title value in main component which serve as main layout component of application.

Angular2 Routes Config:

@NgModule({
    imports: [
        RouterModule.forRoot([
            {
                path: 'foo',
                component: FooComponent,
                pathMatch: 'full',
                data: { title: 'Foo' }
            },
            {
                path: 'tweet',
                component: BarComponent,
                pathMatch: 'full',
                data: { title: 'Bar' }
            }
        ])
    ],
    exports: [
        RouterModule
    ]
})

Component retrieving data property:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    templateUrl: './app/app.component.html'
})

export class AppComponent implements OnInit{
    pageTitle: string;

    constructor(private router: Router) {
    }

    ngOnInit() {
        this.router.events
            .filter((event: any) => event instanceof NavigationEnd)
            .subscribe(() => {
                var root = this.router.routerState.snapshot.root;
                while (root) {
                    if (root.children && root.children.length) {
                        root = root.children[0];
                    } else if (root.data && root.data["title"]) {
                        this.pageTitle = root.data["title"];
                        return;
                    } else {
                        return;
                    }
                }
            });
    }
}

ASP.NET Core: Register Angular2 routes with CORE MVC routes

Standard

In order to integrate your Angular2 routes within your ASP.NET application, register all angular2 routes as unified entity within Core MVC routes configuration.

Angular2 Routes:

import { NgModule } from '@angular/core';
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { FooComponent } from './foo.component';
import { BarComponent } from './bar.component';

@NgModule({
    imports: [
        RouterModule.forRoot([
            {
                path: '',
                redirectTo: '/foo',
                pathMatch: 'full',
                data: { title: 'Dashboard' }
            },
            {
                path: 'foo',
                component: FooComponent,
                pathMatch: 'full',
                data: { title: 'Foo' }
            },
            {
                path: 'tweet',
                component: BarComponent,
                pathMatch: 'full',
                data: { title: 'Bar' }
            }
        ])
    ],
    exports: [
        RouterModule
    ]
})

export class AppRoutingModule { }

ASP.NET Core Startup.cs Routes:

public void Configure(IApplicationBuilder app)
        {
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(
                    name: "foobar",
                    template: "{*url}",
                    defaults: new { controller = "Home", action = "Index" });
            });
        }

ASP.NET Core: Step by Step Guide to Access appsettings.json in web project and class library

Standard

In ASP.NET Core configuration API provides a way of configuring an app based on a list of name-value pairs that can be read at runtime from multiple sources.Its time to get over with web.config to store and access appSettings keys. Please note that class libraries don’t have an appsettings.json by default. The solution is simple to access appsettings.json key/value pairs in your project through Dependency Injection principle in ASP.NET Core. DI has been already part of Core framework, You just have to register your dependencies in startup.cs file under ConfigureService method.

My appsettings.json

{
  "ServiceSettings": {
    "NewsMainUrl": "https://newsapi.org",
    "NewsApiKey": "abc"
  },

  "BALSettings": {
    "Source": "xyz",
    "FilterTerms": "abc;def;"
  }
}

Step 1: Create Model/Entities classes that has properties that match the settings in a section in appsettings.json

Create a class for BALSettings

namespace Tweet.Entities
{
    public class BALSettings
    {
        public string Source { get; set; }
        public string FilterTerms { get; set; }
    }
}

Create a class for ServiceSettings

namespace Tweet.Entities
{
    public class ServiceSettings
    {
        public string NewsMainUrl { get; set; }
        public string NewsApiKey { get; set; }
    }
}

Please note that in case you want to access the section of appsettings.json in class library project, then create above entities class in separate class library project in order to avoid circular dependencies conflict between projects in one solution. There is strong chance your web project might be dependent on that class library project.

screenshot_2

Step 2: Register appsettings.json section with relevant model classes in DI container

You need to get the appsettings.json section and then bind it, It is done by populating relevant model classes and adding them to the IOptions collection in the DI container and then registering them in Configure() method of the Startup class of ASP.NET Core project

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
   services.Configure<BALSettings>(Configuration.GetSection("BALSettings"));
   services.Configure<ServiceSettings>(Configuration.GetSection("ServiceSettings"));
}

Step 3: Access appsettings.json section in MVC or WebAPI controller in ASP.NET Core Project

You can access that class from any method that the framework calls by adding it as a parameter in the constructor. The framework handles finding and providing the class to the constructor. Include Microsoft.Extension.Options in controller to work with IOption collection.

using Microsoft.Extensions.Options;

public class TestController: Controller
{  
    private readonly IOptions<BALSettings> _balSettings;
    private readonly IOptions<ServiceSettings> _serviceSettings; 

    public TestController(IOptions<BALSettings> balSettings,
                          IOptions<ServiceSettings> serviceSettings)
    {
        _balSettings = balSettings;
        _serviceSettings = serviceSettings;
    }
 
    public IActionResult About()         
    {
       ViewData["Source"] = _balSettings.Value.Source;
       ViewData["NewsMainUrl"] = _serviceSettings.Value.NewsMainUrl;
    }
}

 

Step 4: Access appsettings.json section in Class Library Project

Asp.Net Core DI resolve all dependencies before creating controller. As we have already registered our model classes which are containing relevant sections of appsettings.json in startup code.

I have a class library project and I am accessing appsettings.json section in it using below code.

screenshot_4

using Microsoft.Extensions.Options;

public class NewsService : INewsService
    {
        private readonly IOptions<ServiceSettings> _serviceSettings;

        public NewsService(IOptions<ServiceSettings> serviceSettings)
        {
            _serviceSettings = serviceSettings;
        }

        public string composeUrl()
        {
            return _serviceSettings.Value.NewsMainUrl + "&apiKey=" + _serviceSettings.Value.NewsApiKey;
        }
    }

 

Please Note:
If you wan to access appsettings.json key/value data in class library project then you have to add Microsoft.Extensions.Options from NUGET to your relevant class library project, otherwise IOptions collection wouldn’t be accessible to class library project.

Nuget package manager console command:

PM> Install-Package Microsoft.Extensions.Options 

or using nuget package manager

screenshot_5

C#: Extension method to append specific character at start of each matching word in string

Standard
using System.Text.RegularExpressions;

public static string ReplaceKeywordsWithHashtags(this string data, params string[] filterTerms)
        {
            foreach (string term in filterTerms)
            {
                var item = term.Trim();
                if (!string.IsNullOrEmpty(item))
                {
                    if (data.ToLower().Contains(item))
                        data = Regex.Replace(data, item, '#' + item, RegexOptions.IgnoreCase);
                }
            }
            return data;
        }

Usage:

string temp = "Hello World! Hello World! Hello World! Hello World!";
string[] filter = {"abc", "xyz", "hello"};
string result = temp.ReplaceKeywordsWithHashtags(filter);

C#: Extension method to compare string against multiple other specific words

Standard
public static class Utilities
{
     public static bool ContainsAny(this string data, params string[] filter)
     {
            foreach (string term in filter)
            {
                var item = term.Trim();
                if (!string.IsNullOrEmpty(item))
                {
                    if (data.ToLower().Contains(term))
                        return true;
                }
            }
            return false;
     }
}

Usage:

string temp = "Hello World! Hello World! Hello World! Hello World!";
string[] filter = {"abc", "xyz", "hello"};
bool result = temp.ContainsAny(filter);

C#: Extension method to Limit character in string using linq

Standard
public static class Utilities
    {
        public static string LimitTo(this string data, int length)
        {
            return (data == null || data.Length < length)
              ? data
              : data.Substring(0, length);
        }
    }

Usage:

string temp = "Hello World! Hello World! Hello World! Hello World!";
var result = str.LimitTo(150)

ASP.NET Core: Error – InvalidOperationException Unable to resolve service for type foo while attempting to activate bar

Standard

DI is for objects that have complex dependencies. Controllers, services, adapters, and repositories are all examples of objects that might be added to DI. In order to implement Dependency Injection by constructor in ASP.NET core. We have to use DI Containers (Autofac, Ninject, StructureMap). I was working on side project in ASP.NET core, came across this particular issue relevant to DI.

An unhandled exception occurred while processing the request.  
InvalidOperationException: Unable to resolve service for type 'Tweet.BAL.INewsData'
while attempting to activate 'Tweet.Controllers.TweetController'.

screenshot_4

Solution:

Good news is that DI has been already part of Core framework, You just have to register your dependencies in startup.cs file under ConfigureService method.

services.AddTransient<IFoo, Foo>();
services.AddSingleton<IBar, Bar>();
services.AddScoped<IHello, Hello>();

The first generic type represents the type (typically an interface) that will be requested from the container. The second generic type represents the concrete type that will be instantiated by the container and used to fulfill such requests.

ASP.NET services can be configured with the following lifetimes:

Transient

Transient objects are always different; a new instance is provided to every controller and every service.

Scoped

Scoped objects are the same within a request, but different across different requests

Singleton

Singleton objects are the same for every object and every request (regardless of whether an instance is provided in ConfigureServices)

C#: Error – ‘System.Net.Http.HttpContent’ does not contain a definition for ‘ReadAsAsync’ and no extension method

Standard

I was working with HttpClient class to connect to external REST API’s from C# code and was implementing solution with asynchronous programming(Async / Await). Since class library project already have reference of System.Net.Http but I was having issue with extension method ReadAsAsync<T>()

'HttpContent' does not contain a definition for 'ReadAsAsync' and no extension method 
'ReadAsAsync' accepting a first argument of type 'HttpContent' could be found 
(are you missing a using directive or an assembly reference?)

screenshot_2

Solution:

ReadAsAsync is declared in the class HttpContentExtensions, which is in the namespace System.Net.Http in the library System.Net.Http.Formatting.

Right click on project and click Add a reference option, then go to Extensions from 
Assemblies tab and choose System.Net.Http.Formatting. If its not there then add 
manually this assembly, which is also available in the folder:
C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies 

screenshot_3

 

Alternate Solution:

Execute below command in NUGET console, make sure command is executed only relevant to that project

Install-Package Microsoft.AspNet.WebApi.Client

 

Angular2: Step by Step guide of using Angular Material 2 with Angular2 & Typescript for ASP.NET Core in Visual Studio 2015

Standard

Angular Material 2.0.0 has been released recently for Angular 2. In order to integrate Angular Material in project, follow the below steps:

Step 1: Install npm package for angular material, hammerjs, material typing

npm install --save @angular/material hammerjs
npm install --save-dev @types/angular-material @types/hammerjs

screenshot_6

Note:
The slide-toggle and slider components have a dependency on HammerJS.

Step 2: Include hammerjs to the types section of tsconfig.json file

{
  "compilerOptions": {
    "types": [
      "hammerjs"
    ]
  }
}

 

Step 3: Include @angular/material to the SystemJS configuration in case project is SystemJS for module loading

System.config({
  map: {
    ...,
    '@angular/material': 'npm:@angular/material/bundles/material.umd.js'
  }
});

Note:
Actual material 2 website state ‘npm:@angular/material/material.umd.js’ but I am getting error by systemjs, unable to find materialjs file, so simple solution is fix in url: ‘npm:@angular/material/bundles/material.umd.js’

Step 4: Include material css and hammerjs explicitly in _Layout.cshtml

 @{ var lib = "@angular"; }

<environment names="Development">
  <link href="~/node_modules/@lib/material/core/theming/prebuilt/indigo-pink.css" />
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  http://~/node_modules/hammerjs/hammer.min.js
</environment>

 

Step 5: Import the Angular Material NgModule

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { HttpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';

import { MaterialModule } from '@angular/material';
import 'node_modules/hammerjs/hammer.js';

import { DashboardMainModule } from './dashboard/dashboard.module';
import { AppComponent } from './app.component';
import { AppRoutingModule  } from './app.routing';
import { APP_PROVIDERS } from './app.provider';

@NgModule({
    imports: [
        //angular builtin module
        BrowserModule,
        HttpModule,

        //ui module
        MaterialModule.forRoot(),

        //application feature module
        DashboardMainModule,
        AppRoutingModule 
    ],
    declarations: [
        AppComponent
    ],
    providers: [
        APP_PROVIDERS
    ],
    bootstrap: [
        AppComponent
    ],
    schemas: [
        CUSTOM_ELEMENTS_SCHEMA
    ]
})

export class AppModule {
}

Finally material integration is done and running.

screenshot_7

ASP.NET Core/MVC: Error – The name ‘angular’ does not exist in the current context on Compilation

Standard

In case you are integrating Angular2 and Angular Material 2 with your ASP.NET Core and ASP.NET MVC project, you might need to include css or js files explicitly in layout.cshtml.

screenshot_5

As you can see red squiggly line on @angular, simple reason is ‘@’ character is Razor server side symbol, so Razor View Engine is throwing up exception.

screenshot_4

Solution:

Declare @lib variable in razor view to handle @angular as part of value for href.

@{ var @lib= "@angular"; }

<environment names="Development">
   <link href="~/node_modules/@lib/material/core/theming/prebuilt/indigo-pink.css" />
</environment>