اشتراک‌ها
بررسی تغییرات ASP.NET Core در NET 8 Preview 7.

Here’s a summary of what’s new in this preview release:

Servers & middleware
  Antiforgery middleware
API authoring
  Antiforgery integration for minimal APIs
Native AOT
  Request Delegate Generator supports interceptors feature
  Full TrimMode is used for web projects compiled with trimming enabled
  WebApplication.CreateEmptyBuilder
Blazor
  Antiforgery integration
  Server-side form handling improvements
  Auto render mode
  Register root-level cascading values
  Improved integration of interactive components with server-side rendering
  New EmptyContent parameter for Virtualize
Identity
  New bearer token authentication handler
  New API endpoints
Single page apps (SPA)
  New Visual Studio templates
 

بررسی تغییرات ASP.NET Core در NET 8 Preview 7.
اشتراک‌ها
11.Visual Studio 2017 15.9 منتشر شد
11.Visual Studio 2017 15.9 منتشر شد
نظرات مطالب
فعال سازی عملیات CRUD در Kendo UI Grid
- «Handling Server-Side Validation Errors In Your Kendo UI Grid»
خلاصه‌اش به این صورت است:
- ابتدا رخداد error مربوط به data source را باید مدیریت کرد:
 var dataSource = new kendo.data.DataSource({
            // ... 
            error: function (e) {
                window.SalesHub.OrderDetails_Error(e);
            },
            // ... 
        });
با این متد
window.SalesHub.OrderDetails_Error = function(args) {
    if (args.errors) {
        var grid = $("#orderDetailsGrid").data("kendoGrid");
        var validationTemplate = kendo.template($("#orderDetailsValidationMessageTemplate").html());
        grid.one("dataBinding", function(e) {
            e.preventDefault();

            $.each(args.errors, function(propertyName) {
                var renderedTemplate = validationTemplate({ field: propertyName, messages: this.errors });
                grid.editable.element.find(".errors").append(renderedTemplate);
            });
        });
    }
};
که از این قالب برای نمایش خطاها استفاده می‌کند:
<script type="text/x-kendo-template" id="orderDetailsValidationMessageTemplate">
    # if (messages.length) { #
        <li>#=field#
            <ul>
                # for (var i = 0; i < messages.length; ++i) { #
                    <li>#= messages[i] #</li>
                # } #
            </ul>
        </li>
    # } #
</script>
نظرات مطالب
آشنایی با NHibernate - قسمت هشتم
سلام،
کاری را که شما دارید انجام می‌دید اشتباه است.
Using statement در سی شارپ به صورت خودکار به try/finally به همراه dispose شیء احاطه شده توسط آن ترجمه می‌شود. (+)
به عبارتی شما یک try/finally را در یک سطح بالاتر دارید و داخل آن یک try/catch قرار داده‌اید. اینکار صحیح نیست. Using را حذف کنید و try/catch/finally را جایگزین تمام موارد اضافه شده کنید.
ضمنا توصیه من این است که فقط try/catch را حذف کنید. Using سرجایش باشد تا هدف اصلی آن یعنی dispose اشیاء مرتبط حتما رخ دهد.
به تمام برنامه نویس‌ها آموزش داده می‌شود که exception handling چیست اما در پایان فصل به آن‌ها آموخته نمی‌شود که لطفا تا حد امکان از آن استفاده نکنید! بله، لطفا در استفاده از آن خساست به خرج دهید. چرا؟ چون کرش بر خلاف تصور عمومی چیز خوبی است! زمانیکه شما این try/catch را قرار دادید، flow برنامه متوجه نخواهد شد که در مرحله‌ی قبل مشکلی رخ داده و از ادامه برنامه و خسارت وارد کردن به سیستم جلوگیری کند. ضمنا این را هم به خاطر داشته باشید که exception ها در دات نت حبابی هستند. یعنی به فراخوان خود منتشر خواهند شد و در یک سطح بالاتر هم قابل catch هستند (با تمام جزئیات).
بازخوردهای دوره
جلوگیری از deadlock در برنامه‌های async
نکته جالبی بود، توی یه برنامه ای از چندین تسک استفاده کرده بودم و مشکل اصلی اینجا بوده که الان متوجه شدم. فقط برام عجیبه بعضی از best practice‌ها رو مایکروسافت به صورت پیش فرض لحاظ نمیکنه نمونه اش همین ConfigureAwait(false) !
حالتی وجود داره که ادامه فعالیت متد async بایستی حتما در context فراخوانش ادامه پیدا کنه یعنی حالتی که ConfigureAwait بایستی حتما true باشه؟
اشتراک‌ها
مهاجرت به AngularJS 2.0

"Our goal with Angular 2 is to make the best possible set of tools for building web apps not constrained by maintaining backwards compatibility with existing APIs." —Angular blog 

مهاجرت به AngularJS 2.0
نظرات مطالب
Best Practice هایی برای ASP.NET MVC - قسمت اول
نکات جالبی بود .
یک نکته که به شخصه اون رو تجربه کرده ام (بخصوص در مورد استفاده از best practice‌ها ) وضعیتی است که اصطلاحاً بهش overkilling  میگن ( اگر اشتباه نکنم ) ، یعنی بعضی وقتا دیگه زیاده روی میشه . مثلا در به کاربردن اینترفیس‌ها و یا loose coupling .
برای مثال در مورد تشخیص زمان استفاده از اینترفیس در این کتاب ، یکی از بهترین راهکارها استفاده از آزمون واحد معرفی شده .
بسیار عالی میشه در صورت امکان در این مورد هم نکاتی را ذکر کنید .

نظرات مطالب
عبارت using و نحوه استفاده صحیح از آن
البته از حق هم نمی‌شه گذشت که طراح‌های iText Sharp در این جا هم از Best Practice‌ها پیروی نکردند
این قاعده کلی کار هستش که در Dispose و متد Finalize خطایی ایجاد نشه
حتی چند بار فراخوانی Dispose هم نباید ایجاد خطا کنه، حتی خطای Object Disposed Exception
متاسفانه تفاوت‌های Java و NET. تونسته رو این تیم که iText Sharp رو از Java به NET. برده، رو به یک سری اشتباهات بندازه، مثل این مورد، و عدم استفاده از Enum و چند تا مورد دیگه
اگه فرض کنیم ما Dispose رو فراخونی نکنیم و این فراخونی توسط CLR و در فاینالایزر کلاس رخ بده، این خطایی موجود در Dispose می‌تونه مسائل بدتری رو هم در پی داشته باشه
به دوستان توصیه می‌کنم حتما با Best Practice‌های مدیریت خطا مخصوص NET. آشنا بشن، که در اینترنت منابع زیادی برای این مهم موجوده
نظرات مطالب
Blazor 5x - قسمت 31 - احراز هویت و اعتبارسنجی کاربران Blazor WASM - بخش 1 - انجام تنظیمات اولیه
بله. اگر کاربری برای مثال دو نقش داشته باشد، این دو نقش به صورت یک آرایه در JWT ظاهر می‌شوند:
{
  "iss": "https://localhost:5001/",
  "iat": 1617386360,
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "vahid@dntips.ir",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "vahid@dntips.ir",
  "Id": "14fc329a-6198-4b0d-958d-daa9f07707ec",
  "DisplayName": "vahid@dntips.ir",
  "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": [
    "Admin",
    "Employee"
  ],
  "nbf": 1617386360,
  "exp": 1617387560,
  "aud": "Any"
}
که این آرایه را به صورت زیر هم می‌توان پردازش کرد:
    public static class JwtParser
    {
        public static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
        {
            var claims = new List<Claim>();
            var payload = jwt.Split('.')[1];

            var jsonBytes = ParseBase64WithoutPadding(payload);

            var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
            foreach(var item in keyValuePairs)
            {
                if (item.Value is JsonElement element && element.ValueKind == JsonValueKind.Array)
                {
                   foreach(var itemValue in element.EnumerateArray())
                   {
                      claims.Add(new Claim(item.Key, itemValue.ToString()));
                   } 
                }
                else
                {
                   claims.Add(new Claim(item.Key, item.Value.ToString()));
                }
            }
            return claims;
        }