ASP.NET Core etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
ASP.NET Core etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

30 Nisan 2019 Salı

.Net Core Uygulamasında Redis Cache Kullanımı


Bu yazıda Docker üzerinde bir Redis Container'ı koşturup, artından bir .Net Core Mvc projesinde nasıl kullanılacağını inceleyeceğiz. Redis (distributed cahce)' de amaç, bir web sayfası yada bir web API' dan gelen istekler olduğunda her seferinde servise ya da DB'ye gitmektense bu istekleri In Memory olarak yani ram'den karşılanması ve bu sayede performansın arttırılmasıdır.

Yazının tamamında kullanılacak teknolojiler;
  • Docker
  • Redis
  • .Net Core
Öncelikle eğer makinamızda Docker yok ise https://www.emrakin.com/2019/04/docker-nedir-neden-kullanlr-nasl.html bu adresten Docker kurulumu hakkında bilgi edinebilirsiniz.

Docker üzerinde bir Redis Container koştumak için aşağıdaki kodu kullanalar "6379" portundan ayağa kalkması sağlanır.
docker run -d --name Redis -p 6379:6379 redis

Ben .Net Core Mvc projesinde Redis için ServiceStack kullandım. İlgili kütüphaneyi https://www.nuget.org/packages/ServiceStack.Redis.Core bu linkten inceleyebilir ve Nuget ile projenize ekleyebilirsiniz.
PM> Install-Package ServiceStack.Redis.Core

Redis'in .Net Core projesinde kullanımı için Startup.cs'de AddDistributedRedisCache() methodu ile redisserver'ın IP ve Portu'nu tanımlıyoruz.
public void ConfigureServices(IServiceCollection services)
{
     services.Configure<CookiePolicyOptions>(options =>
     {
           options.CheckConsentNeeded = context => true;
           options.MinimumSameSitePolicy = SameSiteMode.None;
     });
     services.AddDistributedRedisCache(options =>
     {
            options.InstanceName = "RedisNetCoreSample";
            options.Configuration = "localhost:6379"; //Your Redis Connection
      });

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

AddDistributedRedisCache() methodunu Startup.cs' de kullanmak için Microsoft.Extensions.Caching.Redis'i Nugetten projenize dahil etmeniz gerekiyor.
PM> Install-Package Microsoft.Extensions.Caching.Redis

Models: Models klasörü altında Person.cs adında bir sınıf oluşturuyoruz.
public class Personal
{
     public int ID { get; set; }
     public string Name { get; set; }
     public string Surname { get; set; }
     public int Age { get; set; }
 }

Projemize RedisRepository adında bir klasör ekliyoruz. Bu klasör altında Redis'le ilgili işlemlerimizi bir interface yapı da tutacağız. RedisRepository klasörünün altında IRedisService adında bir interface oluşturuyoruz.
public interface IRedisService
{
     List<Person> GetAll(string cachekey);
     Person GetById(string cachekey);
 }

RedisRepository klasörü altına IRedisService.cs den  inheritance olmuş RedisManager.cs adında bir sınıf oluşturuyoruz.
public class RedisManager : IRedisService
{
    public List<Person> GetAll(string cachekey)
        {
            using (IRedisClient client = new RedisClient())
            {
                List<Person> dataList = new List<Person>();
                List<string> allKeys = client.SearchKeys(cachekey);
                foreach (string key in allKeys)
                {
                    dataList.Add(client.Get<Person>(key));
                }
                return dataList;
            }
        }

        public Person GetById(int personId, string cachekey)
        {
            using (IRedisClient client = new RedisClient())
            {
                var redisdata = client.Get<Person>(cachekey);

                return redisdata;
            }
        }
}

IRedisServise ve RedisManager'ı Startup.cs'e dahil etmemiz gerekiyor.

public void ConfigureServices(IServiceCollection services)
{
      services.Configure<CookiePolicyOptions>(options =>
      {
             options.CheckConsentNeeded = context => true;
             options.MinimumSameSitePolicy = SameSiteMode.None;
      });
      services.AddDistributedRedisCache(options =>
      {
            options.InstanceName = "RedisNetCoreSample";
            options.Configuration = "localhost:6379"; //Your Redis Connection
      });

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

      services.AddScoped<IRedisService, RedisManager>();
}

HomeController.cs/HomeController(): Öncelikle person sınıfı tipinde yeni bir kayıt oluşturup Redis cache'e atıyoruz.

- "cachedata.SetValue("Person"+personvalue.ID, personvalue);": Redis'de "Person+ID" key'ine karşılık value değeri olarak oluşturulan dataByte[] dizisi SetValue() methodu ile atıyoruz.

private readonly IRedisService _redisService;

public HomeController(IRedisService redisService)
{
      _redisService = redisService;
   
     using (IRedisClient client = new RedisClient())
     {
           if (client.SearchKeys("Person*").Count == 0)
           {
                 var personvalue = new Person();
                 personvalue.ID = 1;
                 personvalue.Name = "Emrah";
                 personvalue.Surname = "Akın";
                 personvalue.Age = 40;

                 var cachedata = client.As<Person>();
                 cachedata.SetValue("Person"+personvalue.ID, personvalue);

            }
      }
}

HomController.cs/Index: Redis'e "Person" key'i ile atılan tüm verileri getirmek için "Person*" ile çağırıyoruz.
public IActionResult Index()
{
      const string cacheKey = "Person*";
      var redisdata = _redisService.GetAll(cacheKey);

      return View(redisdata);
}

Index.cshtml:  View modelden gelenleri ekrana yansıtıyoruz

@model IEnumerable<NetCoreRedis.Models.Person>
@{
    ViewData["Title"] = "Index";
}

<table class="table">
    <thead>
        <tr>
            <th>
                ID
            </th>
            <th>
                Name
            </th>
            <th>
                SurName
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>

        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.ID)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Surname)
                </td>
                <td>
                    @Html.ActionLink("Details", "Home", new { id = item.ID }) |
                </td>
            </tr>
        }
    </tbody>
</table>

HomeController.cs/Detail: 
public IActionResult Detail(int Id)
{
    string cacheKey = "Person"+Id;
    var redisdata = _redisService.GetById(cacheKey);

     return View(redisdata);
}

Detail.cshtml: 
@model NetCoreRedis.Models.Person
@{
    ViewData["Title"] = "Detail";
}

<h3><b>Person:</b></h3>

<table class="table">
    <tr>
        <td>Ad:</td>
        <td>@Model.Name</td>
    </tr>
    <tr>
        <td>Soyad:</td>
        <td>@Model.Surname</td>
    </tr>
    <tr>
        <td>Yaş:</td>
        <td>@Model.Age</td>
    </tr>
</table>


Docker container olarak ayaklandırdığımız Redis cache üzerinden key value'larımızı görmek için terminal ekranına aşağıdaki kodu yazdıktan sonra "Keys *" komunu kullanabilirsiniz.

docker exec -it Redis redis-cli

Projenin bitmiş haline https://github.com/emrakin/.NetCore-Redis buradan ulaşabilirsiniz.

İlgili Kaynaklar:

21 Eylül 2018 Cuma

.Net Core File Upload

.Net Core kullanarak dosyaları karşıya yüklemenin bir çok yolu vardır.
Benim şimdiye kadar kullandığım en basit yol aşağıda bahsettiğim şekilde. Daha basit bir yol bulursam bu kodu güncelleyeceğim.

view (cshtml) :


<form method="post" asp-action="Upload" asp-controller="Home" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" value="upload"/>
</form>


controller(cs) :

Eğer Dosyayı uygulamınızda bir dizine yüklemek istiyorsanız, webroot yolunu almak için IHostingEnvironment'i kullanmalısınız.


 public class HomeController : Controller
    {
        private readonly IHostingEnvironment _environment;

        public HomeController(IHostingEnvironment environment) {_environment = environment; }

        public IActionResult Upload()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Create(IFormFile Getfile)
        {
           string fileName = Guid.NewGuid().ToString();
           if (Getfile != null)
           {
               var Upload = Path.Combine(_environment.WebRootPath, "Dosya Yolu",fileName);
               Getfile.CopyTo(new FileStream(Upload, FileMode.Create));
           }
            return View();
        }
    }


Umarım faydalı olmuştur...