اشتراک‌ها
نمونه معماری پیاده سازی شده با ASP.NET Core و Angular و DDD

Architecture with .NET Core 3.1, ASP.NET Core 3.1, Entity Framework Core 3.1, C#, Angular 9.1, Clean Code, SOLID, DDD, Code Analysis, Docker and more. 

Technologies 

  • .NET Core 3.1
  • ASP.NET Core 3.1
  • Entity Framework Core 3.1
  • C# 8.0
  • Angular 9.1
  • Typescript
  • JWT
  • FluentValidation
  • Scrutor
  • Serilog
  • Docker
  • Azure DevOps
  • ...

Practices 

  • Clean Code
  • SOLID Principles
  • DDD (Domain-Driven Design)
  • Unit of Work Pattern
  • Repository Pattern 
  • ...
نمونه معماری پیاده سازی شده با ASP.NET Core و Angular و DDD
اشتراک‌ها
زمانه angular 2

I’ve been avoiding even thinking about the latest rev of Angular as every time I did look at it, I came away with a headache. It was weird and the docs were even weirder. I saw plenty of blog posts on the topic, but in general they dealt with one small slice of Angular 2 and were too confusing for me to grok. 

زمانه angular 2
نظرات مطالب
چگونه پروژه‌های Angular ی سبکی داشته باشیم - قسمت اول
مشکلی اصلی که در اینجا وجود دارد این است که چرا کامپایلر فعلی Angular (یعنی تا نگارش 7 آن)، قادر نیست وابستگی‌هایی را که در برنامه ارجاعی به آن‌ها وجود ندارند، در بسته یا بسته‌های کامپایل شده‌ی نهایی لحاظ نکند؟ این مشکل قرار است در نگارش 8 آن با ارائه‌ی یک کامپایلر جدید به نام Ivy که مدت زیادی است مشغول به کار بر روی آن هستند، برطرف شود:
The cool thing about Ivy versus the older compilers, however, is that it’s “ tree-shaking friendly ,” which basically means that it automatically removes unused bits of code (including unused Angular features!), shrinking your bundles.  
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت هشتم - دریافت اطلاعات از سرور
با سلام. در یک پروژه Angular 5 داده‌های ComboBox‌ها باید در سمت کلاینت کش شوند. بنده در ngOnInit مربوط به app.component عملیات دریافت این داده‌ها را با http.get انجام میدهم و داده‌ها در یک پروپرتی Observable کش می‌شوند. حالا در فرم هایی که به این داده‌ها نیاز دارم در متد ngOnInit اقدام به دریافت داده‌ها از کش میکنم اما هنوز داده‌ها دریافت نشده اند (مشکل همزمانی).
همچنین بنده lifecycle Angular رو بررسی کردم. از ngAfterContentInit هم برای دریافت داده‌ها در فرم‌ها استفاده کردم اما باز هم موقع اجرای این متد(ngAfterContentInit   ) هنور متد subscribe مربوط به http.get اجرا نشده است.
 لطفا در صورت امکان راهنمایی کنید. با تشکر
نظرات مطالب
احراز هویت و اعتبارسنجی کاربران در برنامه‌های Angular - قسمت دوم - سرویس اعتبارسنجی
هنگام login کردن به پیغام زیر در console بر می‌خورم. مشکل از سمت سرور هست یا کد‌های Angular؟ البته سمت سرور در پروژه‌های دیگر Angular جواب می‌گیرم.
POST http://localhost:5000/api/account/login 500 (Internal Server Error)
Failed to load http://localhost:5000/api/account/login: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 500.
اشتراک‌ها
مقایسه‌ای کوتاه بین ABP Framework و DNTFrameworkCore

In this post, I want to compare “DNTFrameworkCore” with “ABP Framework”.


ABP is one of most popular and well documented frameworks with high level abstraction that I learned a lot from it. It has many other features that I don’t list them in this post, because, DNTFrameworkCore has not them actually. Behind of ABP, there is a team. It has 123 contributors in GitHub. Also, all of features have related unit-tests.

In other side, DNTFrameworkCore is lightweight with low level abstraction. It is personal open-source project without any contributor and has unit-tests for small part. 

I wrote this post to prove that thinking behind of DNTFrameworkCore completely different from ABP (at least in most sections)  

مقایسه‌ای کوتاه بین ABP Framework و DNTFrameworkCore
مطالب
جایگزین کردن jQuery با JavaScript خالص - قسمت دوم - کار با Attributes
عناصر HTML از سه قسمت نام، محتوا و ویژگی‌ها یا attributes تشکیل می‌شوند که دو مورد آخر، اختیاری هستند.
<form action="/rest/login" method="POST">
    <input name="username" required>
    <input type="password" name="password" required>
</form>
در این مثال سه المان form و دو input را مشاهده می‌کنید. تگ المان <form> دارای نام form و تگ المان <input> دارای نام input است.
محتوا یا content به معنای المان‌هایی هستند که درون یک المان قرار می‌گیرند. برای مثال در اینجا المان <form> دارای محتوایی متشکل از دو المان <input> است و دون المان <input> دارای محتوایی نیستند.
از ویژگی‌ها و یا attributes، برای ارائه‌ی اطلاعات بیشتر و یا تعیین حالت عناصر استفاده می‌شود. برای نمونه در اینجا المان <form> دارای دو ویژگی action و method است که برای ارائه‌ی اطلاعاتی بیشتر جهت تعیین روش و محل ارسال اطلاعات به سرور از آن‌ها استفاده می‌شود. همچنین می‌توان ویژگی‌های سفارشی را نیز توسط ویژگی‌های شروع شده‌ی با -data نیز به المان‌ها اضافه کرد که جزئی از استاندارد HTML 5 است. هرچند می‌توان ویژگی کاملا غیرمتعارفی مانند myproject-uuid را نیز به یک المان اضافه کرد. این مورد مشکل خاصی را ایجاد نکرده و صفحه بدون مشکل رندر می‌شود؛ اما یک چنین صفحه‌ای دیگر به عنوان یک صفحه‌ی استاندارد HTML ارزیابی نخواهد شد؛ از این جهت که از ویژگی استفاده کرده‌است که در هیچکدام از استانداردهای HTML ذکر نشده‌است.
آخرین نگارش HTML5 به همراه 4 ویژگی جدید دیگر نیز هست:
- Boolean attribute : مانند ویژگی required که به المان‌های <input> قابل انتساب است. حضور این نوع ویژگی‌ها بدون مقداری در یک المان
 <input name=username required>
به معنای true بودن مقدار آن‌ها است و اگر به طور کامل ذکر نشوند، مقدار false را خواهند داشت.
نمونه‌ی دیگری از این نوع ویژگی‌ها، ویژگی hidden است که به HTML 5.1 اضافه شده‌است و اگر به عنصری اضافه شود، آن المان رندر نخواهد شد.
- unquoted attribute: به این معنا که می‌توان "" را از اطراف مقدار یک ویژگی حذف کرد:
 <input name=username required>
البته با این شرط که این مقدار دارای فاصله، علامت مساوی، مقداری خالی و یا >< نباشد.
- single-quoted and double-quoted attributes: که به معنای استفاده از "" و یا '' جهت تعیین مقدار یک ویژگی است.


تفاوت attributes با خواص المان‌ها چیست؟

Attributes در تعریف تگ HTML یک عنصر ظاهر می‌شوند اما خواص، جزئی از تعریف شیء یک عنصر هستند.
<div class="bold">I'm a bold element</div>
در این مثال المان <div> دارای ویژگی class است. هرچند ویژگی‌ها و خواص دارای مفاهیم یکسانی نیستند، اما در تعریف اشیاء HTML به ازای تمام ویژگی‌های استاندارد، یک خاصیت با نام معادل نیز در نظر گرفته‌است و تغییر مقدار آن‌ها از طریق کد، سبب به روز رسانی مقدار ویژگی‌های متناظر نیز می‌شود.
 <a href="http://www.site.com/blog/">Read the blog</a>
برای مثال اگر بخواهیم مقدار ویژگی href المان فوق را تغییر دهیم، می‌توانیم ابتدا این شیء را یافته و سپس خاصیت href آن‌را به روز رسانی کنیم تا بر روی ویژگی متناظر با آن تاثیرگذار شود:
<script>
   document.querySelector('A').href = 'https://www.dntips.ir';
</script>
هرچند در اکثر موارد تناظری بین نام خواص و ویژگی‌های المان‌ها برقرار است، اما یکسری استثناءهایی هم وجود دارند:
- برای مثال واژه‌ی class در زبان جاوا اسکریپت یک واژه‌ی کلیدی است. به همین جهت در اینجا اگر بخواهیم مقدار ویژگی class را تغییر دهیم باید از خاصیت className آن المان استفاده کنیم.
- مورد دوم ویژگی checked المان‌های radio و checkbox است. این ویژگی فقط در ابتدای کار این المان‌ها به آن‌ها متصل می‌شود:
  <input type="checkbox" checked>

  <script>
      // this does not remove the checked attribute 
      document.querySelector('INPUT').checked = false;
  </script>
با اجرای قطعه کد فوق، هرچند مقدار خاصیت checked این المان false می‌شود، اما سبب حذف خود ویژگی از المان نخواهد شد.
- تمام ویژگی‌های غیراستانداردی که تعریف شوند، دارای خاصیت متناظری در آن المان نخواهند بود، اما به آن‌ها expando properties گفته می‌شود.


یافتن المان‌ها بر اساس ویژگی‌های آن‌ها

از آنجائیکه attribute selectors در استاندارد W3C CSS 2 معرفی شده‌اند، امکان کار با آن‌ها از زمان IE 8.0 میسر بوده‌است و برای کار با آ‌ن‌ها الزاما نیازی به استفاده از jQuery نیست!


یافتن المان‌ها بر اساس نام ویژگی‌ها

  <form action="/submitHandler" method="POST">
      <input name="first-name">
      <input name="last-name" required>
      <input type="email" name="email" required>
      <button disabled>submit</button>
  </form>
در اینجا برای یافتن المان‌هایی که دارای ویژگی‌هایی با نام‌های required و disabled هستند، در جی‌کوئری از CSS 2+ attribute selector string آن‌ها استفاده می‌شود:
 var $result = $('[required], [disabled]');
و در جاوا اسکریپت خالص نیز دقیقا به همان شکل و با استفاده از همان استاندارد است:
 var result = document.querySelectorAll('[required], [disabled]');
که خروجی آن آرایه‌ای از المان‌های last-name، email و دکمه است.

در اینجا باید دقت داشت که این جستجو صرفا بر اساس نام ویژگی‌ها انجام می‌شود؛ حتی اگر این ویژگی دارای مقداری نباشد:
  <div class="bold">I'm bold</div>
  <span class>I'm not</span>
در اینجا ویژگی class دوم دارای مقداری نیست و اگر کوئری ذیل را اجرا کنیم، هر دو المان span و div را دریافت خواهیم کرد:
  var result = document.querySelectorAll('[class]');


یافتن المان‌ها بر اساس نام و مقدار ویژگی‌ها

  <section>
     <h2>Sites</h2>
     <ul>
          <li>
              <a href="https://www.dntips.ir/">dotnettips</a>
          </li>
          <li>
              <a href="https://google.com/">Google</a>
          </li>
      </ul>
  </section>
اگر یافتن المان‌ها صرفا بر اساس نام ویژگی‌های آن‌ها کافی نیست، استفاده از همان روش استاندارد CSS selector string برای یافتن عنصری بر اساس نام و مقدار یک ویژگی نیز میسر است. برای مثال در این حالت در جی‌کوئری خواهیم داشت:
 var $result = $('A[href="https://www.dntips.ir/"]');
معادل این کد در جاوا اسکریپت خالص نیز به همین شکل است؛ اما بدون نیاز به وابستگی خاصی و سریعتر:
 var result = document.querySelectorAll('A[href="https://www.dntips.ir/"]');

و یا اگر اینبار بخواهیم تمام ویژگی‌های کلاسی که دارای مقدار هستند را انتخاب کنیم، روش آن با استفاده از exclusion selector به صورت زیر است:
 var result = document.querySelectorAll('[class]:not([class=""]');


یافتن المان‌ها بر اساس نام و قسمتی از مقدار ویژگی‌ها

  <a href="https://www.dntips.ir/">home page</a>
  <a href="https://www.dntips.ir/postsarchive">articles</a>
  <a href="https://www.dntips.ir/newsarchive">news</a>
در مثال قبل، المان‌هایی را که دارای مقدار ویژگی کاملا مشخصی بودند، یافتیم. اما اگر بخواهیم در قطعه HTML فوق لینک‌هایی را که دارای domain مشخصی هستند بیابیم چطور؟ در اینجا باید از substring attribute selector که جزئی از استاندارد W3C CSS 3 است، استفاده کنیم:
 var result = document.querySelectorAll('A[href*="www.dotnettips.info"]');
در اینجا تمام anchor tagهایی که دارای ویژگی href با مقداری حاوی www.dotnettips.info هستند، یافت خواهند شد.


یافتن المان‌ها بر اساس نام و کلمه‌ای مشخص در مقدار ویژگی‌ها

<div class="one two three">1 2 3</div>
<div class="onetwothree">123</div>
در این مثال می‌خواهیم المانی را بیابیم که کلاس two به آن اعمال شده‌است. برای اینکار از attribute word selector استفاده می‌شود:
 var result = document.querySelectorAll('[class∼=two]');
خروجی این کوئری، لیستی است حاوی اولین div تعریف شده.

در اینجا نوع دیگری از کوئری را هم می‌توان مطرح کرد: آیا المانی مشخص، دارای کلاس two است؟
روش انجام آن در jQuery به صورت زیر است:
 var hasTwoClass = $divEl.hasClass('two');
و در جاوا اسکریپت خالص:
 var hasTwoClass = divEl.classList.contains('two');
DOM API به همراه خاصیتی است به نام classList که امکان یافتن عنصری خاص را در آن توسط متد استاندارد contains میسر می‌کند.
همچنین خاصیت classList به همراه متدهای استاندارد add و remove نیز هست که معادل متدهای addClass و removeClass جی‌کوئری هستند.
divEl.classList.remove('red');
divEl.classList.add('blue');
و یا متد toggle خاصیت classList سبب افزوده شدن کلاسی مشخص و یا فراخوانی مجدد آن سبب حذف آن کلاس می‌شود (معادل متد toggleClass جی‌کوئری است):
// removes "hide" class
divEl.classList.toggle('hide');

// re-adds "hide" class
divEl.classList.toggle('hide');


یافتن المان‌ها بر اساس نام و شروع یا خاتمه‌ی عبارتی مشخص در مقدار ویژگی‌ها

  <img id="cat" src="/images/cat.gif">
  <img id="zebra" src="zebra.gif">
  <a href="#zebra">watch the zebra</a>
  <a href="/logout">logout</a>
در اینجا می‌خواهیم تمام المان‌هایی را که از نوع تصاویر gif هستند، به همراه لینک‌هایی که به صفحه‌ی جاری اشاره می‌کنند، بیابیم:
 var result = document.querySelectorAll('A[href^="#"], [src$=".gif"]');
این کوئری نحوه‌ی استفاده‌ی از starts with attribute value selector یا ^ و ends with attribute value selector یا $ را نمایش می‌دهد. این مثال لینک‌هایی را که با # شروع می‌شوند و همچنین المان‌هایی را که دارای src ختم شده‌ی به gif هستند، پیدا می‌کند.


خواندن مقادیر ویژگی‌ها

 <input type="password" name="user-password" required>
روش خواندن مقدار ویژگی type و بررسی وجود ویژگی required در جی‌کوئری:
// returns "password"
$inputEl.attr('type');

// returns "true"
$inputEl.is('[required]');
و معادل همین قطعه کد در جاوا اسکریپت خالص به صورت زیر است:
// returns "password"
inputEl.getAttribute('type');

// returns "true"
inputEl.hasAttribute('required');
متد getAttribute از سال 1997 به همراه استاندارد W3C DOM Level 1 Core و متد hasAttribute از سال 2000 به همراه استاندارد DOM Level 2 Core معرفی شده‌اند.


تغییر مقدار ویژگی‌ها

 <input name="temp" required>
می‌خواهیم این المان را به نحوی تغییر دهیم که نوع آن email شود، بدون ویژگی required و نام آن به userEmail تغییر یابد.
روش انجام اینکار در جی‌کوئری:
 $inputEl
 .attr('type', 'email') // #1
 .removeAttr('required') // #2
 .attr('name', 'userEmail'); // #3
و با جاوا اسکریپت خالص:
 inputEl.setAttribute('type', 'email'); // #1
inputEl.removeAttribute('required'); // #2
inputEl.setAttribute('name', 'userEmail'); // #3
متدهای استاندارد setAttribute و removeAttribute نیز جزئی از استاندارد W3C DOM Level 1 Core سال 1997 هستند؛ اما مانند jQuery قابلیت ذکر زنجیروار را ندارند که ... مهم نیست.
اشتراک‌ها
معرفی Smart Unit Tests

 Smart Unit Tests tries to address these impediments. It discovers all code paths in your code, synthesizes precise test input values that exercise those code paths, and then records what the output from your code was for the said inputs

معرفی Smart Unit Tests