نظرات مطالب
CheckBoxList برای فیلد Enum Flags مدل در ASP.Net MVC
مراجعه کنید به پیشنیازهای این مباحث تکمیلی. مانند:
تهیه سایت‌های چند زبانه و بومی سازی نمایش اطلاعات در ASP.NET MVC
Globalization در ASP.NET MVC 
اولی در مورد کار با ریسورس‌ها است و بومی سازی ویژگی‌ها نیز در آن لحاظ شده و دومی تهیه یک فریم ورک است برای کار با بانک اطلاعاتی و تامین منبع داده از این طریق
مطالب
MEF و الگوی Singleton

در مورد معرفی مقدماتی MEF می‌توانید به این مطلب مراجعه کنید و در مورد الگوی Singleton به اینجا.


کاربردهای الگوی Singleton عموما به شرح زیر هستند:
1) فراهم آوردن دسترسی ساده و عمومی به DAL (لایه دسترسی به داده‌ها)
2) دسترسی عمومی به امکانات ثبت وقایع سیستم در برنامه logging -
3) دسترسی عمومی به تنظیمات برنامه
و موارد مشابهی از این دست به صورتیکه تنها یک روش دسترسی به این اطلاعات وجود داشته باشد و تنها یک وهله از این شیء در حافظه قرار گیرد.

با استفاده از امکانات MEF دیگر نیازی به نوشتن کدهای ویژه تولید کلاس‌های Singleton نمی‌باشد زیرا این چارچوب کاری دو نوع روش وهله سازی از اشیاء (PartCreationPolicy) را پشتیبانی می‌کند: Shared و NonShared . حالت Shared دقیقا همان نام دیگر الگوی Singleton است. البته لازم به ذکر است که حالت Shared ، حالت پیش فرض تولید وهله‌ها بوده و نیازی به ذکر صریح آن همانند ویژگی زیر نیست:
[PartCreationPolicy(CreationPolicy.Shared)]

مثال:
فرض کنید قرار است از کلاس زیر تنها یک وهله بین صفحات یک برنامه‌ی Silverlight توزیع شود. با استفاده از ویژگی‌ Export به MEF اعلام کرده‌ایم که قرار است سرویسی را ارائه دهیم :

using System;
using System.ComponentModel.Composition;

namespace SlMefTest
{
[Export]
public class WebServiceData
{
public int Result { set; get; }

public WebServiceData()
{
var rnd = new Random();
Result = rnd.Next();
}
}

}
اکنون برای اثبات اینکه تنها یک وهله از این کلاس در اختیار صفحات مختلف قرار خواهد گرفت، یک User control جدید را به همراه یک دکمه که مقدار Result را نمایش می‌دهد به برنامه اضافه خواهیم کرد. دکمه‌ی دیگری را نیز به همین منظور به صفحه‌ی اصلی برنامه اضافه می‌کنیم.
کدهای صفحه اصلی برنامه (که از یک دکمه و یک Stack panel جهت نمایش محتوای یوزر کنترل تشکیل شده) به شرح بعد هستند:
<UserControl x:Class="SlMefTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
<StackPanel>
<Button Content="MainPageButton" Height="23"
HorizontalAlignment="Left"
Margin="10,10,0,0" Name="button1"
VerticalAlignment="Top" Width="98" Click="button1_Click" />
<StackPanel Name="panel1" Margin="5"/>
</StackPanel>
</UserControl>

using System.ComponentModel.Composition;
using System.Windows;

namespace SlMefTest
{
public partial class MainPage
{
[Import]
public WebServiceData Data { set; get; }

public MainPage()
{
InitializeComponent();
this.Loaded += mainPageLoaded;
}

void mainPageLoaded(object sender, RoutedEventArgs e)
{
CompositionInitializer.SatisfyImports(this);
panel1.Children.Add(new SilverlightControl1());
}

private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Data.Result.ToString());
}
}
}
با استفاده از ویژگی Import به MEF اعلام می‌کنیم که به اطلاعاتی از نوع شیء WebServiceData نیاز داریم و توسط متد CompositionInitializer.SatisfyImports کار وهله سازی و پیوند زدن export و import های همانند صورت می‌گیرد. سپس استفاده‌ی مستقیم از Data.Result مجاز بوده و مقدار آن null نخواهد بود.

کدهای User control ساده اضافه شده به شرح زیر هستند:

<UserControl x:Class="SlMefTest.SilverlightControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<Button Content="UserControlButton"
Height="23"
HorizontalAlignment="Left"
Margin="10,10,0,0"
Name="button1"
VerticalAlignment="Top"
Width="125"
Click="button1_Click" />
</Grid>
</UserControl>

using System.ComponentModel.Composition;
using System.Windows;

namespace SlMefTest
{
public partial class SilverlightControl1
{
[Import]
public WebServiceData Data { set; get; }

public SilverlightControl1()
{
InitializeComponent();
this.Loaded += silverlightControl1Loaded;
}

void silverlightControl1Loaded(object sender, RoutedEventArgs e)
{
CompositionInitializer.SatisfyImports(this);
}

private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Data.Result.ToString());
}
}
}
اکنون قبل از شروع برنامه یک break point را در سازنده‌ی کلاس WebServiceData قرار دهید. سپس برنامه را آغاز نمائید. تنها یکبار این سازنده فراخوانی خواهد شد (هر چند در دو کلاس کار Import اطلاعات WebServiceData صورت گرفته است). همچنین با کلیک بر روی دو دکمه‌ای که اکنون در صفحه‌ی اصلی برنامه ظاهر می‌شوند، فقط یک عدد مشابه نمایش داده می‌شود (با توجه به اینکه اطلاعات هر دکمه در یک وهله‌ی جداگانه قرار دارد؛ یکی متعلق است به صفحه‌ی اصلی و دیگری متعلق است به user control اضافه شده).

نظرات مطالب
چرا در سازمان‌ها برنامه‌های وب جایگزین برنامه‌های دسکتاپ شده‌اند (یا می‌شوند)؟
سلام مهندس . جالب بود و در اکثر کشور ها با توجه به افزایش سرعت اینترنت به این سمت گرایش داشتند . در آلمان در ایستگاه قطار یا آژانس هواپیمایی و ... به همین شکل هست و یا حداقل از یک وب سرویس بهره میبرند حتی اگر برنامه ویندوز داشته باشند . در آمریکا هم تا اونجا که میدونم silverlight و wpf به این منظور ( جهت همسان سازی محیط اینترنت و ویندوز ) استفادش رو به رشد هست . راستی آقای نصیری شما رو silverlight مانور نمیدید . یه مدتی هست که از Jquery چیزی نمیگید . منتظر مطالب جدیدتون هستم . موفق باشید .
مطالب
Span در C# 7.2
C# 7.2 به همراه تعداد کوچکی از بهبودهای کامپایلر است و با Visual Studio 2017 نگارش 15.5 ارائه شده و روش فعالسازی آن با نگارش 7.1 آن یکی است (انتخاب گزینه‌ی «C# latest minor version (latest)» در تنظیمات پیشرفته‌ی Build خواص پروژه). همچنین اگر از VSCode استفاده می‌کنید، نگارش 1.14 افزونه‌ی #C آن، پشتیبانی کاملی را از C# 7.2 به همراه دارد؛ در اینجا، افزودن خاصیت <LangVersion>latest</LangVersion> به فایل csproj برنامه برای استفاده‌ی از آخرین نگارش کامپایلر نصب شده، کفایت می‌کند. البته باید دقت داشت کامپایلر C# 7.2 به همراه NET Core SDK 2.1.2. ارائه شده‌است. بنابراین تنها نصب آخرین نگارش افزونه‌ی #C مخصوص VSCode برای کامپایل آن کافی نیست و باید حداقل SDK یاد شده (یا نگارش جدیدتر آن) را هم نصب کنید.
 

نوع‌های جدید <Span<T و  <ReadOnlySpan<T در C# 7.2

نوع‌های جدید <Span<T و <ReadOnlySpan<T جهت ارائه‌ی ناحیه‌های اختیاری پیوسته‌ای از حافظه، شبیه به آرایه‌ها تدارک دیده شده‌اند و هدف استفاده‌ی از آن‌ها، تولید برنامه‌های سمت سرور با کارآیی بالا است.
برای کار با این نوع‌ها، هم نیاز به کامپایلر C# 7.2 است و هم نصب بسته‌ی نیوگت System.Memory:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.Memory" Version="4.4.0-preview1-25305-02" />
  </ItemGroup>
</Project>
این بسته از .NETStandard 1.0. به بعد را پشتیبانی می‌کند؛ یعنی با +NET 4.5+ ،Mono 4.6.  و +NET Core 1.0. سازگار است.


Spanها و امکان دسترسی به انواع حافظه

Spanها می‌توانند به حافظه‌ی مدیریت شده، حافظه‌ی بومی (native) و حافظه‌ی اختصاص داده شده‌ی در Stack اشاره کنند. به عبارتی Spanها یک لایه انتزاعی، برفراز تمام انواع و اقسام حافظه‌هایی هستند که می‌توانند در اختیار توسعه دهندگان NET. باشند.
- البته اکثر توسعه دهندگان دات نت از حافظه‌ی مدیریت شده استفاده می‌کنند. برای مثال Stack memory تنها از طریق کدهای unsafe و واژه‌ی کلیدی stackalloc قابل تخصیص است. این نوع حافظه بسیار سریع است و همچنین بسیار کوچک؛ کمتر از یک مگابایت که به خوبی در CPU cache جا می‌شود. اما اگر در این بین حجم حافظه‌ی تخصیصی بیشتر از یک مگابایت شود، بلافاصله استثنای StackOverflowException غیرقابل مدیریتی را به همراه خاتمه‌ی فوری برنامه به همراه خواهد داشت. برای نمونه از این نوع حافظه در جهت مدیریت رخ‌دادهای داخلی corefx زیاد استفاده می‌شود.
- حافظه‌ی مدیریت شده، همان حافظه‌ای است که توسط واژه‌ی کلیدی new در برنامه، جهت ایجاد اشیاء، تخصیص داده می‌شود و طول عمر آن تحت مدیریت GC است.
- حافظه‌ی مدیریت نشده یا بومی از دید GC مخفی است و توسط متدهایی مانند Marshal.AllocHGlobal و Marshal.AllocCoTaskMem در اختیار برنامه قرار می‌گیرند. این حافظه باید به صورت صریحی توسط توسعه دهنده به کمک متدهایی مانند Marshal.FreeHGlobal و Marshal.FreeCoTaskMem آزاد شود. وب سرور Kestrel مخصوص ASP.NET Core، از این روش جهت کار با آرایه‌های حجیم، جهت کاهش بار GC استفاده می‌کند.

مزیت کار با Spanها این است که دسترسی امن و type safeایی را به انواع حافظه‌های مهیا، جهت توسعه دهندگانی که عموما کدهای unsafe ایی را نمی‌نویسند و با اشاره‌گرها به صورت مستقیم کار نمی‌کنند، میسر می‌کند. برای مثال تا پیش از معرفی Spanها، برای دسترسی به 1000 عنصر یک آرایه‌ی 10 هزار عنصری و ارسال آن به یک متد، نیاز بود تا ابتدا یک کپی از این 1000 عنصر را تهیه کرد. این عملیات از لحاظ میزان مصرف حافظه و همچنین زمان انجام آن، بسیار هزینه‌بر است. با استفاده از <Span<T می‌توان یک دید مجازی از آن آرایه را بدون اختصاص آرایه‌ای و یا آرایه‌هایی جدید، ارائه کرد.


مثالی از کاربرد Spanها جهت کاهش تعداد بار تخصیص‌های حافظه

برای نمونه، متد IsValidName زیر، بررسی می‌کند که طول رشته‌ی دریافتی حداقل 2 باشد و حتما با یک حرف شروع شده باشد:
    static class NameValidatorUsingString
    {
        public static bool IsValidName(string name)
        {
            if (name.Length < 2)
                return false;

            if (char.IsLetter(name[0]))
                return true;

            return false;
        }
    }
در این حالت یک نمونه مثال از استفاده‌ی آن می‌تواند به صورت زیر باشد:
string fullName = "User 1";
string firstName = fullName.Substring(0, 4);
NameValidatorUsingString.IsValidName(firstName);
در اینجا زمانیکه از متد Substring استفاده می‌شود، در حقیقت تخصیص حافظه‌ی دومی جهت تولید firstName رخ می‌دهد.

همچنین اگر این اطلاعات را از طریق شبکه دریافت کرده باشیم، ممکن است به صورت آرایه‌ای از حروف دریافت شوند:
char[] anotherFullName = { 'A', 'B' };
که به صورت مستقیم در متد IsValidName قابل استفاده نیست و خطای عدم امکان تبدیل []char به string، از طرف کامپایلر صادر می‌شود:
NameValidatorUsingString.IsValidName(anotherFullName);
در این حالت برای استفاده‌ی از این آرایه، نیاز است یک تخصیص حافظه‌ی دیگر نیز صورت گیرد:
NameValidatorUsingString.IsValidName(new string(anotherFullName));

اکنون در C# 7.2، بازنویسی این متد توسط ReadOnlySpan، به صورت ذیل است:
    static class NameValidatorUsingSpan
    {
        public static bool IsValidName(ReadOnlySpan<char> name)
        {
            if (name.Length < 2)
                return false;

            if (char.IsLetter(name[0]))
                return true;

            return false;

        }
    }
که این مزایا را به همراه دارد:
ReadOnlySpan<char> fullName = "User 1".AsSpan();
ReadOnlySpan<char> firstName = fullName.Slice(0, 4);
NameValidatorUsingSpan.IsValidName(firstName);
کار با API مربوط به Spanها به همراه تخصیص حافظه‌ی جدیدی نیست. برای نمونه در اینجا متد Slice این API، سبب تخصیص حافظه‌ی جدیدی نمی‌شود (برخلاف متد Substring) و فقط به قسمتی از حافظه‌ی موجود اشاره می‌کند (بدون نیاز به کار مستقیم با اشاره‌گرها و کدهای unsafe).

و یا اینبار امکان استفاده‌ی از آرایه‌ای از کاراکترها، بدون نیاز به تخصیص حافظه‌ای جدید، برای بررسی اعتبار مقادیر دریافتی میسر است:
char[] anotherFullName = { 'A', 'B' };
NameValidatorUsingSpan.IsValidName(anotherFullName);

برای نمونه از یک چنین APIایی در پشت صحنه‌ی کتابخانه‌هایی مانند SignalR و یا Roslyn، برای بالا بردن کارآیی برنامه، با کاهش تعداد بار تخصیص‌های حافظه‌ی مورد نیاز، بسیار استفاده شده‌است. برای نمونه در NET Core 2.1.، حجم رشته‌های تخصیص داده شده‌ی در فریم ورک‌های وابسته، به این ترتیب به شدت کاهش یافته‌است.


مثال‌هایی از کار با API نوع Span

امکان ایجاد یک Span از یک array
var arr = new byte[10];
Span<byte> bytes = arr; // Implicit cast from T[] to Span<T>
پس از آن کار با این span همانند کار با آرایه‌های معمولی است؛ با این تفاوت که این span تنها یک دید مجازی از قسمتی از این آرایه را ارائه می‌دهد؛ بدون سربار تخصیص حافظه‌ی اضافی و کپی اطلاعات:
Span<byte> slicedBytes = bytes.Slice(start: 5, length: 2);
slicedBytes[0] = 42;
slicedBytes[1] = 43;
slicedBytes[2] = 44; // Throws IndexOutOfRangeException
bytes[2] = 45; // OK
در اینجا slicedBytes یک دید مجازی از ایندکس 5 تا 7 آرایه‌ی arr را ارائه می‌دهد. کار کردن با آن نیز همانند آرایه‌ها، توسط ایندکس‌ها میسر است.
همچنین تغییرات بر روی Span (غیر read only) بر روی آرایه‌ی اصلی نیز تاثیر گذار است. برای مثال در اینجا با تغییر bytes[2]، مقدار arr[2] نیز تغییر می‌کند.

و یا روش دیگر ایجاد Span استفاده از متد AsSpan است:
var array = new byte[100];
Span<byte> interiorRef1 = array.AsSpan().Slice(start: 20);
همین عملیات را توسط new Span نیز می‌توان به صورت ساده‌تری ارائه داد:
Span<byte> interiorRef2 = new Span<byte>(array: array, start: 20, length: array.Length - 20);


محدودیت‌های کار با Spanها

- Span تنها یک نوع stack-only است.
- Spanها در بین تردها به اشتراک گذاشته نمی‌شوند. هر استک در یک زمان تنها توسط یک ترد قابل دسترسی است. بنابراین Spanها thread-safe هستند.
- طول عمر Spanها کوتاه است و قابلیت قرارگیری بر روی heap با طول عمر بیشتر را ندارند؛ یعنی:
  • به صورت فیلد در یک نوع non-stackonly قابل تعریف نیستند:
class Impossible
{
   Span<byte> field;
}
فیلدهای یک کلاس در heap ذخیره می‌شوند. بنابراین محل ذخیره سازی spanها نیستند.
  • به عنوان پارامترهای متدهای async قابل استفاده نیستند. چون در این بین در پشت صحنه یک AsyncMethodBuilder تشکیل می‌شود که در قسمتی از آن، پارامترها بر روی heap قرار می‌گیرند.
  • هرجائیکه عملیات boxing صورت گیرد، نتیجه‌ی عملیات بر روی heap قرار می‌گیرد. بنابراین در یک چنین مواردی نمی‌توان از Spanها استفاده کرد. برای مثال تعریف Func<T> valueProvider و سپس فراخوانی ()valueProvider.Invoke به همراه یک boxing است. بنابراین نمی‌توان از spanها به عنوان نوع آرگومان جنریک استفاده کرد. این مورد هرچند کامپایل می‌شود، اما در زمان اجرا سبب خاتمه‌ی برنامه خواهد شد و یا نمونه‌ی دیگر، عدم امکان دسترسی به آن‌ها توسط reflection invoke APIs است که سبب boxing می‌شود.


معرفی نوع <Memory<T

با توجه به محدودیت‌های Span و خصوصا اینکه به عنوان پارامتر متدهای async قابل استفاده نیست (چون بر روی stack ذخیره می‌شوند)، نوع دیگری به نام <Memory<T نیز به همراه C# 7.2 ارائه شده‌است. البته این نوع هنوز به بسته‌ی نیوگت فوق اضافه نشده‌است و به همراه ارائه نهایی NET Core 2.1. ارائه خواهد شد.
این نوع، محدودیت <Span<T را نداشته و قابلیت ذخیره سازی بر روی heap را دارا است.
static async Task<int> ChecksumReadAsync(Memory<byte> buffer, Stream stream)
{
   int bytesRead = await stream.ReadAsync(buffer);
   return Checksum(buffer.Span.Slice(0, bytesRead));
   // Or buffer.Slice(0, bytesRead).Span
}
در اینجا نیز می‌توان از یک آرایه، یک <Memory<T را ایجاد و سپس یک <Span<T را از آن دریافت و با Sliceهای آن کار کرد.
مطالب
ساخت ربات تلگرامی با #C
 با رشد دنیای تکنولوژی، وسائل هوشمند همراه نیز به سرعت پیشرفته‌تر شدند. در این میان با گسترش زیرساخت اینترنت، رشد شبکه‌های اجتماعی نیز چشمگیر بوده است. یکی از بهترین این‌ها، شبکه‌های تلگرام می‌باشد که با بهره گیری از سرورهای ابری، امنیت و سرعت را برای کاربران به ارمغان آورده است.
چندی پیش موسسان تلگرام با معرفی API‌های کاربردی، به توسعه کنندگان اجازه دادند که با بهره گیری از بستر این شبکه، اقدام به تولید اینترفیسی به اسم بات کنند که با دریافت دستورات سفارشی، عملیات خاصی را انجام دهد.
در واقع تلگرام و متدهای ارائه شده، یک راه ارتباطی بین کاربران و برنامه‌های تولید شده را ایجاد کردند که با قدری ذوق و سلیقه، شاهد بات‌های جالب و کاربردی هستیم.
در این مقاله سعی شده طرز تهیه یک بات با زبان #C توضیح داده شود.
در ابتدا شما باید توسط یکی از بات‌های اصلی تلگرام اقدام به ثبت نام کاربری و تنظیمات بات مورد نظر خودتان نمایید. بات مورد نظر @BotFather می‌باشد که با شروع مکالمه می‌توان با فرستادن دستورات مختلف تنظیمات مختلفی را انجام داد. با شروع مکالمه با بات مورد نظر با دستور /start دستورات زیر قابل انجام می‌باشد:

 You can control me by sending these commands :

/ newbot - create a new bot

/ token - generate authorization token

/ revoke - revoke bot access token

/ setname - change a bot's name

/ setdescription - change bot description

/ setabouttext - change bot about info

/ setuserpic - change bot profile photo

/ setcommands - change bot commands list

/ setjoingroups - can your bot be added to groups ?

/ setprivacy - what messages does your bot see in groups ?

/ deletebot - delete a bot

/ cancel - cancel the current operation
با انجام دستور /newbot در ابتدا نام بات و یوزنیم (دقت کنید یوزرنیم می‌بایست حتما به کلمه‌ی bot ختم شود) را تنظیم کنید.
بعد از تایید نام و یوزر نیم، به شما یک توکن اختصاص داده می‌شود که توسط آن شما شناسایی می‌شوید.
در اینجا شما می‌توانید تنظیمات اضافه‌تری مانند عکس برای پروفایل و غیره را نیز تنظیم کنید.
در مرحله‌ی بعد می‌توانید در همین قسمت دستورات مورد نظر را جهت بات خود تنظیم کنید. برای این کار باید دستور /setcommands را وارد کنید و دستور مورد نظر خود را به فرمت command1 – Description وارد کنید.
مرحله‌ی بعد، تنظیمات برنامه‌ی شما جهت دریافت دستورات وارد شده و انجام عملیات مورد نظر و تولید و ارسال خروجی مورد نظر است.

دریافت دستورات به دو طریق انجام می‌شود:
1. توسط دستور getUpdates می‌توان تمامی کامندهای دریافتی را از سرور تلگرام دریافت کرد و با انجام پروسس‌های لازم، خروجی را به کاربر مورد نظر ارسال کرد.
2. توسط تابع webhook از تلگرام درخواست کرد در صورت دریافت دستور جدید به بات، این دستور را به یک آدرس خاص ارسال کرد.

قابل توجه است که می‌توان فقط از یکی از دو روش فوق استفاده کرد. همچنین در روش دوم حتما سرور مورد نظر باید گواهی ssl تایید شده داشته باشد.
کد زیر دریافت کامندهای یک بات به روش اول می‌باشد :
public class mydata
    {
        public result[] result;
    }
    public class result
    {
        public int update_id { get; set; }
        public message message { get; set; }
    }
    public class message
    {
        public int message_id { get; set; }
        public message_from from { get; set; }
        public message_chat chat { get; set; }
        public int date { get; set; }
        public string text { get; set; }
    }
    public class message_from
    {
        public int ind { get; set; }
        public string first_name { get; set; }
        public string username { get; set; }
    }
    public class message_chat
    {
        public int id { get; set; }
        public string first_name { get; set; }
        public string username { get; set; }
    }
 
public  Void GetUpdates()
        {
 
            WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + yourToken + "/getUpdates");
            req.UseDefaultCredentials = true;
            WebResponse resp = req.GetResponse();
            Stream stream = resp.GetResponseStream();
            StreamReader sr = new StreamReader(stream);
            string s = sr.ReadToEnd();
            sr.Close();
            var jobject = Newtonsoft.Json.Linq.JObject.Parse(s);
            mydata gg = JsonConvert.DeserializeObject<mydata>(jobject.ToString());
            List<result> results = new List<result>();
            foreach (result rs in gg.result)
            {
                results.Add(rs); 
                SendMessage(rs.message.chat.id.ToString(), "hello"+" "+"Dear"+rs.message.chat.first_name); 
            }             
        }
و توسط تابع زیر می‌توان به کاربری که به بات کامند ارسال کرد، پاسخ داد:
public static void SendMessage(string chat_id, string message)
        {
            WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + youToken + "/sendMessage?chat_id=" + chat_id + "&text=" + message);
            req.UseDefaultCredentials = true;
 
            var result = req.GetResponse();
            req.Abort();
        }

لازم به ذکر است خروجی توابع بات‌های تلگرام با فرمت JSON می‌باشد که با نصب پکیج NewTonsoft می‌توان آن را به لیست تبدیل کرد.
rs.message.chat.id، آی دی فردی است که به بات تلگرامی ما مسیج ارسال کرده است.
rs.message.chat.first_name نام فردی است که به بات تلگرام مسیج ارسال کرده است.
همچنین می‌توان در جواب کامند بات، علاوه بر متن، صدا و تصویر را نیز ارسال نمود .

در این لینک و این لینک می‌توان توضیحات بیشتری را در این زمینه مطالعه کرد.
در انتها خوشحال می‌شوم ذوق‌ها و ایده‌های شما را در ساخت بات‌ها با آیدی @iekhtiari مشاهده کنم.
نظرات اشتراک‌ها
رایگان شدن بیش از ۷۰۰۰ دوره سایت Pluralsight
 من هم با ارور Please complete the security check to access the site . If you continue to experience problems , let us know
مواجه شدم . 
در صورتی که توسط مرورگر یا خود برنامه وبسایت به دوره‌ها دسترسی دارم و لاگین میکنم ! در تنظیمات حساب کاربری وبسایت pluralsight هم موردی پیدا نکردم 
اگر امکانش هست دوستان بعضی از لینک‌های دانلود رو به اشتراک بذارن
ممنون

نظرات مطالب
اعتبارسنجی مبتنی بر JWT در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
خیر. شیء this.User با اطلاعات جدول کاربران، تناظر یک به یک ندارد. از نگارش‌های پیشین ASP.NET ، هنوز هم اطلاعات شیء User مانند User.Identity.Name در ASP.NET Core نیز در دسترس هستند. به این ترتیب زمانیکه کاربری به سیستم وارد شد، دیگر نیازی نیست تا جهت یافتن Name او، از بانک اطلاعاتی کوئری گرفت. خاصیت Name یاد شده به صورت خودکار از کوکی رمزنگاری شده‌ی و یا در اینجا از توکن او دریافت شده و در اختیار برنامه قرار می‌گیرد. این Name در ASP.NET Core Identity، اصطلاحا یک User Claim پیش‌فرض نام دارد و به صورت خودکار ایجاد و مقدار دهی می‌شود. روش مقدار دهی اولیه‌ی آن هم در متد createAccessTokenAsync مشخص است. هر زمانیکه این توکن به سمت سرور ارسال می‌شود، پس از اعتبارسنجی توکن و پذیرش آن، این Claims هم پردازش شده و جزئی از اطلاعات شیء this.User می‌شوند.
نظرات مطالب
سفارشی سازی ASP.NET Core Identity - قسمت اول - موجودیت‌های پایه و DbContext برنامه
باسلام؛ بنده از این سیستم برای طراحی یک سایت فروش استفاده میکنم، سناریو به این شکل می‌باشد که تنها مدیر سیستم میتواند کاربران جدیدی را به وجود بیاورد، بنده به دنبال ملغی کردن استفاده از ایمیل می‌باشم، با وجود حذف خاصیت ایمیل در register veiwmodel  و همچین حذف ستون ایمیل در بانک کاربران باز هم  خطای اعتبار سنجی وارد کردن ایمیل را دریافت میکنم، با دنبال کردن جریان برنامه به تابع base.CreateAsyc توکار می‌رسم که نام کاربری را به صورت آدرس ایمیل مورد بررسی قرار میدهد، حتی با تغییر مقدار return  در تابع IsEmailAddress باز هم با خطا مواجه می‌گردم. خواهش میکنم راهکاری ارائه نمایید که بدون دریافت ایمیل ادمین قادر به افزودن کاربر جدید باشد.
نظرات مطالب
بررسی خطاهای ممکن در حین راه اندازی اولیه برنامه‌های ASP.NET Core در IIS
حداقل دو دلیل را می‌تواند داشته باشد:
- کاربر application pool برنامه (و یا کاربری که توسط آن به بانک اطلاعاتی متصل می‌شوید)، دسترسی مناسبی را به SQL Server ندارد. در قسمت مدیریت کاربران SQL Server، این کاربر باید حداقل دسترسی‌های db_datareader و db_dataweriter را بر روی دیتابیس شما داشته باشد.
- کوئری‌های شما بر اساس اسکیمای dbo صادر می‌شوند، اما اسکیمای واقعی بانک اطلاعاتی موجود در هاست، برای کاربر شما مثلا user1 است و نه dbo مدیریتی. در این حالت نمی‌توانید کوئری‌هایی مانند select * from dbo.table1 را صادر کنید. باید کوئری‌های شما با اسکیمای جدید select * from user1.table1 اجرا شوند.
این موارد در نظرات سری EF Code First بررسی شده‌اند و در اینجا هم تفاوتی نمی‌کنند؛ چون موارد پایه‌ای مدیریت دسترسی‌های SQL Server هستند.