مطالب
خواندنی‌های 12 تیر

اس کیوال سرور

امنیت

توسعه وب

دات نت فریم ورک

دبلیو سی اف

دبلیو پی اف و سیلور لایت

سایت‌های ایرانی

شیرپوینت

لینوکس

متفرقه

محیط‌های مجتمع توسعه

مرورگرها

مسایل انسانی، اجتماعی و مدیریتی برنامه نویسی

پی اچ پی

نظرات اشتراک‌ها
Rider 2024.2 منتشر شد

شرکت JetBrains اخیرا IPهای ایرانی را بسته و دیگر این بسته‌ها از قسمت download سایت آن، قابل دریافت نیستند؛ اما لینک مستقیم دریافت آن‌ها بدون مشکل کار می‌کند:

https://download-cdn.jetbrains.com/rider/JetBrains.Rider-2024.2.exe
نظرات مطالب
تغییر عملکرد و یا ردیابی توابع ویندوز با استفاده از Hookهای دات نتی
سورس پروژه قابل دریافت هست و به عنوان یک قالب برای این نوع کارها میشه ازش استفاده کرد.
برای مثال در این قالب جایی که هوک تعریف میشه به این صورت تغییر خواهد کرد:
                _getHostByNameHook = LocalHook.Create(
                                        InTargetProc: LocalHook.GetProcAddress("ws2_32.dll", "gethostbyname"),
                                        InNewProc: new GetHostByNameDelegate(getHostByNameHooked),
                                        InCallback: this);
delegate آن چنین تعریفی خواهد داشت (توضیحات آن در متن فوق هست؛ قسمت (ج) نوشتن هوک):
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = false)]        
        private delegate IntPtr GetHostByNameDelegate(string name);
و جایی که نهایتا درخواست‌های DNS دریافت می‌شوند به صورت زیر تعریف خواهد شد:
        private static IntPtr getHostByNameHooked(string name)
        {
            // redirect ...
            //if (name.StartsWith("www.google.com"))
            //{
            //    return Native.GetHostByName("127.0.0.1");
            //}            

            return Native.gethostbyname(name);
        }
در اینجا می‌شود درخواست‌های DNS را تغییر جهت داد (مثلا گوگل را بلاک کرد)، یا همان تابع اصلی ویندوز را اجرا کرد و یا name دریافتی را در یک فایل مثلا لاگ کرد.
مطالب
ELMAH 1.1

نگارش جدید ELMAH ارائه شده است. این نگارش کاملا با نگارش قبلی سازگار بوده و تنها بازنویسی فایل dll آن با نگارش جدید کفایت می‌کند.

لیست موارد فیکس شده
- System.Data.SQLite.dll causes image problems on 64-bit IIS/ASP.NET
- Incorrect jscript filter sample

لیست تازه‌های آن
- Ability to set mail priority in errorMail config section
- Allow configuration-based filtering rules to be diffrent for e-mail and log
- Adjust behavior of smtpPort attribute in
- Remove the XML declaration from the string returned by ErrorXml.EncodeString


دریافت از گوگل کد و یا دریافت از رپید شیر (سورس +‌ بایناری)

مطالب
آشنایی با DGML

یکی از قابلیت‌های جدید VS2010 ، معرفی یک markup language است به نام DGML که از آن جهت data visualization و رسم انواع و اقسام گراف‌ها استفاده می‌شود.




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




نظرات مطالب
یکپارچه سازی Angular CLI و ASP.NET Core در VS 2017
فایل zip پیوستی انتهای بحث را دریافت کنید. در فایل src\app\app.module.ts آن، تعریف ذیل برای معرفی HttpModule وجود دارد و بدون آن، استثنای No provider for Http را دریافت خواهید کرد:
import { HttpModule } from '@angular/http';

@NgModule({
  imports: [
    HttpModule
  ]
مطالب
اضافه کردن Watermark به تصاویر یک برنامه ASP.NET MVC در صورت لینک شدن در سایتی دیگر
درگیر شدن با سایت‌های دیگر که چرا مطالب ما را کپی کرده‌اید نهایتا بجز فرسایش عصبی حاصل دیگری را به همراه ندارد. اساسا زمانیکه مطلبی را به صورت باز در اینترنت انتشار می‌دهید، قید کپی شدن یا نشدن آن‌را باید زد. اما ... می‌توان همین سایت‌ها را تبدیل به تبلیغ کننده‌های رایگان کار خود نمود که در ادامه نحوه انجام آن‌را در یک برنامه ASP.NET MVC بررسی خواهیم کرد:

الف) نیاز است ارائه تصاویر تحت کنترل برنامه باشند.

using System.IO;
using System.Net.Mime;
using System.Web.Mvc;

namespace MvcWatermark.Controllers
{
    public class HomeController : Controller
    {
        const int ADay = 86400;

        public ActionResult Index()
        {
            return View();
        }

        [OutputCache(VaryByParam = "fileName", Duration = ADay)]
        public ActionResult Image(string fileName)
        {
            fileName = Path.GetFileName(fileName); // تمیز سازی امنیتی است
            var rootPath = Server.MapPath("~/App_Data/Images");
            var path = Path.Combine(rootPath, fileName);
            if (!System.IO.File.Exists(path))
            {
                var notFoundImage = "notFound.png";
                path = Path.Combine(rootPath, notFoundImage);
                return File(path, MediaTypeNames.Image.Gif, notFoundImage);
            }
            return File(path, MediaTypeNames.Image.Gif, fileName);
        }
    }
}
در اینجا یک کنترلر را مشاهده می‌کنید که در اکشن متد Image آن، نام یک فایل دریافت شده و سپس این نام در پوشه App_Data/Images جستجو گردیده و نهایتا در مرورگر کاربر Flush می‌شود. از آنجائیکه الزامی ندارد fileName، واقعا یک fileName صحیح باشد، نیاز است توسط متد استاندارد Path.GetFileName این نام دریافتی اندکی تمیز شده و سپس مورد استفاده قرار گیرد. همچنین جهت کاهش بار سرور، از یک OutputCache به مدت یک روز نیز استفاده گردیده است.
نحوه استفاده از این اکشن متد نیز به نحو زیر است:
<img src="@Url.Action(actionName: "Image", controllerName: "Home", routeValues: new { fileName = "EF_Stra_08.gif" })" />


ب) آیا فراخوان تصویر ما را مستقیما در سایت خودش قرار داده است؟

        private bool isEmbeddedIntoAnotherDomain
        {
            get
            {
                return this.HttpContext.Request.UrlReferrer != null &&
                       !this.HttpContext.Request.Url.Host.Equals(this.HttpContext.Request.UrlReferrer.Host,
                                                                   StringComparison.InvariantCultureIgnoreCase);
            }
        }
در ادامه توسط خاصیت سفارشی isEmbeddedIntoAnotherDomain درخواهیم یافت که درخواست رسیده، از دومین جاری صادر شده است یا خیر. اینکار توسط بررسی UrlReferrer ارسال شده توسط مرورگر صورت می‌گیرد. اگر Host این UrlReferrer با Host درخواست جاری یکی بود، یعنی تصویر از سایت خودمان فراخوانی شده‌است.


ج) افزودن خودکار Watermark در صورت کپی شدن در سایتی دیگر

        private byte[] addWaterMark(string filePath, string text)
        {
            var image = new WebImage(filePath);
            image.AddTextWatermark(text);
            return image.GetBytes();
        }
کلاسی در فضای نام System.Web.Helpers وجود دارد به نام WebImage که کار افزودن Watermark را بسیار ساده کرده است. نمونه‌ای از نحوه استفاده از آن‌را در متد فوق ملاحظه می‌کنید.
اما ... پس از امتحان تصاویر مختلف ممکن است گاها با خطای زیر مواجه شویم:
 A Graphics object cannot be created from an image that has an indexed pixel format.
مشکل از اینجا است که تصاویر با فرمت ذیل برای انجام کار Watermark پشتیبانی نمی‌شوند:
PixelFormatUndefined
PixelFormatDontCare
PixelFormat1bppIndexed
PixelFormat4bppIndexed
PixelFormat8bppIndexed
PixelFormat16bppGrayScale
PixelFormat16bppARGB1555
اما می‌توان تصویر دریافتی را ابتدا تبدیل به BMP کرد و سپس Watermark دار نمود:
        private byte[] addWaterMark(string filePath, string text)
        {
            using (var img = System.Drawing.Image.FromFile(filePath))
            {
                using (var memStream = new MemoryStream())
                {
                    using (var bitmap = new Bitmap(img))//avoid gdi+ errors
                    {
                        bitmap.Save(memStream, ImageFormat.Png);                        
                        var webImage = new WebImage(memStream);
                        webImage.AddTextWatermark(text, verticalAlign: "Top", horizontalAlign: "Left", fontColor: "Brown");
                        return webImage.GetBytes();
                    }
                }
            }
        }
در اینجا نمونه اصلاح شده متد addWaterMark فوق را بر اساس کار با تصاویر bmp و سپس تبدیل آن‌ها به png، ملاحظه می‌کنید. به این ترتیب دیگر به خطای یاد شده بر نخواهیم خورد.
در ادامه، قسمت آخر کار، اعمال این مراحل به اکشن متد Image است:
            if (isEmbeddedIntoAnotherDomain)
            {
                var text = Url.Action(actionName: "Index", controllerName: "Home", routeValues: null, protocol: "http");
                var content = addWaterMark(path, text);
                return File(content, MediaTypeNames.Image.Gif, fileName);
            }
            return File(path, MediaTypeNames.Image.Gif, fileName);
در اینجا اگر تشخیص داده شود که تصویر، در دومین دیگری لینک شده است، آدرس سایت ما به صورت خودکار در بالای تصویر درج خواهد شد.

کدهای نهایی این کنترلر را از اینجا می‌توانید دریافت کنید:
HomeController.cs
به همراه نمونه تصویری که استثنای یاد شده را تولید می‌کند؛ جهت آزمایش بیشتر:
EFStra08.gif
مطالب
روش‌های مختلف انجام چند کار به صورت همزمان در C# .NET - قسمت دوم
در قسمت قبل دیدیم که انجام کارهای همزمان، با Objectهایی که به اصطلاح Thread Safe نیستند (مانند DbContext) خروجی چندان جالبی ندارد و برای مثال اگر در یک Service یک DbContext را Inject کنیم (مثلا با Constructor injection) و از آن در متدی استفاده کنیم که آن متد یا با TPL یا RX و ... به صورت چندتایی و همزمان اجرا شود، DbContext به مشکل می‌خورد؛ یعنی نمی‌توان یک وهله از DbContext را بین چند Thread همزمان پردازش موازی، به اشتراک گذاشت.
در کدهای فرضی مثال‌های قسمت قبل، متدی داشتیم با نام DoSomethingWithCustomer که مثلا همان متدی بود که قرار است همزمان اجرا شود. یکی از ساده‌ترین کارهایی که برای رفع این مشکل می‌توان انجام داد، نوشتن چنین کدی است:
public async Task DoSomethingWithCustomer(Customer customer)
{
    using var dbContext = new AppDbContext();

    // ...
}
در این حالت، اگر متد DoSomethingWithCustomer به صورت همزمان اجرا شود، به ازای هر بار اجرا، یک DbContext جدید ساخته میشود؛ پس از یک DbContext مشترک، به صورت همزمان توسط چندین Thread پردازش موازی، استفاده نخواهد شد. ولی مشکل اینجاست که از Dependency Injection برای ساختن DbContext استفاده نشده‌است و ما خودمان، هم new کرده‌ایم و هم Dispose!

این روش ابدا توصیه نمی‌شود؛ برای اینکه Dependency Injection این روزها مسائل خیلی زیادی را مدیریت می‌کند. مثلا DbContext در EF Core وقتی با Dependency Injection ساخته شود، Logging اش هم فعال می‌شود و یا مثلا اگر از متد زیر
services.AddDbContextPool<AppDbContext>();
برای Register کردن DbContext استفاده کرده باشیم، تعدادی DbContext ساخته می‌شود و در پروژه به صورت امن از همان چندتا استفاده می‌شود؛ بجای اینکه Objectها مدام ساخته و از بین برده شوند که این مهم، روی کارآیی تاثیر گذار است.
و یا مثلا برای HttpClient فقط در همین سایت نزدیک به یک دوجین مقاله توضیح داده‌اند که چرا new کردن و Dispose کردن HTTP Client مناسب نیست و بهتر است برای Register کردن HttpClient، از services.AddHttpClient استفاده و از IHttpClientFactory و سایر روشها برای Resolve کردن HttpClient استفاده کنیم که اینها نیز توسط Dependency Injection قابل استفاده هستند. از مسائلی مانند Polly و ... نیز می‌گذریم.
راه حل ایجاد یک Context جدید، تقریبا در تمامی کتابخانه‌های Dependency Injection دیده شده‌است و آن ساختن یک Child Scope است. در ادامه با Microsoft.Extensions.DependencyInjection یک پیاده سازی آن‌را خواهیم داشت؛ ولی مشابه این روش در سایر کتابخانه‌ها همچون Autofac نیز شدنی است.

برای شروع System.IServiceProvider را inject کنید. سپس کد قبلی را به این شکل بنویسید:
(نیاز به ;using Microsoft.Extensions.DependencyInjection در بالای فایل کد است)
public async Task DoSomethingWithCustomer(Customer customer)
{
    using var scope = _serviceProvider.CreateScope();
    var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    var httpClient = scope.ServiceProvider.GetRequiredService<IHttpClientFactory>().CreateClient();
    // ...
}
در این روش فقط نیاز به using نوشتن برای خط اول است؛ یعنی scope که Dispose شود، Objectهایی که به وسیله آن scope ساخته شده‌اند، آزاد خواهند شد. تمام آن چیزهایی را که قبلا با Constructor یا Property injection می‌توانستید بگیرید را اکنون می‌توانید با متد GetRequiredService بگیرید.
همچنین می‌توانید برای داشتن کدی بهتر، یک interface و class را ایجاد کنید و logic مربوطه را در آن سرویس قرار دهید و در آن سرویس با constructor یا property injection از DbContext و HttpClient و سایر سرویس‌ها استفاده کنید و در نهایت آن interface/class را رجیستر کنید و در DoSomethingWithCustomer به کمک child scope، یک object از آن سرویس بسازید و متدش را فراخوانی کنید. برای مثال اگر هدف ساختن Excel تاریخچه خریدهای مشتری است، داریم:
public interface IOrderHistoryService
{
    Task BuildCustomerHistory();
}

public class OrderHistoryService : IOrderHistoryService
{
    private AppDbContext _dbContext;

    public OrderHistoryService(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task BuildCustomerHistory()
    {
        // ...
    }
}
سپس اگر جایی لازم شد روی لیستی از مشتری‌ها این متد اجرا شود، از TPL استفاده می‌کنیم و متدی را فراخوانی می‌کنیم که در آن child scope می‌سازیم و scope.GetRequiredService را برای گرفتن IOrderHistoryService استفاده می‌کنیم. در این روش هم مشکلی در استفاده از Object هایی که thread safe نیستند (مانند DbContext) رخ نخواهد داد و از Dependency injection و مزیت‌های بی‌شمار آن نیز بهره برده‌ایم.
نظرات مطالب
سطح دوم cache در NHibernate
برای برنامه‌های تک کاربره شاید لزومی نداشته باشه چون هدف اصلی آن کم کردن بار سرور است
یک سری از موارد سایت عمومی است مثلا آمار سایت حالا سوال اینجا است که اگر 10 هزار نفر هم اکنون به سایت مراجعه کردند باید 10 هزار بار به بانک اطلاعاتی جهت دریافت یک سری اطلاعات با سطح دسترسی عمومی مراجعه کرد؟ اینجا است که سطح دوم کش ذکر شده معنا پیدا می‌کند