Add Service in ASP.NET Core 2.1
Tags: csharp, webdev
Published: 2020-06-15 07:13:38

Setup Service in ASP.NET CORE 2.1, We need register Service in Startup.cs. When we build project, Service in Startup.cs class file, will be start
In project, we througth register much service, so need add service to Startup.cs file, when start
You can see it: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1#service-lifetimes-and-registration-options

+ **Transient** :  The object is always different. Every time we call it, it create a new object
+ **Scoped** : Created once for each request, the objects have the same scope in a request and it uses the same instance in other calls in the same web request.
+ **Singleton** : Singleton objects are the same for every object and every request. The service is created only once.

Okay, now create project.

Steps 1: In Visual Studio 2019, **File->New**, select Project
Steps 2: Select Create a new project
Steps 3: Select **ASP.NET Core Web Application template**
Steps 4: Enter name project, select Create
Steps 5: Select **.NET Core**, **ASP.NET Core 2.1**, Select **Web Application (Model-View-Controller)**, after then click Create

If you create project complete, go to Models folder, create model Product.cs file
+ **Models/Product.cs**
```csharp
public class Product
    {
        public int idProduct { get; set; }
        public string Title { get; set; }
        public string UrlImage { get; set; }
        public decimal Price { get; set; }
        public string Detail { get; set; }

    }
```
Create **(Scoped, Singleton, Transient)** folder

**Transient**
Go to Services/Transient directory, create two file(ITransient.cs,ItemTransientService.cs)
+ **Services/Transient/ITransient.cs**
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AddServiceASP_core21.Models;
namespace AddServiceASP_core21.Services.Transient
{
    public interface ITransient
    {
		//return product
        Product getProduct();

		//return server count
        int countService();
    }
}
```
+ **Services/Transient/ItemTransientService.cs** : Inherits from **ITransient.cs**, to build the methods defined in **ITransient.cs**
```csharp
using AddServiceASP_core21.Models;
namespace AddServiceASP_core21.Services.Transient
{
    public class ItemTransientService : ITransient
    {
        Product product;
        int count=0;
        public ItemTransientService()
        {
            product = new Product
            {
                idProduct = 1,
                Title = "Test Transient:" + Guid.NewGuid(),
                UrlImage = "Transient.jpg",
                Price = 79000,
                Detail = "Transient"
            };

        }
        public Product getProduct()
        {
            count++;
            return product;

        }
        public int countService()
        {
            return count;
        }
    }
}
```
After when we setup complete, now we need register it to **Startup.cs** file
Steps 1: **using AddServiceASP_core21.Services.Transient;**
Steps 2: Register **using AddServiceASP_core21.Services.Transient;** in ConfigureServices method
Okay, go to Controllers folder->add new **ProductController.cs**
```csharp
using AddServiceASP_core21.Services.Transient;
namespace AddServiceASP_core21.Controllers
{
    public class ProductController : Controller
    {
        /*Transient*/
        private readonly ITransient _transient1;
        private readonly ITransient _transient2;

        public ProductController(ITransient transient1, ITransient transient2)
        {
            _transient1 = transient1;
            _transient2 = transient2;

        }
        public IActionResult Index()
        {
            //Transient
            ViewBag.data01 = _transient1.getProduct();
            ViewBag.count01 = _transient1.countService();
            ViewBag.data02 = _transient2.getProduct();
            ViewBag.count02 = _transient2.countService();

            return View();
        }
    }
}
```
+ **Views/Product/Index.cshtml:**
```csharp
@model IEnumerable<Product>
@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    //Transient
    var data01 = ViewBag.data01;
    var data02 = ViewBag.data02;
}
<h2>Transient</h2>
<span>@data01.Title - [Price:@data01.Price] - CountServer:@ViewBag.count01</span>
<br />
<span>@data02.Title - [Price:@data02.Price] - CountServer:@ViewBag.count02</span>
```
**Demo Transient:**
![Add Service in ASP.NET Core 2.1](https://hoanguyenit.com/public/upload/images/add-services-aspnet-core21.JPG)

In the figure above, we see ID always different, Server always create, so params Count always is 1

**Singleton**
+ **Services/Singleton/ISingleton.cs**
```csharp
using AddServiceASP_core21.Models;
namespace AddServiceASP_core21.Services.Singleton
{
    public interface ISingleton
    {
        Product getProduct();
        int countService();
    }
}
```
+ **Services/Singleton/ItemSingletonService.cs**
```csharp
using AddServiceASP_core21.Models;
namespace AddServiceASP_core21.Services.Singleton
{
    public class ItemSingletonService : ISingleton
    {
        Product product;
        int count = 0;

        public ItemSingletonService()
        {
            product = new Product
            {
                idProduct = 1,
                Title = "Test Singleto:" + Guid.NewGuid(),
                UrlImage = "Singleto.jpg",
                Price = 79000,
                Detail = "Singleto"
            };

        }
        public Product getProduct()
        {
            count++;
            return product;

        }
        public int countService()
        {
            return count;
        }

    }
}
```
Okay, we need register it to **Startup.cs**
**services.AddSingleton<ISingleton, ItemSingletonService>();** in ConfigureServices method
+ Controllers/ProductController.cs: modify the following below code
```csharp
using AddServiceASP_core21.Services.Transient;
using AddServiceASP_core21.Services.Singleton;
namespace AddServiceASP_core21.Controllers
{
    public class ProductController : Controller
    {
        /*Transient*/
        private readonly ITransient _transient1;
        private readonly ITransient _transient2;

        /*SingletoService*/
        private readonly ISingleton _singleton1;
        private readonly ISingleton _singleton2;

        public ProductController(ITransient transient1, ITransient transient2,ISingleton singleton1, ISingleton singleton2)
        {
            _transient1 = transient1;
            _transient2 = transient2;

            _singleton1 = singleton1;
            _singleton2 = singleton2;

            _scoped1 = scoped1;
            _scoped2 = scoped2;

        }

        public IActionResult Index()
        {
            //Transient
            ViewBag.data01 = _transient1.getProduct();
            ViewBag.count01 = _transient1.countService();
            ViewBag.data02 = _transient2.getProduct();
            ViewBag.count02 = _transient2.countService();

            //Singleto
            ViewBag.data03 = _singleton1.getProduct();
            ViewBag.count03 = _singleton1.countService();
            ViewBag.data04 = _singleton2.getProduct();
            ViewBag.count04 = _singleton2.countService();

            return View();
        }
    }
}
```
+ **Views/Product/Index.cs**
```csharp
@model IEnumerable<Product>

@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    //Transient
    var data01 = ViewBag.data01;
    var data02 = ViewBag.data02;


    //Singleto
    var data03 = ViewBag.data03;
    var data04 = ViewBag.data04;


}

<h2>Transient</h2>
<span>@data01.Title - [Price:@data01.Price] - CountServer:@ViewBag.count01</span>
<br />
<span>@data02.Title - [Price:@data02.Price] - CountServer:@ViewBag.count02</span>

<p>----------------------------------------------</p>

<h2>Singleto</h2>
<span>@data03.Title - [Price:@data03.Price] - CountServer:@ViewBag.count03</span>
<br />
<span>@data04.Title - [Price:@data04.Price] - CountServer:@ViewBag.count04</span>
```
**Demo Transient & Scoped:**
![Add Service in ASP.NET Core 2.1](https://hoanguyenit.com/public/upload/images/add-services-aspnet-core21-02.JPG)
You see the figure above, The Product object does not change the ID despite repeated refreshes, But the Count increases, that is, the Server only runs once, it stores the object and uses it again
![Add Service in ASP.NET Core 2.1](https://hoanguyenit.com/public/upload/images/add-services-aspnet-core21-03.JPG)
**Scoped**
+ Services/Scoped/IScoped.cs
```csharp
using AddServiceASP_core21.Models;
namespace AddServiceASP_core21.Services.Scoped
{
    public interface IScoped
    {
        Product getProduct();
        int countService();
    }

}
```
+ **Services/Scoped/ItemScopedService.cs**
```csharp
using AddServiceASP_core21.Models;
namespace AddServiceASP_core21.Services.Scoped
{
    public class ItemScopedService : IScoped
    {
        Product product;
        int count = 0;
        public ItemScopedService()
        {
            product = new Product
            {
                idProduct = 1,
                Title = "Test Scoped:" + Guid.NewGuid(),
                UrlImage = "Scoped.jpg",
                Price = 79000,
                Detail = "Singleto"
            };
        }
        public Product getProduct()
        {
            count++;
            return product;

        }
        public int countService()
        {
            return count;
        }
    }
}
```
+ **Controllers/ProductController.cs**
```csharp
using AddServiceASP_core21.Models;
using AddServiceASP_core21.Services.Transient;
using AddServiceASP_core21.Services.Singleton;
using AddServiceASP_core21.Services.Scoped;
namespace AddServiceASP_core21.Controllers
{
    public class ProductController : Controller
    {
        /*Transient*/
        private readonly ITransient _transient1;
        private readonly ITransient _transient2;

        /*SingletoService*/
        private readonly ISingleton _singleton1;
        private readonly ISingleton _singleton2;

        /*ScopedService*/
        private readonly IScoped _scoped1;
        private readonly IScoped _scoped2;
        public ProductController(ITransient transient1, ITransient transient2,ISingleton singleton1, ISingleton singleton2, IScoped scoped1,IScoped scoped2)
        {
            _transient1 = transient1;
            _transient2 = transient2;

            _singleton1 = singleton1;
            _singleton2 = singleton2;

            _scoped1 = scoped1;
            _scoped2 = scoped2;

        }

        public IActionResult Index()
        {
            //Transient
            ViewBag.data01 = _transient1.getProduct();
            ViewBag.count01 = _transient1.countService();
            ViewBag.data02 = _transient2.getProduct();
            ViewBag.count02 = _transient2.countService();

            //Singleto
            ViewBag.data03 = _singleton1.getProduct();
            ViewBag.count03 = _singleton1.countService();
            ViewBag.data04 = _singleton2.getProduct();
            ViewBag.count04 = _singleton2.countService();


            //Scoped
            ViewBag.data05 = _scoped1.getProduct();
            ViewBag.count05 = _scoped1.countService();
            ViewBag.data06 = _scoped2.getProduct();
            ViewBag.count06 = _scoped2.countService();


            return View();
        }
    }
}
```
We need register Scode in **Startup.cs** file,
**services.AddScoped<IScoped, ItemScopedService>();**
+ **Startup.cs (full code)**
```csharp
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using AddServiceASP_core21.Services.Transient;
using AddServiceASP_core21.Services.Singleton;
using AddServiceASP_core21.Services.Scoped;
namespace AddServiceASP_core21
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            //Transient
            services.AddTransient<ITransient, ItemTransientService>();
            //Singleto
            services.AddSingleton<ISingleton, ItemSingletonService>();
            //Scoped
            services.AddScoped<IScoped, ItemScopedService>();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Product}/{action=Index}/{id?}");
            });
        }
    }
}
```
+ **Views/Product/Index.cshtml**
```csharp
@model IEnumerable<Product>

@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    //Transient
    var data01 = ViewBag.data01;
    var data02 = ViewBag.data02;


    //Singleto
    var data03 = ViewBag.data03;
    var data04 = ViewBag.data04;

    //Scoped
    var data05 = ViewBag.data05;
    var data06 = ViewBag.data06;

}

<h2>Transient</h2>
<span>@data01.Title - [Price:@data01.Price] - CountServer:@ViewBag.count01</span>
<br />
<span>@data02.Title - [Price:@data02.Price] - CountServer:@ViewBag.count02</span>

<p>----------------------------------------------</p>

<h2>Singleto</h2>
<span>@data03.Title - [Price:@data03.Price] - CountServer:@ViewBag.count03</span>
<br />
<span>@data04.Title - [Price:@data04.Price] - CountServer:@ViewBag.count04</span>

<p>----------------------------------------------</p>

<h2>Scoped</h2>
<span>@data05.Title - [Price:@data05.Price] - CountServer:@ViewBag.count05</span>
<br />
<span>@data06.Title - [Price:@data06.Price] - CountServer:@ViewBag.count06</span>
```
**Demo Transient & Singleto & Scoped**
![Add Service in ASP.NET Core 2.1](https://hoanguyenit.com/public/upload/images/add-services-aspnet-core21-04.JPG)

We see Scoped on the image above, the ID does not change, it only changes when refreshing the page, and Count it always changes
It only creates a new request object once, so the ID doesn't change, and that's why its Count increased by 2.
Each time you request the page again, it will create a new object
Github:https://github.com/skipperhoa/add-services-aspcore
The Article:[Add Service in ASP.NET Core 2.1](https://hoanguyenit.com/add-service-in-aspnet-core-21.html)