CategoriesProgramming

Benchmark Code dengan BenchmarkDotNet

Saat ini performa system merupakan hal yang sangat penting dan perlu diperhatikan bagi para developer. Semakin baik performa suatu system tentu akan membuat pengguna semakin nyaman menggunakannya. Untuk itu developer seperti kita perlu untuk melakukan Benchmark Code.

Apa itu Benchmark?

Benchmark adalah metode/langkah untuk mengukur serangkaian kode yang ada dalam sebuah fungsi. Dengan melakukan benchmark, kita bisa membandingkan kinerja kode mana yang lebih baik sehingga dapat mengoptimalkan system kita.

Untuk melakukan Benchmark Code, kita akan menggunakan tools dari DotNet yaitu BenchmarkDotNet.

Langkah Benchmark Code

  1. Buat Project baru
  2. Install BenchmarkDotNet Nuget package
  3. Buat Benchmark class
  4. Buat BenchmarkRunner instance
  5. Jalankan aplikasi dalam release mode
Continue reading
CategoriesProgramming

Membuat Planner dengan Microsoft Graph API

Microsoft Graph adalah platform dari Microsoft yang menghubungkan banyak layanan dan perangkat yang sudah disediakan oleh Microsoft. Dengan menggunakan Microsoft Graph, pengembang dapat melakukan integrasi layanan dengan layanan – layanan yang ada di Microsoft 365. Misal dalam tulisan ini saya ingin menggunakan layanan Microsoft Planner untuk membuat Task menggunakan API sendiri.

Berikut adalah langkah – langkahnya:

Continue reading
CategoriesProgramming

Pemetaan obyek dengan AutoMapper pada ASP .Net Core 3.1

AutoMapper adalah object to object mapper yang memetakan obyek A menjadi obyek B yang memiliki properti dan tipe yang berbeda. Seperti contoh kita perlu melakukan pemetaan Data Transfer Object ke object model. AutoMapper memudahkan proses pemetaan konvensional yang harus memetakan secara manual satu per satu.

Untuk menggunakan AutoMapper pada ASP .Net Core 3.1 terlebih dahulu harus menginstal AutoMapper melalui NuGet atau command pada NuGet Package Manager seperti ini.

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

Install AutoMapper.Extensions.Microsoft.DependencyInjection, bukan AutoMapper. Karena tujuan kita adalah membuat AutoMapper bisa digunakan diluar dari Startup.cs yang mana di dalam package itu sudah ada AutoMapper.

Setelah install, kita tambahkan di Startup.cs seperti ini.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
    services.AddControllers();
}

Dalam contoh ini saya akan memakai model WeatherForecast hasil dari create project di ASP .Net Core 3.1 Web API.

public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    public string Summary { get; set; }
}

Lalu kita buatkan model baru untuk target mapping kali ini. Kita namai WeatherRoom.

public class WeatherRoom
{
    public string Room { get; set; }
    public DateTime Date { get; set; }
    public int TemperatureC { get; set; }
    public int TemperatureR { get; set; }
    public string Summary { get; set; }
}

Setelah itu buatkan class baru AutoMapperProfile untuk membuat konfigurasi map sesuai kebutuhan.

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        //map object WeatherForecast menjadi WeatherRoom
        CreateMap<WeatherForecast, WeatherRoom>();
    }
}

Kita pindah ke WeatherForecastController.cs dan tambahkan Dependency Injection di constructor.

private IMapper _mapper;

public WeatherForecastController(ILogger<WeatherForecastController> logger, IMapper mapper)
{
    _logger = logger;
    _mapper = mapper;
}

Lalu tambahkan Endpoint API baru untuk mengambil data WeatherRoom hasil dari mapping WeatherForecast.

[HttpGet("WeatherRoom")]
public IEnumerable<WeatherRoom> GetWeatherRoom()
{
    var rng = new Random();
    //populate data WeatherForecast dengan random number 
    var weatherForeCastEnum = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    });
    //mapping data WeatherRoom dari WeatherForeCast
    var weatherRoom = _mapper.Map<IEnumerable<WeatherRoom>>(weatherForeCastEnum);
    return weatherRoom;
}

Setelah kita run, hasil dari weatherForeCastEnum adalah

[
  {
    "Date": "2020-07-05T10:11:48.6788616+07:00",
    "TemperatureC": -10,
    "TemperatureF": 15,
    "Summary": "Hot"
  },
  {
    "Date": "2020-07-06T10:11:48.7193388+07:00",
    "TemperatureC": -3,
    "TemperatureF": 27,
    "Summary": "Cool"
  },
  {
    "Date": "2020-07-07T10:11:48.7200952+07:00",
    "TemperatureC": 19,
    "TemperatureF": 66,
    "Summary": "Hot"
  },
  {
    "Date": "2020-07-08T10:11:48.7201173+07:00",
    "TemperatureC": -1,
    "TemperatureF": 31,
    "Summary": "Chilly"
  },
  {
    "Date": "2020-07-09T10:11:48.7201289+07:00",
    "TemperatureC": -13,
    "TemperatureF": 9,
    "Summary": "Balmy"
  }
]

Sedangkan hasil mapping ke WeatherRoom adalah

[
  {
    "room": null,
    "date": "2020-07-05T10:13:19.4494555+07:00",
    "temperatureC": 19,
    "temperatureR": 0,
    "summary": "Hot"
  },
  {
    "room": null,
    "date": "2020-07-06T10:13:19.4509221+07:00",
    "temperatureC": 53,
    "temperatureR": 0,
    "summary": "Balmy"
  },
  {
    "room": null,
    "date": "2020-07-07T10:13:19.4510079+07:00",
    "temperatureC": 25,
    "temperatureR": 0,
    "summary": "Warm"
  },
  {
    "room": null,
    "date": "2020-07-08T10:13:19.4510124+07:00",
    "temperatureC": 48,
    "temperatureR": 0,
    "summary": "Bracing"
  },
  {
    "room": null,
    "date": "2020-07-09T10:13:19.4510135+07:00",
    "temperatureC": 20,
    "temperatureR": 0,
    "summary": "Hot"
  }
]

Voilla, kita sudah berhasil melakukan mapping dari WeatherForecast ke WeatherRoom. Tapi, kita lihat ada beberapa properti yang valuenya masih default, apakah kita bisa mengatur properti tersebut otomatis?

Tentu bisa, kita bisa menggunakan fitur BeforeMap atau AfterMap. Apa itu?

BeforeMap adalah fungsi untuk merubah data dari input atau target sebelum melakukan mapping, sedangkan AfterMap adalah fungsi untuk merubah data dari input atau target setelah mapping. Hmm, kita coba saja biar lebih mudah memahaminya.

Kita ubah konfigurasi AutoMapper pada AutoMapperProfile seperti ini.

public AutoMapperProfile()
{
    //map object WeatherForecast menjadi WeatherRoom
    CreateMap<WeatherForecast, WeatherRoom>()
        .BeforeMap((f, r) => f.Summary = f.Summary + " asik")
        .AfterMap((f, r) => r.TemperatureR = Convert.ToInt32(f.TemperatureC * 0.45));
}

Pada fungsi BeforeMap, kita tambahkan teks “asik” pada summary, lalu pada AfterMap kita akan mengisi nilai dari TemperaturR dari hasil perhitungan TemperaturC  * 0.45.

Kita run sekali lagi hingga kita dapat hasil seperti ini.

weatherForeCastEnum

[
  {
    "Date": "2020-07-05T10:27:41.4824998+07:00",
    "TemperatureC": -17,
    "TemperatureF": 2,
    "Summary": "Chilly"
  },
  {
    "Date": "2020-07-06T10:27:41.5248275+07:00",
    "TemperatureC": 28,
    "TemperatureF": 82,
    "Summary": "Chilly"
  },
  {
    "Date": "2020-07-07T10:27:41.5255516+07:00",
    "TemperatureC": -19,
    "TemperatureF": -2,
    "Summary": "Chilly"
  },
  {
    "Date": "2020-07-08T10:27:41.5255696+07:00",
    "TemperatureC": -13,
    "TemperatureF": 9,
    "Summary": "Chilly"
  },
  {
    "Date": "2020-07-09T10:27:41.5255805+07:00",
    "TemperatureC": 47,
    "TemperatureF": 116,
    "Summary": "Mild"
  }
]

weatherRoom

[
  {
    "room": null,
    "date": "2020-07-05T10:28:09.5609512+07:00",
    "temperatureC": -6,
    "temperatureR": -3,
    "summary": "Mild asik"
  },
  {
    "room": null,
    "date": "2020-07-06T10:28:09.575253+07:00",
    "temperatureC": -11,
    "temperatureR": -5,
    "summary": "Warm asik"
  },
  {
    "room": null,
    "date": "2020-07-07T10:28:09.5752684+07:00",
    "temperatureC": 51,
    "temperatureR": 23,
    "summary": "Cool asik"
  },
  {
    "room": null,
    "date": "2020-07-08T10:28:09.575271+07:00",
    "temperatureC": 32,
    "temperatureR": 14,
    "summary": "Freezing asik"
  },
  {
    "room": null,
    "date": "2020-07-09T10:28:09.5752734+07:00",
    "temperatureC": 18,
    "temperatureR": 8,
    "summary": "Chilly asik"
  }
]

Kita sudah berhasil melakukan mapping beserta custom map datanya. Mudah bukan?

Semoga bermanfaat 😀

CategoriesProgramming

Menambah IdentityUser Property di Identity ASP.Net Core

Identity pada ASP.Net Core ada untuk memudahkan kita menambahkan user dan mengatur user management pada website. Bahkan Identity sudah bisa menghandle  TwoFactorAuthentication, ExternalLogins dll. Secara default, identity akan membuat user dengan bentuk model seperti berikut.

Bisa kita lihat IdentityUser hanya terdiri dari beberapa property dan tidak bisa kita ubah. Lalu bagaimana jika kita butuh untuk menambah property?

Misalnya kita akan menambah property “Address” pada user, berikut langkahnya

Buat Model Baru

Mari kita buat Model baru yang extend pada IdentityUser

using Microsoft.AspNetCore.Identity;
namespace CustomIdentityUser.Models
{
    public class ApplicationUser: IdentityUser
    {
        public string Address { get; set; }
    }
}

Update Database Context

Ubah extend DatabaseContext menjadi “IdentityDbContext<ApplicationUser>”. Sehingga menjadi seperti ini

namespace CustomIdentityUser.Data
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions options)
            : base(options)
        {
        }
    }
}

Update Startup

Ubah configurasi Identity dari IdentityUser

services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores();

Menjadi ApplicationUser

services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores();

Update Views/Shared/_LoginPartial.cshtml

Ubah kode berikut

@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

Menjadi

@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

Add Default Identity Pages

  1. Klik kanan pada project
  2. Pilih Add > New Scaffolded Item
  3. Pilih Identity dan tekan Add
  4. Kamu bisa pilih override all files, atau hanya pilih beberapa yang kamu butuhkan. Misal saat ini kita pilih Account/Register
  5. Pilih database context yang sudah tersedia

Langkah ini akan membuat page register secara otomatis.

Register.cshtml.cs

Tambahkan property Address pada InputModel

public string Address { get; set; }

Tambahkan Address pada ApplicationUser di OnPostAsync

var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email, Address = Input.Address };

Register.cshtml

Tambahkan input untuk address pada form

<div class="form-group">
    <label asp-for="Input.Address"></label>
    <input asp-for="Input.Address" class="form-control" />
    <span asp-validation-for="Input.Address" class="text-danger"></span>
</div>

Add Migration dan Update Database

Tambahkan migrasi dengan command berikut pada Package Manager Console

add-migration AddCustomUser

Lalu update database dengan command

update-database

Jalankan website dan coba lakukan register

Dan saat kita buka di database, bisa dilihat sudah muncul Addres pada table AspNetUsers