نظرات مطالب
مروری بر کاربردهای Action و Func - قسمت اول
نمی‌توان. چون در اصل Action و Func به این صورت تعریف شده‌اند:
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
البته می‌توان بجای Action و Func، یک delegate سفارشی را از صفر نوشت؛ ولی هدف در اینجا سهولت استفاده‌است.
+ از زمان C# 7.0 اگر نیاز به نامگذاری این پارامترها را داشتید، می‌توانید از tuples به صورت زیر استفاده کنید:
Func<(string firstName, string lastName), string> f = (data) => data.firstName + data.lastName;
f(("Foo", "Bar"));
نظرات مطالب
Blazor 5x - قسمت 34 - توزیع برنامه‌های Blazor بر روی IIS
یک نکته‌ی تکمیلی: بهبود IL Trimming در NET 6x.
در دات نت 5، IL Trimming فقط اسمبلی‌های استفاده نشده را حذف می‌کند. در دات نت 6، این حالت پیش‌فرض به link تغییر پیدا کرده؛ یعنی نه فقط اسمبلی‌های استفاده نشده را حذف می‌کند، بلکه متدها و اعضایی را هم که در برنامه استفاده نشده‌اند نیز حذف می‌کند.
نظرات مطالب
BloggerToCHM 1.3
برای تنظیم پ به صورت زیر عمل کنید:
فایل BloggerToCHM.exe.config را با یک ادیتور ساده مثل notepad باز کنید.
الف) سپس usesystemdefault رادر قسمت defaultProxy به True تنظیم کنید. اکنون هر پروکسی که در IE ست کرده باشید به صورت خودکار در برنامه استفاده می‌شود. (البته یکبار باید برنامه را باز و بسته کنید تا اعمال شود)
یا
ب) روش دوم:
به مثال آخر صفحه آدرس زیر مراجعه کنید:
http://msdn.microsoft.com/en-us/library/sa91de1e.aspx


این روش‌ها در مورد هر برنامه‌ای که با دات نت فریم ورک نوشته شده باشد صادق است. (حتی اگر فایل کانفیگ هم نداشت، دستی درست کنید کار می‌کند)
مطالب
برنامه‌ی ++ Notepad و syntax highlighting فایل‌های دات نتی

برنامه‌ی ++ Notepad به عنوان یک ادیتور رایگان، سبک و بسیار سریع به همراه ارائه‌ی syntax highlighting عالی، یکی از ویرایشگرهای محبوب برنامه نویس‌ها (در هر گرایش و صنفی) به شمار می‌رود. اکثر فایل‌های مرتبط با دات نت فریم ورک هم منهای فایل‌های سورس‌ها با پسوند cs و vb و امثال آن، دقیقا از نوع XML هستند؛ برای مثال: xaml, config, edmx, csproj و بسیاری موارد دیگر. این پسوندها به صورت پیش فرض در برنامه‌ی ++ Notepad جهت اعمال syntax highlighting تعریف نشده‌اند و برای اضافه کردن آن‌ها کافی است به صورت زیر عمل کرد:
به منوی Settings گزینه‌ی Style configurator مراجعه کنید. سپس در قالبی که آن‌را انتخاب کرده‌اید، زبان XML را انتخاب کرده و فیلد User ext را تکمیل کنید (شکل زیر):



مطالب
آشنایی با Gridify
Gridify چیست ؟

به طور خلاصه Gridify یک کتابخانه ساده و سریع است که عملیات‌های Filtering , Pagination و Sorting را با استفاده از شرط‌های متنی (string based) امکان پذیر میکند.
به طور مثال فرض کنید که یک API را برای دریافت لیست کاربران با نام UsersList نوشته‌اید. مثال:
 [HttpGet("[action]")]
 public async Task<IActionResult> UsersList()
 {
    var users =  await _dbContext.Users.AsNoTracking().ToListAsync();
    return Ok(users);
 }
طبیعتا بخش FrontEnd نرم افزار شما نیاز دارد این اطلاعات را به کاربر نمایش دهد. به همین جهت در بیشتر مواقع از یک گرید برای نمایش این اطلاعات استفاده میشود.
پس از دریافت اطلاعات از سرور با مشکلات زیر مواجه خواهیم شد.
  1. عدم پشتیبانی از Pagination: چون API، تمامی کاربران را به سمت کلاینت ارسال میکند؛ به همین جهت، هم با مشکل کارآیی (performance) در آینده مواجه میشویم و هم امکان گذاشتن صفحه بندی (Pagination) وجود نخواهد داشت. 
  2. عدم پشتیبانی از Sorting: اگر در گرید نمایش داده شده کاربر بخواهد اطلاعات را Sort کند، چون چنین امکانی هنوز برای API ما تعریف نشده، این عملیات سمت سرور امکان پذیر نیست.
  3. عدم پشتیبانی از Filtering: همیشه نمایش تمامی اطلاعات مفید نیست. در اکثر مواقع ما نیاز داریم تا قسمتی از اطلاعات را با شرطی خاص، برگردانیم. به طور مثال لیست کاربران فعال در سامانه یا لیست کاربران غیرفعال. 
این مشکلات بدون استفاده از هیچ کتابخانه‌ای قابل حل است ولی نه به سادگی؛ به طور مثال یا باید چندین API مختلف با امکانات مختلف بنویسیم، یا یک API را برای پشتیبانی از این موارد تغییر بسیار دهیم. من برای اینکه از بحث دور نشویم، به پیاده سازی نمونه دستی پشتیبانی از این موارد در اینجا نمی‌پردازم، چرا که اگر یکبار تلاشی را برای اینکار انجام داده باشیم، طبیعتا  مشکلات و کد کثیفی که در نهایت تولید شده است، یادآوری خواهد شد. 
برای رفع این مشکلات میتوان از کتابخانه Gridify استفاده کرد. مثال :
 [HttpGet("[action]")]
 public async Task<IActionResult> UsersList(GridifyQuery filter)
 {
    var users =  await _dbContext.Users.AsNoTracking().GridifyAsync(filter);
    return Ok(users);
 }
در مثال بالا با استفاده از کلاس GridifyQuery میتوانیم به کنترل هر سه مشکل Sorting - Pagination - Filtering سمت کلاینت بپردازیم. (در ادامه با این کلاس بیشتر آشنا خواهیم شد).


استفاده از Gridify به API‌ها محدود نمیشود. به طور کلی ما میتوانیم در هر نوع لیستی که امکان استفاده از IQueryable  را به ما میدهد از آن استفاده نماییم. 
فرض کنید در یک برنامه Console Application قصد داریم یک فیلتر را از کاربر دریافت کرده و آن را روی لیست خروجی خود اعمال کنیم. به دلیل اینکه امکان جستجوی متنی در دات نت وجود ندارد، برای انجام اینکار مجبور خواهیم شد که برای تک تک فیلدهایی که قرار است برای فیلترینگ پشتیبانی کنیم، یک query جداگانه بنویسیم؛ ولی این عملیات توسط کتابخانه Gridify امکان پذیر است. به طور مثال فرض کنید قصد داریم در لیست کاربران، کاربرانی را  با نام Ali، پیدا کنیم. 
var result = Users.AsQueryable().ApplyFiltering("name==Ali");
این کد دقیقا معادل کد زیر است.
var result = Users.AsQueryable().Where(q => q.Name == "Ali");
در اینجا با استفاده از کتابخانه Gridify ما توانستیم یک static Linq را به یک dynamic Linq که در runtime مقدار دهی خواهد شد، تغییر دهیم. به همین جهت استفاده از مورد اول در برنامه‌ی Console ما امکان پذیر است. تا اینجا ما با امکانات کلی این کتابخانه آشنا شدیم. در مقالات بعدی سعی میکنم به سایر امکانات این کتابخانه و بیشتر به جزئیات بپردازم. همینطور برای کسب اطلاعات بیشتر میتوانید به لینک زیر مراجعه نمایید.
مطالب
گوگل ریدر و افزودن توضیحات

اگر به گوگل ریدر دقت کرده باشید، دو گزینه‌ی به اشتراک گذاری دارد: share و share with note .


اگر گزینه‌ی share with note را انتخاب کرده و توضیحی را ارسال یا اضافه کنیم، این توضیحات، به فید از نوع Atom اشتراک‌ها هم اضافه می‌شود. مثلا:

<?xml version="1.0"?>
<feed xmlns:media="http://search.yahoo.com/mrss/"
xmlns:gr="http://www.google.com/schemas/reader/atom/"
xmlns:idx="urn:atom-extension:indexing"
xmlns="http://www.w3.org/2005/Atom"
idx:index="no"
gr:dir="ltr">

...

<entry gr:crawl-timestamp-msec="1316627782108">
...
<gr:annotation>
<content type="html">text-text-text</content>
<author>
<name>Vahid</name>
</author>
</gr:annotation>
...
</entry>

...

</feed>



این افزونه استاندارد نیست و همانطور که در قسمت xmlns:gr اطلاعات فوق مشخص است، در فضای نام http://www.google.com/schemas/reader/atom/ معنا پیدا می‌کند. از دات نت سه و نیم به بعد هم کلاسی جهت خواندن فیدهای استاندارد وجود دارد (تعریف شده در فضای نام System.ServiceModel.Syndication). اما چگونه می‌توان این افزونه‌ی غیر استاندارد را با کمک امکانات توکار دات نت خواند؟
روش کار با استفاده از ElementExtensions هر آیتم یک فید است؛ به صورت زیر :

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using System.Xml.Linq;

namespace Linq2Rss
{
public class RssEntry
{
public string Title { set; get; }
public string Description { set; get; }
public string Link { set; get; }
public DateTime PublicationDate { set; get; }
public string Author { set; get; }
public string BlogName { set; get; }
public string BlogAddress { set; get; }
public string Annotation { set; get; }
}

public static class AtomReader
{
private static string getAtomAnnotation(this SyndicationElementExtensionCollection items)
{
if (!items.Any()) return string.Empty;
var item = items.Where(x => x.OuterName.ToLowerInvariant() == "annotation").FirstOrDefault();
if (item == null) return string.Empty;

var element = item.GetObject<XElement>();
var content = element.Element("{http://www.w3.org/2005/Atom}content");
return content == null ? string.Empty : content.Value;
}

public static IList<RssEntry> GetEntries(string feedUrl)
{
using (var reader = XmlReader.Create(feedUrl))
{
var feed = SyndicationFeed.Load(reader);
if (feed == null) return null;

return feed.Items.Select(x =>
new RssEntry
{
Title = x.Title.Text,
Author = x.Authors.Any() ? x.Authors.First().Name : string.Empty,
Description = x.Content == null ? string.Empty : ((TextSyndicationContent)x.Content).Text,
Link = x.Links.Any() ? x.Links.First().Uri.AbsoluteUri : string.Empty,
PublicationDate = x.PublishDate.UtcDateTime,
BlogName = x.SourceFeed.Title.Text,
BlogAddress = x.SourceFeed.Links.Any() ? x.SourceFeed.Links.First().Uri.AbsoluteUri : string.Empty,
Annotation = x.ElementExtensions.getAtomAnnotation()

}).ToList();
}
}
}
}

در این مثال به کمک متد الحاقی getAtomAnnotation، مجموعه‌ی SyndicationElementExtensionCollection هر آیتم یک فید بررسی شده، در بین این‌ها، موردی که از نوع annotation باشد انتخاب و سپس content آن استخراج می‌گردد.


نکته‌ای دیگر:
اکثر کلاس‌های موجود در فضاهای نام مرتبط با XML در دات نت امکان خواندن اطلاعات را از یک Uri هم دارند؛ مانند مثال فوق و متد XmlReader.Create بکارگرفته شده در آن. اما اگر بخواهیم حین خواندن اطلاعات، یک پروکسی را نیز به پروسه جاری اضافه کنیم، به نظر خاصیت یا متدی جهت انجام اینکار وجود ندارد. برای رفع این مشکل می‌توان یک پروکسی سراسری را تعریف کرد. تنها کافی است خاصیت System.Net.WebRequest.DefaultWebProxy مقدار دهی شود. پس از آن به صورت خودکار بر روی کل برنامه تاثیر خواهد گذاشت.


مطالب
مقایسه نتایج الگوریتم‌های هش کردن اطلاعات در اس کیوال سرور و دات نت

از اس کیوال سرور 2005 به بعد تابع HashBytes نیز به مجموعه توابع قابل استفاده در دستورات T-SQL اس کیوال سرور اضافه شده است که الگوریتم‌های MD2 | MD4 | MD5 | SHA | SHA1 را پشتیبانی می‌کند. برای مثال:
DECLARE @str1 VARCHAR(4),
@str2 NVARCHAR(4)

--متن یونیکد اینجا ناقص ذخیره می‌شود
SET @str1 = 'وحید'

SET @str2 = N'وحید'

SELECT hashbytes('md5', @str1) --C82A7D721AAE517AD76EF1B871BC33CE

SELECT hashbytes('md5', @str2) --7D883091B80F3CD20B872CADBFDDACDF

اگر این نتایج را بخواهیم با استفاده از فضای نام استاندارد System.Security.Cryptography تولید کنیم، باید به encoding رشته دریافتی حتما دقت داشت؛ در غیر اینصورت نتایج یکسان نخواهند بود.
مهم‌ترین encoding های پشتیبانی شده در دات نت در جدول زیر برشمرده شده‌اند:

Encoding تعداد بیت هر کاراکتر

ASCII
هر کاراکتر آن 7 بیت است

UTF7
هر کاراکتر آن 7 بیت است

UTF8
هر کاراکتر آن 8 بیت و یا یک بایت است

Unicode (UTF-16)
هر کاراکتر آن 16 بیت و یا دو بایت است

UTF32
هر کاراکتر آن 32 بیت و یا 4 بایت است


نوع nvarchar در اس کیوال سرور همانند حالت Encoding.Unicode‌ دات نت است و هر کاراکتر آن 2 بایت می‌باشد.
این نکته‌ هنگام استفاده از این توابع بسیار حائز اهمیت است. برای مثال اگر تابع HashBytes اس کیوال سرور را بخواهیم در دات نت پیاده سازی کنیم، به کلاس زیر خواهیم رسید:

using System.Text;
using System.Security.Cryptography;

class CHash
{
public static string GetMD5Hash(string input, Encoding encoding)
{
byte[] bytes = new MD5CryptoServiceProvider().ComputeHash(encoding.GetBytes(input));
StringBuilder chars = new StringBuilder();
foreach (byte chr in bytes)
{
chars.Append(chr.ToString("x2"));
}
return chars.ToString();
}
}
در اینجا تنها حالت زیر با هش تولید شده یک فیلد یا متغیر از نوع nvarchar توسط تابع HashBytes اس کیوال سرور معادل است:

string result = CHash.GetMD5Hash("وحید", Encoding.Unicode);

پ.ن.
احتمالا عده‌ای را دیده‌اید که هر چقدر تلاش می‌کنند با سی شارپ متون ایران سیستم تحت داس را به نمونه‌های ویندوزی تبدیل کنند، کمتر موفق می‌شوند؛ علت را با توجه به جدول encoding فوق و عدم اطلاع از آن بهتر می‌توان بررسی کرد.


اشتراک‌ها
تکمیل نهایی ویژوال استودیو 2012 و دات نت فریم ورک 4.5
مایکروسافت از تکمیل نهایی ویژوال استودیو 2012 و دات نت فریم ورک 4.5 خبر داده است. به این ترتیب انتشار نهایی برای مشترکین MSDN در تاریخ 15 اگوست و برای عموم در تاریخ 12 سپتامبر در دسترس خواهد بود.
تکمیل نهایی ویژوال استودیو 2012 و دات نت فریم ورک 4.5
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 2 - بررسی ساختار جدید Solution
وقتی که دات نت 4.6.1 رو خواستید معرفی کنید جدای گره dotnetcoreapp بود و نود جدید براش نوشتید . خب اگر این طور باشه پس این دو تا وابستگی بهم ندارن؟ یعنی در واقع دو سکو برای اجرا برنامه معرفی کردیم ؟ و اگر فریم ورک 4.6.1 داخل dotnetcoreapp باشه یعنی dotnetcore روی بیس 4.6.1 اجرا می‌شه؟
نظرات مطالب
معرفی DNTProfiler
- تصویر انتهای بحث در ویندوز 8.1 تهیه شده‌است.
- این برنامه برای اجرا نیاز به دات نت فریم ورک 4 دارد. بنابراین بر روی ویندوزهای XP SP3 به بعد قابل اجرا است.
- ضمنا خطاهای برنامه در فایل متنی به نام ErrorsLog.Log در کنار فایل اجرایی برنامه ثبت می‌شوند.