نظرات مطالب
اشتباهات متداول برنامه‌نویس‌های دات نت
سلام

خبرخوان (تکست و گرافیکی)، لیست و فید وبلاگ‌های برنامه‌نویسی ارائه شده است که وبلاگ شما نیز جز آنها قرار گرفته است.

http://persianbloggers.blogspot.com/2009/03/programming-p.html

پرشین بلاگرز شما را به بازدید و استفاده از این خبرخوان و 23 خبرخوان تخصصی دیگر موجود دعوت می‌کند.
بازخوردهای دوره
متدهای async تقلبی
برای استفاده از یک وب سرویس، اگر به شکل زیر در یک ClassLibrary استفاده شود، آیا واقعا غیر همزمان عمل می‌شود یا تقلبی محسوب می‌شود؟
public bool SendSms()
{
    try
    {
        var result = false;
        foreach (var nomber in _fromNombers)
        {
            if (result) continue;
            if (_smsService.SendGroupSmsSimple(Model.Signature, nomber, Model.Numbers, Model.Body, false,
                string.Empty) == 1)
                result = true;
        }
        return result;
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
        return false;
    }
}

private Task SendSmsAsync()
{
    return Task.Run(() => SendSms());
}
و مثلا در یک ConsoleApp:
static void Main(string[] args)
{
    var r = SendAsync();
    r.Wait();
}

private static async Task SendAsync()
{
    var model = new SmsModel
    {
        Body = "سلام",
        Numbers = new[] { "0917*******" }
    };

    var service = new SmsService(model);

    await service.SendSmsAsync();
}

بازخوردهای دوره
استفاده از async و await در برنامه‌های ASP.NET Web forms 4.5
- اعمال async با اعمال پس زمینه یکی نیستند. اعمال async واقعی از ترد استفاده نمی‌کنند؛ به همین جهت سربار کمی دارند و مقیاس پذیری سیستم را افزایش می‌دهند. زمانیکه از یک عملیات async استفاده می‌کنید، ترد جاری خالی می‌شود و به سرعت به thread pool، برای استفاده از آن جهت پردازش سایر درخواست‌های رسیده هدایت خواهد شد اما اعمال غیر async، ترد جاری را تا پایان پردازش معطل می‌کنند. این تفاوت اصلی و مهم کارهای async و غیر async است.
- انتقال پارامترها به متدهای async مطابق روش C# 5، همانند قبل و مانند روش‌های متداول موجود است. هدف اصلی از طراحی async و await، عادی به نظر رسیدن این اعمال است؛ از دید برنامه نویس.
در مثال بالا، متد public async Task LoadSomeData بدون پارامتر است. اگر نیاز به ارسال پارامتر به آن هست، از روش زیر استفاده کنید:
RegisterAsyncTask(new PageAsyncTask(() => SomeMethod(param1: 1000)));
بازخوردهای دوره
مدیریت استثناءها در حین استفاده از واژه‌های کلیدی async و await
- در مورد EF و متدهای Async آن مطلب جداگانه‌ای تهیه شده: «پردازش‌های Async در Entity framework 6»
- در مورد ASP.NET MVC و متدهای Async هم یک مطلب اختصاصی تهیه شده: «استفاده از Async و Await در برنامه‌های ASP.NET MVC »
- مثال دوم شما async نیست چون از متد Wait استفاده کرده‌اید (این متد، یک متد blocking است و ترد جاری را قفل می‌کند). این مثال با نمونه‌ی همزمان تقریبا یکسان عمل می‌کند.
همچنین در این مثال استفاده از Task.Factory.StartNew به معنای async تقلبی است و اصلا توصیه نمی‌شود. برای EF متدهای Async واقعی وجود دارند.
- هدف از بکارگیری متدهای async الزاما سریعتر کردن اجرای عملیات مورد نظر نیست. هدف خالی کردن ترد جاری و امکان استفاده‌ی مجدد از آن برای پاسخ دهی به یک کاربر دیگر است؛ با توجه به اینکه هزینه ایجاد تردهای جدید بالا است و همچنین نهایتا بر اساس مشخصات و منابع سرور، این تعداد محدود است. هدف بالا بردن میزان مقیاس پذیری یک برنامه است با تعداد کاربران بالا.
بازخوردهای دوره
آشنایی با مدل برنامه نویسی TAP
سلام
من متد DownloadStringAsync و رویداد مرتبط با آن یعنی DownloadStringCompleted رو تست کردم و به دلیل اینکه متد DownloadStringAsync  را در UI Thread صدا میزدم رویداد DownloadStringCompleted  نیز همیشه در UI Thread فراخوانی میشد.
من در یک پروژه یک کتابخانه درست کرده بودم که یکی از متدها باید کاری رو به صورت Async انجام میداد و وقتی که کار این متد تمام میشد نتیجه را با Raise کردن یک event به اطلاع استفاده کننده میرسوندم.
اما مشکل اینجا بود که به کنترل‌های روی فرم دسترسی نداشتم و داخل این رویداد ابتدا شرط InvokeRequired و سپس Invoke رو نوشته بودم.این کار مشکل رو حل کرده بود.
اما به نظر من این کار درست نیست.چون من در واقع یکسری API نوشته ام و در اختیار برنامه نویسان دیگر گذاشته ام و آنها باید بتوانند کدهای خود را بدون InvokeRequired درون رویداد بنویسند.
آیا راهی هست که بشه متد من در هر Thread یی اجرا شود رویداد اتمام آن نیز در همان Thread صدازننده ، فراخوانی شود؟
من در این کتابخانه از async و await استفاده نکرده بودم.
ممنون
نظرات مطالب
بررسی بهبودهای ProblemDetails در ASP.NET Core 7x
در ASP.NET Core 8.0 نیز امکان مدیریت استثناءها به صورت سراسری با پیاده‌سازی اینترفیس  IExceptionHandler مسیر شده است:
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;

internal sealed class GlobalExceptionHandler : IExceptionHandler
{
    private readonly ILogger<GlobalExceptionHandler> _logger;

    public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
    {
        _logger = logger;
    }

    public async ValueTask<bool> TryHandleAsync(
        HttpContext context,
        Exception exception,
        CancellationToken cancellationToken = default)
    {
        _logger.LogError(exception, "An unhandled exception has occurred while executing the request.");
        var problemDetails = new ProblemDetails
        {
            Status = StatusCodes.Status500InternalServerError,
            Title = "Server Error",
        };

        context.Response.StatusCode = StatusCodes.Status500InternalServerError;
        await context.Response.WriteAsJsonAsync(problemDetails);

        return true;
    }
}

برای ریجستر کردن آن نیز:
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
// other code
app.UseExceptionHandler();
نظرات مطالب
اعتبارسنجی مبتنی بر کوکی‌ها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
بسیار ممنون. از این روش در پروژه دیگری استفاده کرده بودم و هرکاری می‌کردم بازهم خطای مذبور را دریافت می‌کردم. پس از چند روز مقایسه کدها، کاشف به عمل آمد که مشکل از نوع تزریق سرویس در کامپوننت می‌باشد. در پروژه برای تزریق سرویس از این روش استفاده کرده بودم:
@inherits OwningComponentBase 
...
private IUserInfoService userInfoService { get; set; } 
...
userInfoService = ScopedServices.GetRequiredService<IUserInfoService>();
که با تغییر آن به شکل زیر مشکل در سطح کامپوننت حل شد:
@inject IUserInfoService UserInfoService
اما مشکل هنوز در سطح سرویس وجود دارد. یعنی اگر از سرویس UserInfoService در سرویس دیگر به روش زیر استفاده شود، آنگاه خطا بروز می‌کند.
public class ManualLog: IManualLog
    {
    private readonly IUserInfoService _userInfoService;

    public ManualLog(IUserInfoService userInfoService)
            {
                _userInfoService = userInfoService ?? throw new ArgumentNullException(nameof(userInfoService));
            }

    public async task Log()
            {
                int userId = await _userInfoService.GetUserIdAsync();
             }
    }
پیام خطا مثل قبل:
 GetAuthenticationStateAsync was called before SetAuthenticationState   
نظرات مطالب
Blazor 5x - قسمت 19 - کار با فرم‌ها - بخش 7 - نکات ویژه‌ی کار با EF-Core در برنامه‌های Blazor Server
منظور من استفاده از IunitOfWork بود که در این حالت در تمامی سرویس‌ها در سازنده تزریق میشد و سپس از طریق سازنده dbset‌ها به صورت گلوبال از طریق متد <Set<T مقدادرهی میشدند و در این حالت متد dispose به uow دسترسی ندارد جهت dispose کردن آن و تنها set‌ها هستند.
یک چنین چیزی:
  private readonly DbSet<SmsLog> _smsLogs;
        private readonly DbSet<SmsProvider> _smsProviders;

        public MessageService(IUnitOfWork uow)
        {
            _smsLogs = uow.Set<SmsLog>();
            _smsProviders = uow.Set<SmsProvider>();
        }
        public async Task NewSmsLogAsync(SmsLog log)
        {
            await _smsLogs.AddAsync(log);
        }

 سپس بحث اعمال savechanges باید روی متد نهایی مثل اکشن صورت میگرفت که در صورت استفاده از چندین متد در یک یا چند سرویس همه با هم همزمان برای ذخیره سازی و دریافت نتیجه به سمت دیتابیس ارسال گردند. مثل ارسال اطلاعات جدید هتل و تصاویر آن. نه تک تک جدا ذخیره شوند. همه با هم یا هیچ کدام
نظرات مطالب
Blazor 5x - قسمت یازدهم - مبانی Blazor - بخش 8 - کار با جاوا اسکریپت
امکان رندر کامل یک کامپوننت Blazor توسط کدهای جاوااسکریپتی در Blazor 6x

مرحله‌ی اول آماده سازی یک کامپوننت، جهت دسترسی به آن توسط کدهای جاوااسکریپتی، ثبت آن به نحو زیر در فایل Program.cs است:
builder.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
البته نمونه‌ی blazor server آن به صورت زیر است:
builder.Services.AddServerSideBlazor(options =>
{
    options.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
});
پس از آن، کدهای جاوااسکریپتی فراخوان کامپوننت Counter، به صورت زیر خواهند بود:
<button onclick="callCounter()">Call Counter</button>

<script>
  async function callCounter() {
     let containerElement = document.getElementById('my-counter');
     await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });      
  }
</script>
 
<div id="my-counter">
</div>
که نتیجه‌ی نهایی این فراخوانی، در div ای با id مساوی my-counter، رندر خواهد شد. در اینجا نحوه‌ی ارسال پارامتری را نیز به این کامپوننت، مشاهده می‌کنید.
نظرات مطالب
Blazor 5x - قسمت هفتم - مبانی Blazor - بخش 4 - انتقال اطلاعات از کامپوننت‌های فرزند به کامپوننت والد
با سلام
در بخش << یک تمرین: انتقال رویداد انتخاب شدن یک div به کامپوننت والد >>
درسته که امضای متد از نوع  MouseEventArgs هست اما لازم نیست حتماً امضای متد رو تقلید کنیم و یک نوع  MouseEventArgs به متد ارسال کنیم به جاش میشه از این شکل هم استفاده کرد
<div class="bg-light border p-2 col-5 offset-1 mt-2"
    @onclick="@(() => AmenitySelectionChanged(Amenity.Name))">
    <h4 class="text-secondary">Amenity - @Amenity.Id</h4>
    @Amenity.Name<br />
    @Amenity.Description<br />
</div>

@code
{
    [Parameter]
    public BlazorAmenity Amenity { get; set; }

    [Parameter]
    public EventCallback<string> OnAmenitySelection { get; set; }

    protected async Task AmenitySelectionChanged(string name)
    {
        await OnAmenitySelection.InvokeAsync(name);
    }
}