With the release of Visual Studio 2015 came the (final) release of the Roslyn C# compiler and C# 6. This latest version of C#’s feature list seems to be…less than exciting, but it’s important to keep in mind that before Roslyn, none of these new features would have ever made it into a release. It was simply too hard to add a feature in C#, so higher impact/value features made it in while minor annoyances/enhancements would be deferred, indefinitely
.NET applications however rely on the ciphers provided by the OS, and the only way to get new ciphers into the OS is through a patch from Microsoft. Unsupported versions of Windows typically do not receive these patches, so over time you can expect an increasing number of websites to stop working with .NET applications.
افزودن متغیرهای محیطی
در برنامهی نمایش لیست فیلمهایی که تا قسمت 29 آنرا بررسی کردیم، از فایل src\config.json برای ذخیره سازی اطلاعات تنظیمات برنامه استفاده شد. هرچند این روش کار میکند اما بر اساس محیطهای مختلف توسعه، متغیر نیست. اغلب برنامهها باید بتوانند حداقل در سه محیط توسعه، آزمایش و تولید، بر اساس متغیرها و تنظیمات خاص هر کدام، کار کنند. برای مثال بر روی سیستمی که کار توسعه در آن انجام میشود، میخواهیم apiUrl متفاوتی را نسبت به حالتیکه برنامه توزیع میشود، داشته باشیم.
برای رفع این مشکل، برنامههایی که توسط create-react-app تولید میشوند، دارای پشتیبانی توکاری از متغیرهای محیطی هستند. برای این منظور نیاز است در ریشهی پروژه (جائیکه فایل package.json قرار دارد) فایل جدید env. را ایجاد کرد. در ویندوز برای ایجاد یک چنین فایلهایی که فقط از یک پسوند تشکیل میشوند، باید نام فایل را به صورت .env. وارد کرد؛ سپس خود ویندوز نقطهی نهایی را حذف میکند. البته اگر از ادیتور VSCode برای ایجاد این فایل استفاده میکنید، نیازی به درج نقطهی انتهایی نیست. در این فایل environment ایجاد شده میتوان تمام متغیرهای محیطی مورد نیاز را با مقادیر پیشفرض آنها درج کرد. همچنین میتوان این مقادیر پیشفرض را بر اساس محیطهای مختلف کاری، بازنویسی کرد. برای مثال میتوان فایل env.development. را اضافه کرد؛ به همراه فایلهای env.test. و env.production.
متغیرهای محیطی به صورت key=value درج میشوند. این کلیدها نیر باید با REACT_APP_ شروع شوند؛ در غیر اینصورت، کار نخواهند کرد. برای مثال در فایل env.، دو متغیر پیشفرض زیر را تعریف میکنیم:
REACT_APP_NAME=My App REACT_APP_VERSION=1
console.log(process.env);
در این خروجی، متغیر "NODE_ENV: "development به صورت خودکار با تولید بستههای مخصوص ارائهی نهایی، به production تنظیم میشود. سایر متغیرهای محیطی تعریف شده را نیز در اینجا ملاحظه میکنید. با توجه به خواص شیء env، برای مثال جهت دسترسی به نام برنامه میتوان از مقدار process.env.REACT_APP_NAME استفاده کرد.
یک نکته: با هر تغییری در مقادیر متغیرهای محیطی، نیاز است یکبار دیگر برنامه را از ابتدا توسط دستور npm start، راه اندازی مجدد کرد؛ چون این فایلها به صورت خودکار ردیابی نمیشوند.
نحوهی پردازش متغیرهای محیطی درج شدهی در برنامه
اگر همان سطر لاگ کردن خروجی process.env را به صورت زیر تغییر دهیم:
console.log("My App Name", process.env.REACT_APP_NAME);
همانطور که مشاهده میکنید، فراخوانی console.log ما، دیگر به همراه متغیر process.env.REACT_APP_NAME نیست؛ بلکه مقدار اصلی این متغیر در اینجا درج شدهاست. بنابراین اگر در در حین توسعهی برنامه، از متغیرهای محیطی استفاده شود، این متغیرها با مقادیر اصلی آنها در حین پروسهی Build نهایی، جایگزین میشوند.
Build برنامههای React برای محیط تولید
اجرای دستور npm start، سبب ایجاد یک Build مخصوص محیط توسعه میشود که بهینه سازی نشدهاست و به همراه اطلاعات اضافی قابل توجهی جهت دیباگ سادهتر برنامهاست. برای رسیدن به یک خروجی بهینه سازی شدهی مخصوص محیط تولید و ارائهی نهایی باید دستور npm run build را در خط فرمان اجرا کرد. خروجی نهایی این دستور، در پوشهی جدید build واقع در ریشهی پروژه، قرار میگیرد. اکنون میتوان کل محتویات این پوشه را جهت ارائهی نهایی در وب سرور خود، مورد استفاده قرار داد.
پس از پایان اجرای دستور npm run build، پیام «امکان ارائهی آن توسط static server زیر نیز وجود دارد» ظاهر میشود:
> npm install -g serve > serve -s build
البته با توجه به اینکه backend سرور برنامههای ما نیز در همین آدرس قرار دارد و در صورت ورود این آدرس، به صورت خودکار به https://localhost:5001/index.html هدایت خواهید شد، میتوان این پورت پیشفرض را با اجرای دستور serve -s build -l 1234 تغییر داد. اکنون میتوان آدرس جدید http://localhost:1234 را در مرورگر آزمایش کرد که ... با خطای زیر کار نمیکند:
Access to XMLHttpRequest at 'https://localhost:5001/api/genres' from origin 'http://localhost:1234' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
WithOrigins("http://localhost:3000", "http://localhost:1234")
یک نکته: زمانیکه از دستور npm start استفاده میشود، متغیرهای محیطی از فایل env.development. خوانده خواهند شد و زمانیکه از دستور npm run build استفاده میشود، این متغیرها از فایل env.production. تامین میشوند. در این حالتها اگر متغیری در این دو فایل درج نشده بود، از مقدار پیشفرض موجود در فایل env. استفاده میگردد. از فایل env.test. با اجرای دستور npm test، به صورت خودکار استفاده میشود.
آماده سازی برنامهی React، برای توزیع نهایی
تا اینجا برنامهی React تهیه شده، اطلاعات apiUrl خودش را از فایل config.json دریافت میکند. اکنون میخواهیم بر اساس حالات مختلف توسعه و تولید، از apiUrlهای متفاوتی استفاده شود. به همین جهت به فایل env.production. مراجعه کرده و تنظیمات ذیل را به آن اضافه میکنیم:
REACT_APP_API_URL=https://localhost:5001/api REACT_APP_ADMIN_ROLE_NAME=Admin
اکنون به برنامه مراجعه کرده و در هرجائی که ارجاعی به فایل config.json وجود دارد، سطر import آنرا حذف میکنیم. با این تغییر، تمام آدرسهایی مانند:
const apiEndpoint = apiUrl + "/users";
const apiEndpoint = "/users";
axios.defaults.baseURL = process.env.REACT_APP_API_URL;
همچنین adminRoleName مورد نیاز در فایل src\services\authService.js را نیز از همان فایل env جاری تامین میکنیم:
const adminRoleName = process.env.REACT_APP_ADMIN_ROLE_NAME;
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: sample-34-frontend.zip و sample-34-backend.zip
انتشار PostSharp 6.0 RC
PostSharp 6.0 is the biggest refactoring since the 2.0 version released in July 2010. For a good cause: PostSharp 6.0 now runs natively in .NET Core 2.0. Previous versions of PostSharp executed only under .NET Framework at build time and the support for .NET Core was achieved by using a load of hacks that ended up being unmaintainable, warranting this big refactoring.
Let’s have a look at the new features of PostSharp 6.0 :
- Support for .NET Core 2.0-2.1 and .NET Standard 2.0.
- Support for Portable PDB.
- Support for C# 7.2.
- Ending the PostSharp versioning hell side-by-side: backward compatibility within the same major version.
- Logging: robustness to faults in the logging subsystem.
- Logging: no need to initialize before the first logged method is hit.
- Caching: preventing concurrent execution (locking).
- Visual Studio tooling: support for the new CPS-based project systems.
- GDPR compliance: we no longer collect your name and email for trial, nor use unsecure HTTP, nor use non-resettable user id hashes.
Unit Testing در AngularJS
JavaScript is a dynamically typed language which comes with great power of expression, but it also comes with almost no help from the compiler. For this reason we feel very strongly that any code written in JavaScript needs to come with a strong set of tests. We have built many features into Angular which make testing your Angular applications easy. With Angular, there is no excuse for not testing.
این پروژه در 12 بخش گوناگون تقسیم بندی شدهاست که هر کدام در قالب یک فایل HTML میباشد و تمامی اسکریپتهای مورد نیاز به آن افزوده شدهاست. هر بخش به صورت مجزا به شرح یک ویژگی کاربردی در angular-translate میپردازد.
ex1_basic_usage
<script src="Scripts/angular.js"></script> <script src="Scripts/angular-translate.js"></script>
angular.module('app', ['pascalprecht.translate']) .config([ '$translateProvider', function ($translateProvider) { // Adding a translation table for the English language $translateProvider.translations('en_US', { "TITLE": "How to use", "HEADER": "You can translate texts by using a filter.", "SUBHEADER": "And if you don't like filters, you can use a directive.", "HTML_KEYS": "If you don't like an empty elements, you can write a key for the translation as an inner HTML of the directive.", "DATA_TO_FILTER": "Your translations might also contain any static ({{staticValue}}) or random ({{randomValue}}) values, which are taken directly from the model.", "DATA_TO_DIRECTIVE": "And it's no matter if you use filter or directive: static is still {{staticValue}} and random is still {{randomValue}}.", "RAW_TO_FILTER": "In case you want to pass a {{type}} data to the filter, you have only to pass it as a filter parameter.", "RAW_TO_DIRECTIVE": "This trick also works for {{type}} with a small mods.", "SERVICE": "Of course, you can translate your strings directly in the js code by using a $translate service.", "SERVICE_PARAMS": "And you are still able to pass params to the texts. Static = {{staticValue}}, random = {{randomValue}}." }); // Adding a translation table for the Russian language $translateProvider.translations('ru_RU', { "TITLE": "Как пользоваться", "HEADER": "Вы можете переводить тексты при помощи фильтра.", "SUBHEADER": "А если Вам не нравятся фильтры, Вы можете воспользоваться директивой.", "HTML_KEYS": "Если вам не нравятся пустые элементы, Вы можете записать ключ для перевода в как внутренний HTML директивы.", "DATA_TO_FILTER": "Ваши переводы также могут содержать любые статичные ({{staticValue}}) или случайные ({{randomValue}}) значения, которые берутся прямо из модели.", "DATA_TO_DIRECTIVE": "И совершенно не важно используете ли Вы фильтр или директиву: статическое значение по прежнему {{staticValue}} и случайное - {{randomValue}}.", "RAW_TO_FILTER": "Если вы хотите передать \"сырые\" ({{type}}) данные фильтру, Вам всего лишь нужно передать их фильтру в качестве параметров.", "RAW_TO_DIRECTIVE": "Это также работает и для директив ({{type}}) с небольшими модификациями.", "SERVICE": "Конечно, Вы можете переводить ваши строки прямо в js коде при помощи сервиса $translate.", "SERVICE_PARAMS": "И вы все еще можете передавать параметры в тексты. Статическое значение = {{staticValue}}, случайное = {{randomValue}}." }); // Tell the module what language to use by default $translateProvider.preferredLanguage('en_US'); }])
.controller('ctrl', ['$scope', '$translate', function ($scope, $translate) { $scope.tlData = { staticValue: 42, randomValue: Math.floor(Math.random() * 1000) }; $scope.jsTrSimple = $translate.instant('SERVICE'); $scope.jsTrParams = $translate.instant('SERVICE_PARAMS', $scope.tlData); $scope.setLang = function (langKey) { // You can change the language during runtime $translate.use(langKey); // A data generated by the script have to be regenerated $scope.jsTrSimple = $translate.instant('SERVICE'); $scope.jsTrParams = $translate.instant('SERVICE_PARAMS', $scope.tlData); }; }]);
<p> <a href="#" ng-click="setLang('en_US')">English</a> | <a href="#" ng-click="setLang('ru_RU')">Русский</a> </p> <!-- Translation by a filter --> <h1>{{'HEADER' | translate}}</h1> <!-- Translation by a directive --> <h2 translate="SUBHEADER">Subheader</h2> <!-- Using inner HTML as a key for translation --> <p translate>HTML_KEYS</p> <hr> <!-- Passing a data object to the translation by the filter --> <p>{{'DATA_TO_FILTER' | translate: tlData}}</p> <!-- Passing a data object to the translation by the directive --> <p translate="DATA_TO_DIRECTIVE" translate-values="{{tlData}}"></p> <hr> <!-- Passing a raw data to the filter --> <p>{{'RAW_TO_FILTER' | translate:'{ type: "raw" }' }}</p> <!-- Passing a raw data to the filter --> <p translate="RAW_TO_DIRECTIVE" translate-values="{ type: 'directives' }"></p> <hr> <!-- Using a $translate service --> <p>{{jsTrSimple}}</p> <!-- Passing a data to the $translate service --> <p>{{jsTrParams}}</p>
ex2_remember_language_cookies
<script src="Scripts/angular-cookies.js"></script> <script src="Scripts/angular-translate-storage-cookie.js"></script>
// Tell the module to store the language in the cookie $translateProvider.useCookieStorage();
ex3_remember_language_local_storage
این مثال همانند مثال قبل رفتار میکند، با این تفاوت که به جای اینکه کلید زبان کنونی را درون کوکی ذخیره کند، آن را درون Local Storage با نام NG_TRANSLATE_LANG_KEY قرار میدهد. برای اجرا کافیست اسکریپتها و تکه کد زیر را با موارد مثال قبل جایگزین کنید.
<script src="Scripts/angular-translate-storage-local.js"></script> // Tell the module to store the language in the local storage $translateProvider.useLocalStorage();
مثال های ex4_set_a_storage_key و ex5_set_a_storage_prefix نام کلیدی که برای ذخیره سازی زبان کنونی در کوکی یا Local Storage قرار میگیرد را تغییر میدهد که به دلیل سادگی از شرح آن میگذریم.
ex6_namespace_support
translate table در angular-translate قابلیت مفید namespacing را نیز داراست. این قابلیت به ما کمک میکند که جهت کپسوله کردن بخشهای مختلف، ترجمه آنها را با namespaceهای خاص خود نمایش دهیم. به مثال زیر توجه کنید:
$translateProvider.translations('en_US', { "TITLE": "How to use namespaces", "ns1": { "HEADER": "A translations table supports namespaces.", "SUBHEADER": "So you can to structurize your translation table well." }, "ns2": { "HEADER": "Do you want to have a structured translations table?", "SUBHEADER": "You can to use namespaces now." } });
همانطور که توجه میکنید بخش ns1 خود شامل زیر مجموعههایی است و ns2 نیز به همین صورت. هر کدام دارای کلید HEADER و SUBHEADER میباشند. فرض کنید هر کدام از این بخشها میخواهند اطلاعات درون یک section را نمایش دهند. حال به نحوهی فراخوانی این translate tableها دقت کنید:
<!-- section 1: Translate Table Called by ns1 namespace --> <h1 translate>ns1.HEADER</h1> <h2 translate>ns1.SUBHEADER</h2> <!-- section 2: Translate Table Called by ns2 namespace --> <h1 translate>ns2.HEADER</h1> <h2 translate>ns2.SUBHEADER</h2>
به همین سادگی میتوان تمامی بخشها را با namespaceهای مختلف در translate table قرار داد.
در بخش بعدی (پایانی) شش قابلیت دیگر angular translate که شامل فراخوانی translate table از یک فایل JSON، فراخوانی فایلهای translate table به صورت lazy load و تغییر زبان بخشی از صفحه به صورت پویا هستند، بررسی خواهند شد.
فایل پروژه: AngularJs-Translate-BestPractices.zip
نگارش نهایی SQL Server 2017 منتشر شد
Download SQL Server 2017 for Windows
Microsoft® SQL Server® 2017 Feature Pack
Microsoft SQL Server 2017 Developer Edition: https://download.microsoft.com/download/E/F/2/EF23C21D-7860-4F05-88CE-39AA114B014B/SQLServer2017-x64-ENU-Dev.iso Microsoft SQL Server 2017 Evaluation: https://download.microsoft.com/download/E/F/2/EF23C21D-7860-4F05-88CE-39AA114B014B/SQLServer2017-x64-ENU.iso Microsoft SQL Server 2017 Express: https://download.microsoft.com/download/E/F/2/EF23C21D-7860-4F05-88CE-39AA114B014B/SQLEXPRADV_x64_ENU.exe https://download.microsoft.com/download/E/F/2/EF23C21D-7860-4F05-88CE-39AA114B014B/SQLEXPR_x64_ENU.exe https://download.microsoft.com/download/E/F/2/EF23C21D-7860-4F05-88CE-39AA114B014B/SqlLocalDB.msi https://download.microsoft.com/download/E/F/2/EF23C21D-7860-4F05-88CE-39AA114B014B/SQLRules_x64_ENU.exe