مطالب
حذف محدودیت‌های فایل‌های PDF توسط iTextSharp
پیشنیاز
«رمزنگاری فایل‌های PDF با استفاده از کلید عمومی توسط iTextSharp»

در مطلب فوق در مورد رمزنگاری اطلاعات فایل‌های PDF به کمک iTextSharp بحث شد. در مطلب جاری به نحوه رفع این محدودیت‌ها خواهیم پرداخت.

الف) رمزگشایی با استفاده از کلمه عبور
using System.IO;
using iTextSharp.text.pdf;

namespace PdfDecryptor.Core
{
    public class PasswordDecryptor
    {
        public string ReadPassword { set; get; }
        public string PdfPath { set; get; }
        public string OutputPdf { set; get; }

        public void DecryptPdf()
        {
            PdfReader.unethicalreading = true;

            PdfReader reader;
            if (string.IsNullOrWhiteSpace(ReadPassword))
                reader = new PdfReader(PdfPath);
            else
                reader = new PdfReader(PdfPath, System.Text.Encoding.UTF8.GetBytes(ReadPassword));

            using (var stamper = new PdfStamper(reader, new FileStream(OutputPdf, FileMode.Create)))
            {
                stamper.Close();
            }
        }
    }
}
کلاس فوق دوکاربرد را می‌تواند به همراه داشته باشد:
- اگر PDF ایی صرفا دارای محدودیت چاپ بوده و این قابلیت ویژه آن غیرفعال شده است، فقط کافی است مسیر فایل PDF موجود (PdfPath) و مسیر فایل جدیدی که قرار است تولید شود (OutputPdf) ذکر گردد. خروجی فایلی خواهد بود که هیچگونه محدودیتی ندارد. این مساله هم صرفا توسط PdfReader.unethicalreading میسر شده است. به عبارتی ذکر و تنظیم edit password در فایل‌های PDF فاقد امنیت است. همین اندازه که PdfReader می‌تواند فایلی را بخواند، امکان تهیه یک کپی بدون محدودیت از آن توسط PdfStamper وجود خواهد داشت.
در مورد ReadPassword در پیشنیاز ذکر شده، توضیحات کافی به همراه تصویر وجود دارد؛ حالت خاصی که کاربران برای مشاهده محتویات فایل نیاز خواهند داشت تا کلمه‌ی عبور مرتبط را وارد نمایند. در اینجا ذکر ReadPassword الزامی  است. خروجی نهایی کلاس فوق رفع کامل این محدودیت است.


ب) رمزگشایی توسط کلید عمومی
using System.IO;
using iTextSharp.text.pdf;

namespace PdfDecryptor.Core
{
    public class Decryptor
    {
        public string PfxPath { set; get; }
        public string PfxPassword { set; get; }
        public string InputPdf { set; get; }
        public string OutputPdf { set; get; }

        public void DecryptPdf()
        {
            var certs = new PfxReader().ReadCertificate(PfxPath, PfxPassword);
            var reader = new PdfReader(InputPdf, certs.X509Certificates[0], certs.PrivateKey);
            using (var stamper = new PdfStamper(reader, new FileStream(OutputPdf, FileMode.Create)))
            {
                stamper.Close();
            }
        }
    }
}
در اینجا کدهای کامل رمزگشایی فایل PDF ایی که توسط فایل‌های مخصوص PFX رمزنگاری شده است را مشاهده می‌کنید. کلاس PfxReader آن در پیشنیاز بحث موجود است.
در این حالت مسیر فایل PFX به همراه کلمه عبور آن (PfxPassword) باید مشخص شود. خروجی فایلی است بدون محدودیت خاصی.


پ.ن.
این مثال را به صورت یک فایل اجرایی از اینجا می‌توانید دریافت کنید.
مطالب
چگونگی گزارشگیری از Business Objects مانند List توسط StimulSoft

می‌خواهیم از یک لیست در گزارش خود استفاده کنیم؛ بطور مثال وقتی در LINQ  از دستور ToList استفاده می‌کنیم و می‌خواهیم آنرا بصورت مستقیم به Stimul بفرستیم. فرض بر این است که شما DLLهای Stimul را به پروژه اضافه کرده اید و آماده گزارشگیری هستید.

مثلا مدلی در Entity FrameWork با نام base_CenterType 

public class base_CenterType
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public string Dsc { get; set; }
     }

و متدی بصورت ذیل:

public IList<base_CenterType> GetAll()
        {
            return _base_CenterType.ToList();
        }

طراحی گزارش برای این لیست به این صورت است:

1- اضافه کردن StiWebReport به فرم به نام StiWebReport1

2- با کلیک بر روی فلش سمت راست و بالای StiWebReport1 و انتخاب Design Report، وارد قسمت طراحی می‌شویم:

3- با راست کلیک بر روی Business Object و انتخاب New Business Object  پنجره مربوطه باز میشود:

4- بعد از زدن OK پنجره زیر باز خواهد شد که باید در کادر Name نام Business Object را انتخاب کنیم که برای خوانایی بهتر است همان نام کلاس را برای آن انتخاب کنیم. چون Category  نداریم پس باید کادر آن خالی بماند. 

در قسمت Columns باید ستون‌های هم نام و هم نوع با خواص کلاس base_CenterType  را ایجاد کنیم. 

و نهایتا Business Objectی به نام base_CenterType با سه ستون ایجاد خواهد شد. 

  حال می‌توانید ستون‌های مورد نظر را در گزارش بکار ببرید.

با فرض اینکه گزارش را طراحی کرده و آنرا در ریشه درایو C ذخیره کرده‌اید، از  قطعه کد زیر برای ارسال لیست به گزارش و نمایش آن استفاده میکنیم.

StiReport mainreport = new StiReport();            
mainreport.RegBusinessObject("base_CenterType", base_CenterTypeService.GetAll());
mainreport.Load("C:\\StiWebReport2.mrt");
mainreport.Show();
نظرات مطالب
امکان تغییر شکل سراسری URLهای تولیدی توسط برنامه‌های ASP.NET Core 2.2
یک نکته‌ی تکمیلی: بهبود کارآیی IOutboundParameterTransformer تهیه شده
با توجه به مطلب « چگونه Regex سریعتری داشته باشیم؟ » بهتر است regex نوشته شده را کامپایل کرد تا به حداکثر کارآیی رسید:
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Routing;

public class CustomUrlTransformer : IOutboundParameterTransformer
{
    private static readonly Regex _camelCasingRegEx = new Regex("([a-z])([A-Z])", RegexOptions.Compiled);

    public string TransformOutbound(object value)
    {
        return value == null ? null : _camelCasingRegEx.Replace(value.ToString(), "$1-$2");
    }
}
نظرات مطالب
آپلود فایل توسط فرم‌های پویای jqGrid
عرض کردم: « این تغییر را در سمت سرور، معادل کدهای سمت کلاینت، اعمال کردید؟»
// todo: change `imageName` according to the form's file element name
زمانیکه fileElementId = xThumbnail تنظیم شده، همین نام باید در سمت سرور هم اعمال شود:
[HttpPost]
public ActionResult UploadFiles(HttpPostedFileBase xThumbnail, int id)
{
کلا ASP.NET MVC به همین نحو کار model binding را انجام می‌دهد. هم نام‌ها را به هم نام‌ها متصل می‌کند؛ در همه جا. حالت پیش فرض هست.
نظرات مطالب
آشنایی با NHibernate - قسمت هشتم
برای اینکه از بحث دور نشیم، در NHibernate این الگوها قابل مشاهده است:
الگوی Facade که همان session و ISession معروف آن است و کار آن فراخوانی تعداد قابل ملاحظه‌ای زیر سیستم و مخفی کردن آن‌ها از دید کاربر نهایی است. به این صورت شما توانایی کار کردن با انواع بانک‌های اطلاعاتی را بدون درگیر شدن با جزئیات آن‌ها از طریق یک اینترفیس عمومی پیدا می‌کنید.
الگوی proxy که پایه و اساس lazy loading آن است.
الگوی object pool جهت مدیریت اتصالات آن به بانک اطلاعاتی
الگوی Interpreter جهت مدیریت کوئری‌های ویژه آن
و ...

الگوی Repository هم یک نوع نگارش سفارشی الگوی Facade است. در اینجا یک سیستم پیچیده (یک سطح بالاتر است از ISession که کارش مخفی کردن ساختار داخلی NHibernate است) یا همان ORM مورد نظر را دریافت کرده و یک اینترفیس ساده، قابل درک و عمومی را از آن را ارائه می‌دهد. هدف آن مخفی کردن ریز جزئیات روش کار با یک ORM خاص است. به همین جهت به آن Persistence Ignorance هم گفته می‌شود.
الگوی Repository یکی از الگوهای اصلی DDD یا Domain driven design است.
نظرات مطالب
مزیت‌های استفاده از رویه‌های ذخیره شده؛ واقعیت یا توهم؟!
چند مورد را در مورد نکته دوم جهت تکمیل بحث اضافه کنم:

در اس کیوال سرور 2000 اگر از ad hoc کوئری استفاده شود احتمال recompile شدن بسیار زیاد است اما این مورد از اس کیوال سرور 2005 به بعد به شدت بهبود یافته. برای مطالعه بیشتر
Execution Plan Caching and Reuse
http://technet.microsoft.com/en-us/library/ms181055%28SQL.90%29.aspx

نکته مهمی که در ad hoc کوئری‌ها ممکن است سبب recompile شدن plan اجرایی آن شود بحث تغییر نوع یا اندازه‌ی پارامترهای مورد استفاده است. اگر این موارد به صورت صریح ذکر شوند و از پارامترهایADO.Net استفاده شوند، تشخیص نوع و اندازه پارامترها برای اس کیوال سرور بسیار ساده شده و حتما از کش بجای recompile استفاده خواهد کرد. برای مطالعه بیشتر:
Parameters and Execution Plan Reuse
http://technet.microsoft.com/en-us/library/ms175580%28SQL.90%29.aspx
دقیقا همین نکته را اگر از Nhibernate‌ استفاده می‌کنید نیز باید رعایت کنید:
NHibernate queries & sql server execution plans
http://testdrivendevelopment.wordpress.com/2009/03/10/nhibernate-queries-sql-server-execution-plans/
خلاصه این مقاله به این صورت است که اس کیوال سرور را وادار نکنیم که از recompile به جهت مشخص نبودن طول یا اندازه پارامترها، هر بار استفاده نماید.
نظرات مطالب
توزیع پروژه‌های ASP.NET Core 1.1 بدون ارائه فایل‌های View آن
برای کامپایل مجدد فایل‌های ویو (cshtml) در هنگام اجرای برنامه (runtime compilationو مشاهده تغییرات اعمال شده بر روی آن‌ها به صورت زیر عمل می‌کنیم:

  • ASP.NET Core 2.2
services.AddMvc()
    .AddRazorOptions(options => options.AllowRecompilingViewsOnFileChange = true);

  • ASP.NET Core 3.0 , 3.1
ابتدا بسته  Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation به پروژه اضافه کرده و سپس از کد زیر استفاده می‌کنیم:
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
        .AddRazorRuntimeCompilation();
    //...
}
 
نظرات مطالب
امکان بررسی سلامت برنامه در ASP.NET Core 2.2
ارتقاء به ASP.NET Core 3.0

قسمت UseHealthChecks با endpoint routing به صورت زیر تغییر می‌کند که مزیت آن، امکان اعمال authorization و تنظیمات مرتبط با آن است:
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints
            .MapHealthChecks("/healthz")
            .RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
    });
}
نظرات مطالب
بررسی تفصیلی رابطه Many-to-Many در EF Code first
- در مطلب «مراحل Refactoring یک قطعه کد برای اعمال تزریق وابستگی‌ها» این موضوع بهتر بررسی شده‌است.
- new EfTagService را حذف کنید. سپس سازنده‌ی کلاس را به نحو ذیل تغییر دهید:
public EfPostService(IUnitOfWork uow, ITagService tagService)
IoC Container مورد استفاده، بر اساس تنظیمات اولیه‌ی خودش، وهله‌ی مورد نیاز ITagService را تامین خواهد کرد.