اشتراک‌ها
شروع به کار با IdentityServer 6

Creating an IdentityServer 6 Solution

00:00 Self-Signed Certificate
04:40 Docker Compose
07:30 PostgreSQL Database
09:40 IdentityServer
1:15:30 API
1:40:15 Console Application
1:50:35 Web Application
2:07:10 Single-Page Application 

شروع به کار با IdentityServer 6
اشتراک‌ها
نحوه برقراری ارتباط بین #C و Event Store در docker-compose

نحوه برقراری ارتباط بین #C و Event Store  از طریق تعریف اینترفیس شبکه و اختصاص IP در docker-compose 


version: '3.4'

services:
  eventstoresample: 
    image: eventstoresample
    build:
      context: .
      dockerfile: EventStoreSample/Dockerfile
    networks:
      clusternetwork:
        ipv4_address: 172.16.0.12

  eventstore: 
    image: eventstore/eventstore
    environment:
      - EVENTSTORE_INT_IP=172.16.0.13
      - EVENTSTORE_EXT_HTTP_PORT=2113
      - EVENTSTORE_EXT_TCP_PORT=1113
      - EVENTSTORE_EXT_HTTP_PREFIXES=http://*:2113/
    ports:
      - "1113:1113"
      - "2113:2113"
    networks:
      clusternetwork:
        ipv4_address: 172.16.0.13

networks:
  clusternetwork:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 172.16.0.0/24


نحوه برقراری ارتباط بین #C و Event Store  در docker-compose
اشتراک‌ها
یک روش ساده برای دور زدن تحریم ها !

با توجه به اینکه یکسری از سایت‌ها مثل docker و بعضی از repo‌های لینوکسی و .... ایران رو تحریم کردند و نمیشه از سرویس هاشون استفاده کرد اتفاقی با این سایت برخورد کردم که راه حل جالب و ساده ای برای رفع این مشکل در ایران ارائه داده.

شرکت بنیان سرویس ارائه داده است که تحریم‌شکن می‌باشد. بر این اساس شما DNS Server خود را به IP این شرکت تغییر می‌دهید بعد از آن درخواست‌های شما برای سرویس‌های تحریم شده پاسخ داده می‌شود.

توضیحات کامل این سرویس در آدرس زیر قرار دارد. شما با این روش نیز می‌توانید ایمیج‌های داکر را بدون مشکل دریافت کنید. 

یک روش ساده برای دور زدن تحریم ها !
اشتراک‌ها
آزمون اطلاعات عمومی JavaScript

JS Is Weird
JavaScript is a great programming language, but thanks to the fact that its initial release was built in only ten days back in 1995, coupled with the fact that JS is backward-compatible, it's also a bit weird. It doesn't always behave the way you might think. In this quiz, you'll be shown 25 quirky expressions and will have to guess the output. Even if you're a JS developer, most of this syntax is probably, and hopefully, not something you use in your daily life. 

آزمون اطلاعات عمومی JavaScript
مطالب
آشنایی با Jaeger
 در سال‌های اخیر، معماری میکروسرویس، یکی از محبوب‌ترین روش‌ها برای طراحی نرم‌افزار بوده‌است. جهت بهبود کارآیی، رفع خطا، درک  عملکرد سیستم در محیط عملیاتی و  نمایش چگونگی فراخوانی سرویس‌ها توسط یکدیگر می‌توانیم از ابزار‌های distributed tracing استفاده کنیم. ابزارهای متنوعی برای این منظور وجود دارند، اما بطور کلی همه با روش مشابهی کار می‌کنند. اطلاعات مربوط به فعالیت‌هایی مثل فراخوانی سرویس و مراجعه به دیتابیس که درون میکروسرویس رخ می‌دهد، در یک span  ذخیره می‌شوند. Span‌های جداگانه توسط شناسه‌ای یکتا به هم مرتبط می‌شوند و به عنوان یک trace نمایش داده می‌شوند. با استفاده از این trace‌ها، مجموعه‌ای از اطلاعات مثل تاریخ شروع و پایان هر درخواست و هر فعالیت را در اختیار داریم. 


جهت گرفتن دیتای مربوط به هر span، درون هر میکروسرویس می‌توانیم از پروژه‌های متن باز OpenTracing  و یا  OpenTelemetry استفاده کنیم. کتابخانه OpenTracing.Contrib.NetCore پیاده سازی OpenTracing در دات نت می‌باشد و می‌تواند  فعالیت‌های مربوط به ASP.NET Core، Entity Framework Core System.Net.Http (HttpClient)، System.Data.SqlClient و Microsoft.Data.SqlClient را دریافت و به tracer  ارسال کند. 

برای پیاده سازی distributed tracing، می‌توانیم از ابزار متن باز و محبوب Jaeger (با تلفظ یِگِر)  که ابتدا توسط شرکت Uber منتشر شد، استفاده کنیم. نحوه کارکرد Jaeger بصورت زیر می‌باشد:




ساده‌ترین روش  برای راه‌اندازی Jager، استفاده از داکر ایمیج All in one که شامل ماژول های agent ، collector،  query  و ui  است. پورت 6831 مربوط به agent  و پورت 16686 مربوط به ui می‌باشد. برای جزئیات مربوط به ماژول‌های مختلف از این لینک استفاده کنید.

docker run -d -p 6831:6831/udp -p 6832:6832/udp -p 14268:14268 -p 14250:14250 -p 16686:16686 -p 5778:5778  
--name jaeger jaegertracing/all-in-one:latest

بعد از اجرای دستور بالا، اطلاعات مربوط به سرویس‌ها و trace ها  در ماژول Jager UI  با آدرس http://localhost:16686 قابل مشاهده است. 

جهت استفاده از Jaeger از پروژه تستی که شامل دو سرویس User و Gateway می‌باشد، استفاده می‌کنیم. در سرویس User، متد AddUser در صورت عدم وجود کاربر در دیتابیس، اطلاعات کاربر از گیت‌هاب را دریافت و در دیتابیس ذخیره می‌کند. سرویس Gateway از Ocelot برای مسیردهی درخواست‌ها استفاده می‌کند. برای آشنایی با ocelot‌ این پست را  مطالعه نمایید. 


    public async Task<ApiResult<Models.User>> AddUserAsync(string username)
        {

            var result = new ApiResult<Models.User>();
            
            var user = await _applicationDbContext.Users.FirstOrDefaultAsync(x => x.Login == username);

            if (user is null)
            {
                try
                {
                    var url = string.Format(_appConfig.Github.ProfileUrl, username);
                    var apiResult = await _httpClient.GetStringAsync(url);
                    var userDto = JsonSerializer.Deserialize<UserDto>(apiResult);
                    user = _mapper.Map<Models.User>(userDto);
                    await _applicationDbContext.Users.AddAsync(user);
                    await _applicationDbContext.SaveChangesAsync();
                    result.Result = user;
                    result.Message = "User successfully Created";
                    return result;
                }
                catch (Exception e)
                {
                    result.Message = "User not found";
                    return result;
                }
            }

            result.Message = "User already exist";
            result.Result = user;

            return result;

        }


برای ثبت Trace مربوط به درخواست‌ها در Jaeger ، بعد از نصب  پکیج‌های Jaeger و OpenTracing.Contrib.NetCore در هر دو سرویس، در کانفیگ هریک از سرویس‌ها مورد زیر را اضافه می‌کنیم:

"JaegerConfig": {
    "Host": "localhost",
    "Port": 6831,
    "IsEnabled": true,
  "SamplingRate": 0.5
  }


و برای اضافه شدن tracer به برنامه از متد الحاقی زیر استفاده می‌کنیم:

 public static class Extensions
    {
        public static void AddJaeger(this IServiceCollection services, IConfiguration configuration)
        {
            var config = configuration.GetSection("JaegerConfig").Get<JaegerConfig>();
            
            if (!(config?.IsEnabled ?? false))
                return;

            if (string.IsNullOrEmpty(config?.Host))
                throw new Exception("invalid JaegerConfig");

            services.AddSingleton<ITracer>(serviceProvider =>
            {
                string serviceName = Assembly.GetEntryAssembly()?.GetName().Name;

                ILoggerFactory loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();

                var sampler = new ProbabilisticSampler(config.SamplingRate); 

                var reporter = new RemoteReporter.Builder()
                    .WithLoggerFactory(loggerFactory)
                    .WithSender(new UdpSender(config.Host, config.Port, 0))
                    .WithFlushInterval(TimeSpan.FromSeconds(15))
                    .WithMaxQueueSize(300)
                    .Build();
                
                ITracer tracer = new Tracer.Builder(serviceName)
                    .WithLoggerFactory(loggerFactory)
                    .WithSampler(sampler)
                    .WithReporter(reporter)
                    .Build();

                GlobalTracer.Register(tracer);

                return tracer;
            });

            services.AddOpenTracing();
        }
    }


برای ثبت trace‌ها استراتژی‌های متفاوتی وجود دارد. در اینجا از ProbabilisticSampler استفاده شده‌است که در سازنده‌ی آن می‌توان درصد ثبت Trace‌ها را مقدار دهی کرد. در نهایت این متد الحاقی را در Startup اضافه می‌کنیم:

builder.Services.AddJaeger(builder.Configuration);


بعد از اجرای پروژه و فراخوانی https://localhost:6000/gateway/Users/Add ، سرویس Gateway، درخواست را به سرویس User ارسال می‌کند و این سرویس‌ها در  Jaeger UI  قابل مشاهده هستند.




جهت مشاهده trace ‌ها ، سرویس مورد نظر را انتخاب و روی Find Traces کلیک کنید. با کلیک روی Trace مورد نظر، جزئیات فعالیت هایی مثل فراخوانی سرویس و مراجعه به دیتابیس قابل مشاهده است. 


برای اضافه کردن لاگ سفارشی به یک span، می‌توان از اینترفیس ITracer  استفاده کرد:

        private readonly IUserService _userService;
        private readonly ITracer _tracer;

        public UsersController(IUserService userService, ITracer tracer)
        {
            _userService = userService;
            _tracer = tracer;
        }
        [HttpPost]
        public async Task<ActionResult> AddUser(AddUserDto model)
        {
            var actionName = ControllerContext.ActionDescriptor.DisplayName;
            
            using var scope = _tracer.BuildSpan(actionName).StartActive(true);
            
            scope.Span.Log($"Add user log username: {model.Username}");
            
            return Ok(await _userService.AddUserAsync(model.Username));
        }  



کدهای مربوط به این مطلب در اینجا قابل دسترسی است. 

نظرات مطالب
بررسی Bad code smell ها: کلاس بزرگ
مطلبی رو  اینجا دیدم که به نظر طنز هست و مرتبط به مطلب جاری
In the C++ world we don’t create a class witch contains 5 methods and 2 fields like in Java or C#. We do more. A lot more. Our class are consequent and take a lot of stuff inside because it is interesting to have a project with 10 files of 100 KB rather than 300 files of 3 KB organized with fuzzy concepts. We do OOP better. It’s more compact, it’s real, it just works
اشتراک‌ها
NET Core 3. و پشتیبانی از Windows Desktop Applications

At Microsoft Build Live today, we are sharing a first look at our plans for .NET Core 3. The highlight of .NET Core 3 is support for Windows desktop applications, specifically Windows Forms, Windows Presentation Framework (WPF), and UWP XAML. You will be able to run new and existing Windows desktop applications on .NET Core and enjoy all the benefits that .NET Core has to offer. 

NET Core 3. و پشتیبانی از Windows Desktop Applications
اشتراک‌ها
سری ساخت microservices به کمک معماری Event Driven

In this tutorial, I will show how to use the clean architecture, with methods and tools such as domain driven disign (DDD), Test (Behavior) Driven development (TDD), CQRS, Event Sourcing, Containerization, Oauth2 & Oidc to build a microservices architecture 

سری ساخت microservices به کمک معماری Event Driven
اشتراک‌ها
نگاهی به Duende IdentityServer 5

Securing your application is bloody important. With so much jargon to sift through, it’s easy to get lost, for example there’s SSO, OAuth2, SAML 2.0, OpenID Connect, Federated Identity, 2FA, & MFA. Just to name a few! 😱 In this talk, Anthony will take an in depth look at Federated Identity using OpenID Connect and OAuth2 Framework for ASP. NET Core using Duende IdentityServer (aka IdentityServer 5). You will walk away knowing how to navigate the security options and avoid the madness. 

نگاهی به Duende IdentityServer 5
اشتراک‌ها
ReadyRoll محصول جدید شرکت Red-Gate

Develop and deploy databases in Visual Studio with migration scripts.

Want to work on databases in Visual Studio alongside your application? Feeling the pain of managing and deploying database changes manually? Then ReadyRoll's the tool for you.

It generates numerically ordered SQL migration scripts that sit inside your project and take your schema from one version to the next.

You can add them to version control, use them to build and release, and automate database and application deployments, all in one process.

ReadyRoll محصول جدید شرکت Red-Gate