...

ASP.NET CORE Introduction — Part 3

Table of contents

    In this days in­ver­sion of con­trol in every­where. That is a fact. We also face this pat­tern when cre­at­ing ASP.​NET Core ap­pli­ca­tions. So let’s ask our self the ques­tion if our cur­rent so­lu­tion in using this de­sign pat­tern. There can only be one an­swer “No”. And that is a shame. Be­cause the an­swer should be “Yes”. So let’s try to change this sit­u­a­tion.

    First let’s wind a place when the in­ver­sion of con­trol ap­proach can be use­ful. The an­swer is sim­ple. In­ver­sion of con­trol pat­tern should to use while get­ting hello mes­sage. So let’s to that. We need to start by cre­at­ing an in­ter­face and a class. That will be used to get hello mes­sage.

    In­ter­face

    namespace CoreDemo
    {
        public interface IHelloService
        {
            string GetHelloMessage();
        }
    }
    
    

    Class

    namespace CoreDemo
    {
        public class HelloService: IHelloService
        {
            public string GetHelloMessage()
            {
                return "Example Hello";
            }
        }
    }
    

    As we can see, IHel­loSer­vice and Hel­loSer­vice ale very sim­ple. Get just re­turn string. We will change it soon, don’t worry. At this mo­ment we need to con­cen­trate at the In­ver­sion of con­trol. So let’s try to use this new ser­vice ac­cord­ing to this pat­tern.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
     
    namespace CoreDemo
    {
        public class Startup
        {
            public Startup(IHostingEnvironment hostingEnvironment)
            {
                var configurationBuilder = new ConfigurationBuilder()
                    .SetBasePath(hostingEnvironment.ContentRootPath)
                    .AddJsonFile("appsettings.json");
     
                this.Configuration = configurationBuilder.Build();
            }
     
            public IConfiguration Configuration { get; set; }
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
            }
     
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IHelloService helloService)
            {
                loggerFactory.AddConsole();
     
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
     
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync(helloService.GetHelloMessage());
                });
            }
        }
    }
    

    That look fine. Does not it? Con­fig­ure method pa­ra­me­ter got ex­tended for a needed ser­vice. We used it just like, for ex­am­ple Log­ger­Fac­tory. So let’s see if it all works.

    I doesn’t. Get ques­tion is why. It looks all ok. We cre­ated an in­ter­face and a class, and added it just like other pa­ra­me­ters it Con­fig­ure method. It all should be right. Right? Wrong!!!!

    El­e­ments like Log­ger­Fac­tory get reg­is­tered by de­fault. In case of cus­tom ser­vices we un­for­tu­nately need to reg­is­ter them by our self. So let’s do that.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
     
    namespace CoreDemo
    {
        public class Startup
        {
            public Startup(IHostingEnvironment hostingEnvironment)
            {
                var configurationBuilder = new ConfigurationBuilder()
                    .SetBasePath(hostingEnvironment.ContentRootPath)
                    .AddJsonFile("appsettings.json");
     
                this.Configuration = configurationBuilder.Build();
            }
     
            public IConfiguration Configuration { get; set; }
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddSingleton<IHelloService, HelloService>();
            }
     
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IHelloService helloService)
            {
                loggerFactory.AddConsole();
     
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
     
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync(helloService.GetHelloMessage());
                });
            }
        }
    }
    

    It is not hard. All we need to do is to use ser­vice method. In this case it is method to add sin­gle­ton.

    Final touch

    Now that all the el­e­ments are in place there is only one more thing to do. We need to make Hel­loSer­vice ac­tu­ally work­ing. So it needs to get data from the set­tings file and use IOC pat­tern.

    using Microsoft.Extensions.Configuration;
     
    namespace CoreDemo
    {
        public class HelloService: IHelloService
        {
            private string _hello;
            public HelloService(IConfiguration configuration)
            {
                _hello = configuration["HelloMessage"];
            }
            public string GetHelloMessage()
            {
                return _hello;
            }
        }
    }

    This is how ser­vice looks now. The in­ter­est­ing thing is that it uses ICon­fig­u­ra­tion via the IOC pat­tern. So it needs to be reg­is­tered, be­fore it can be used. Just like in pre­vi­ous case. Let’s see how it is done now.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
     
    namespace CoreDemo
    {
        public class Startup
        {
            public Startup(IHostingEnvironment hostingEnvironment)
            {
                var configurationBuilder = new ConfigurationBuilder()
                    .SetBasePath(hostingEnvironment.ContentRootPath)
                    .AddJsonFile("appsettings.json");
     
                this.Configuration = configurationBuilder.Build();
            }
     
            public IConfiguration Configuration { get; set; }
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddSingleton(Configuration);
                services.AddSingleton<IHelloService, HelloService>();
            }
     
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IHelloService helloService)
            {
                loggerFactory.AddConsole();
     
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
     
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync(helloService.GetHelloMessage());
                });
            }
        }
    }
    

    It is dif­fered ap­proach. In this case we add con­fig­u­ra­tion ob­ject as via the sin­gle­ton method. We can do that when we want to pre­pare ob­ject be­fore pass­ing it to IOC con­tainer. In can come very handy in some sit­u­a­tions.


    Karol Rogowski