نظرات اشتراک‌ها
تنظیمات IIS برای توزیع فونت‌های وب
به نظر من توجه به  پاراگراف آخر و یکی مانده به آخر مهم است:
  • حجم فونت‌های WOFF2 از WOFF (نسخه اول)، 20 درصد کمتر است.
  • شاید مرورگر نتواند فونت‌های WOFF2 را بدلیل عدم نگاشت آنها در IIS دریافت نماید و از سایر فونت‌های تعریف شده استفاده نماید اما در هر درخواست ارسالی به سرور خطای 404  رخ می‌دهد که باعث اتلاف پهنای باند و رفت و برگشت‌های بیهوده به سرور می‌شود.
  • درخواست منابعی که با موفقیت انجام می‌شوند مرورگر از ارسال مجدد آنها خودداری می‌کند ولی درخواست‌های 404 سمت مرورگر کش نمی‌شوند و در هر درخواست ارسال می‌گردند، بنابراین جلوگیری از این اتفاق برای منابعی که در هر بارگذاری صفحه فراخوانی می‌شوند مانند favicon.ico الزامی است.
مطالب
دات نت 4 و کلاس Lazy

یکی از الگوهای برنامه نویسی شیء گرا، Lazy Initialization Pattern نام دارد که دات نت 4 پیاده سازی آن‌را سهولت بخشیده است.
در دات نت 4 کلاس جدیدی به فضای نام System اضافه شده است به نام Lazy و هدف از آن lazy initialization است؛ من ترجمه‌اش می‌کنم وهله سازی با تاخیر یا به آن on demand construction هم گفته‌اند (زمانی که به آن نیاز هست ساخته خواهد شد).
فرض کنید در برنامه‌ی خود نیاز به شیءایی دارید و ساخت این شیء بسیار پرهزینه است. نیازی نیست تا بلافاصله پس از تعریف، این شیء ساخته شود و تنها زمانیکه به آن نیاز است باید در دسترس باشد. کلاس Lazy جهت مدیریت اینگونه موارد ایجاد شده است. تنها کاری که در اینجا باید صورت گیرد، محصور کردن آن شیء هزینه‌بر توسط کلاس Lazy است:

Lazy<ExpensiveResource> ownedResource = new Lazy<ExpensiveResource>();

در این حالت برای دسترسی به شیء ساخته شده از ExpensiveResource ، می‌توان از خاصیت Value استفاده نمود (ownedResource.Value). تنها در حین اولین دسترسی به ownedResource.Value ، شیء ExpensiveResource ساخته خواهد شد و نه پیش از آن و نه در اولین جایی که تعریف شده است. پس از آن این حاصل cache شده و دیگر وهله سازی نخواهد شد.
ownedResource دارای خاصیت IsValueCreated نیز می‌باشد و جهت بررسی ایجاد آن شیء می‌تواند مورد استفاده قرار گیرد. برای مثال قصد داریم اطلاعات ExpensiveResource را ذخیره کنیم اما تنها در حالتیکه یکبار مورد استفاده قرار گرفته باشد.
کلاس Lazy دارای دو متد سازنده‌ی دیگر نیز می‌باشد:
public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory, bool isThreadSafe);

و هدف از آن استفاده‌ی صحیح از این متد در محیط‌های چند ریسمانی است. بدیهی است در این نوع محیط‌ ها علاقه‌ای نداریم که در یک لحظه توسط چندین ترد مختلف، سبب ایجاد وهله‌های ناخواسته‌ا‌ی از ExpensiveResource شویم و تنها یک مورد از آن کافی است یا به قولی thread safe, lazy initialization of expensive objects
بدیهی است اگر برنامه‌ی شما چند ریسمانی نیست می‌توانید این مکانیزم را کنسل کرده و اندکی کارآیی برنامه را با حذف قفل‌های همزمانی این کلاس بالا ببرید.

مثال اول:

using System;
using System.Threading;

namespace LazyExample
{
class Program
{
static void Main()
{
Console.WriteLine("Before assignment");
var slow = new Lazy<Slow>();
Console.WriteLine("After assignment");

Thread.Sleep(1000);

Console.WriteLine(slow);
Console.WriteLine(slow.Value);

Console.WriteLine("Press a key...");
Console.Read();
}
}


class Slow
{
public Slow()
{
Console.WriteLine("Start creation");
Thread.Sleep(2000);
Console.WriteLine("End creation");
}
}
}
خروجی این برنامه به شرح زیر است:

Before assignment
After assignment
Value is not created.
Start creation
End creation
LazyExample.Slow
Press a key...

همانطور که ملاحظه می‌کنید تنها در حالت دسترسی به مقدار Value شیء slow ، عملا وهله‌ای از آن ساخته خواهد شد.

مثال دوم:
شاید نیاز به مقدار دهی خواص کلاس پرهزینه‌ وجود داشته باشد. برای مثال علاقمندیم خاصیت SomeProperty کلاس ExpensiveClass را مقدار دهی کنیم. برای این منظور می‌توان به شکل ذیل عمل کرد (یک Func<t>را می‌توان به سازنده‌ی آن ارسال نمود):

using System;

namespace LazySample
{
class Program
{
static void Main()
{
var expensiveClass =
new Lazy<ExpensiveClass>
(
() =>
{
var fobj = new ExpensiveClass
{
SomeProperty = 100
};
return fobj;
}
);

Console.WriteLine("expensiveClass has value yet {0}",
expensiveClass.IsValueCreated);

Console.WriteLine("expensiveClass.SomeProperty value {0}",
(expensiveClass.Value).SomeProperty);

Console.WriteLine("expensiveClass has value yet {0}",
expensiveClass.IsValueCreated);

Console.WriteLine("Press a key...");
Console.Read();
}
}

class ExpensiveClass
{
public int SomeProperty { get; set; }

public ExpensiveClass()
{
Console.WriteLine("ExpensiveClass constructed");
}
}
}

کاربردها:
- علاقمندیم تا ایجاد یک شیء هزینه‌بر تنها پس از انجام یک سری امور هزینه‌بر دیگر صورت گیرد. برای مثال آیا تابحال شده است که با یک سیستم ماتریسی کار کنید و نیاز به چند گیگ حافظه برای پردازش آن داشته باشید؟! زمانیکه از کلاس Lazy استفاده نمائید، تمام اشیاء مورد استفاده به یکباره تخصیص حافظه پیدا نکرده و تنها در زمان استفاده از آن‌ها کار تخصیص منابع صورت خواهد گرفت.
- ایجاد یک شیء بسیار پر هزینه بوده و ممکن است در بسیاری از موارد اصلا نیازی به ایجاد و یا حتی استفاده از آن نباشد. برای مثال یک شیء کارمند را درنظر بگیرید که یکی از خواص این شیء، لیستی از مکان‌هایی است که این شخص قبلا در آنجاها کار کرده است. این اطلاعات نیز به طور کامل از بانک اطلاعاتی دریافت می‌شود. اگر در متدی، استفاده کننده از شیء کارمند هیچگاه اطلاعات مکان‌های کاری قبلی او را مورد استفاده قرار ندهد، آیا واقعا نیاز است که این اطلاعات به ازای هر بار ساخت وهله‌ای از شیء کارمند از دیتابیس دریافت شده و همچنین در حافظه ذخیره شود؟

نظرات مطالب
بررسی علت CPU Usage بالای برنامه در حال اجرا
با سلام خدمت آقای نصیری
چند وقتی است روی یکی از سرورهی ما مش out of memory به وجود آمده
مشخصات سرور ویندوز 2003 سی دو بیتی رم بالای 4 گیگابایت که با سویچ /PAE در فایل بوت ... این حافظه به ویندوز معرفی شده در
ضمن اینکه Lock Page in memory برای یوزری که سرویس IIS را Start کرده تنظیم شده در این حالت باز ما خطا را میگیرم
چیزی که به ذخن من میرسه ما در برنامه از کریستال ریپورت استفاده کردیم که داخل اون یک library ار نوع com وجود داره که کار
تبدیل تاریخ میلادی به شمسی رو انجام میده فکر میکنم به خاطر اینکه این کتابخانه به شکل unmanage code است
سوالی که دارم اینه
 چه طور می توانم مطمئن بشم مشکل از این کتابخانه است و یا خیر

لازم میدونم اشاره کنم تعداد کاربرای سایت بالا و همچنین این سرور مختص iis  است و به هیچ عنوان SQL روی اون نصب نمی باشد
مطالب
آموزش Prism #3
در پست‌های قبلی با Prism و روش استفاده از آن آشنا شدیم (قسمت اول) و (قسمت دوم). در این پست با استفاده از Mef قصد ایجاد یک پروژه Silverlight رو به صورت ماژولار داریم. مثال پیاده سازی شده در پست قبلی را در این پست به صورت دیگر پیاده سازی خواهیم کرد.
تفاوت‌های پیاده سازی مثال پست قبلی با این پست:
  • در مثال قبل پروژه به صورت Desktop و با WPF پیاده سازی شده بود ولی در این مثال با Silverlight می‌باشد؛
  • در مثال قبل از UnityBootstrapper استفاده شده بود ولی در این مثال از MefBootstrapper؛
  • در مثال قبل هر View در یک ماژول قرار داشت ولی در این مثال هر دو View را در یک ماژول قرار دادم؛
  • در مثال قبل از Prism Libary 2.x استفاده شده بود ولی در این مثال از PrismLibrary 4.x؛
  • و...

نکته : برای فهم بهتر مفاهیم، آشنایی اولیه با MEF و مفاهیمی نظیر Export و Import و AggregateCatalog و AssemblyCatalog نیاز است. در صورتی که با این مطالب آشنایی ندارید می‌توانید از (^) شروع کنید.


برای شروع یک پروژه Silverlight ایجاد کنید. بعد از اضافه شدن دو پروژه Silverlight و Web، یک Silverlight Class Library جدید بسازید.
ابتدا یک Page ایجاد کنید و کد‌های زیر را در آن کپی کنید.
<UserControl 
             x:Class="Module1.Module1View1"
             xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" FlowDirection="RightToLeft" FontFamily="Tahoma">
    <StackPanel>
        <sdk:DataGrid Height="100">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Header="کد" Width="50"  />
                <sdk:DataGridTextColumn Header="عنوان" Width="200" />
                <sdk:DataGridTextColumn Header="نویسنده" Width="150"  />
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
        <Button x:Name="NextViewButton"
                Width="150"
                Height="25"
                Foreground="Red"
                Background="Blue"
                Content="لیست طبقه بندی ها" />
    </StackPanel>
</UserControl>
بر روی Page مربوطه راست کلیک کنید و گزینه ViewCode را انتخاب کنید و کد‌های زیر را در آن کپی کنید.
 [Export(typeof(Module1View1))]
    public partial class Module1View1 : UserControl
    {
        [Import]
        public IRegionManager TheRegionManager { private get; set; }

        public Module1View1()
        {
            InitializeComponent();

            NextViewButton.Click += NextViewButton_Click;
        }

        void NextViewButton_Click(object sender, RoutedEventArgs e)
        {
            TheRegionManager.RequestNavigate
            (
                "MyRegion1",
                new Uri("Module1View2", UriKind.Relative),
                a => { }
            );
        }
    }
ابتدا خود این View باید حتما Export شود. در رویداد کلیک با استفاده از متد RequestNavigate می‌توانیم به View مورد نظر برای نمایش در Shell اشاره کنیم و این View در Region نمایش داده می‌شود. به دلیل اینکه در این کلاس به RegionManager نیاز داریم از ImportAttribute استفاده کردیم. این بدین معنی است که کلاس Module1View1 وابستگی مستقیم به IRegionManager دارد.

حال یک Page دیگر برای طبقه بندی کتاب‌ها ایجاد کنید و کدهای زیر را در آن کپی کنید.
<UserControl 
             xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"  x:Class="Module1.Module1View2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" FlowDirection="RightToLeft" FontFamily="Tahoma">
    <StackPanel>
        <sdk:DataGrid Height="100">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Header="کد" Width="150"/>
                <sdk:DataGridTextColumn Header="عنوان" Width="150"/>                
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
        <Button x:Name="NextViewButton"
                Width="150"
                Height="25"
                Foreground="Green"
                Background="Yellow"
                Content="لیست کتاب ها" />
    </StackPanel>
</UserControl>
در Code Behind این Page نیز کد‌های زیر را قرار دهید.
using Microsoft.Practices.Prism.Regions;
using System;
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Controls;

namespace Module1
{
    [Export]
    public partial class Module1View2 : UserControl
    {
        IRegion _region1;

        [ImportingConstructor]
        public Module1View2( [Import] IRegionManager regionManager )
        {
            InitializeComponent();
         
            ViewModel viewModel = new ViewModel();
            DataContext = viewModel;

            viewModel.ShouldNavigateFromCurrentViewEvent += () => { return true; };

            _region1 = regionManager.Regions["MyRegion1"];

            NextViewButton.Click += NextViewButton_Click;
        }

        void NextViewButton_Click( object sender, RoutedEventArgs e )
        {
            _region1.RequestNavigate
            (
                new Uri( "Module1View1", UriKind.Relative ),
                a => { }
            );
        }
    }
}
در این ماژول برای اینکه بتوانیم حالت گردشی در فراخوانی ماژول‌ها را داشته باشیم ابتدا DataContext این کلاس را برابر با ViewModel ساخته شده قرار دادیم. با استفاده از رویداد ShoudlNavigateFromCurrentViewEvent که در کلاس ViewModel وجود دارد تعیین می‌کنیم که آیا باید از این View به View قبلی برگشت داشته باشیم یا نه. در صورتی که مقدار false برگشت داده شود خواهید دید که امکان فراخوانی View1 از View2 امکان پذیر نیست. در رویداد کلیک نیز همانند Page قبلی با استفاده از RegionManager و متد RequestNavigate به View مورد نظر راهبری کرده ایم.
نکته: اگر یک کلاس، سازنده با پارامتر داشته باشد باید با استفاده از ImportingConstructor حتما سازنده مورد نظر را هنگام وهله سازی مشخص کنیم در غیر این صورت با Exception مواجه خواهید شد.
حال قصد ایجاد کلاس ViewModel بالا را داریم:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using Microsoft.Practices.Prism.Regions;

namespace Module1
{
    public class ViewModel : IConfirmNavigationRequest
    {       
        public event Func<bool> ShouldNavigateFromCurrentViewEvent;      

        public bool IsNavigationTarget( NavigationContext navigationContext )
        {
            return true;
        }

        public void OnNavigatedTo( NavigationContext navigationContext )
        {

        }

        public void OnNavigatedFrom( NavigationContext navigationContext )
        {

        }         

        public void ConfirmNavigationRequest( NavigationContext navigationContext, Action<bool> continuationCallback )
        {
            bool shouldNavigateFromCurrentViewFlag = false;

            if ( ShouldNavigateFromCurrentViewEvent != null )
                shouldNavigateFromCurrentViewFlag = ShouldNavigateFromCurrentViewEvent();

            continuationCallback( shouldNavigateFromCurrentViewFlag );
        }    
    }
}
توضیح متد‌های بالا:
  • IsNavigateTarget : برای تعیین اینکه آیا کلاس پیاده سازی کننده اینترفیس، می‌تواند عملیات راهبری را مدیریت کند یا نه.
  • OnNavigateTo : زمانی عملیات راهبری وارد View شود(بهتره بگم View مورد نظر در Region صفحه لود شود) این متد فراخوانی می‌شود.
  • OnNavigateFrom : زمانی که راهبری از این View خارج می‌شود (View از حالت لود خارج می‌شود) این متد فراخوانی خواهد شد.
  • ConfirmNavigationRequest : برای تایید عملیات راهبری توسط کلاس پیاده سازی کننده اینترفیس استفاده می‌شود. 
حال یک کلاس برای پیاده سازی و مدیریت ماژول می‌سازیم.
using Microsoft.Practices.Prism.MefExtensions.Modularity;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.Regions;
using System.ComponentModel.Composition;

namespace Module1
{
    [ModuleExport(typeof(Module1Impl))]
    public class Module1Impl : IModule
    {       
        [Import]
        public IRegionManager TheRegionManager { private get; set; }     

        public void Initialize()
        {
            TheRegionManager.RegisterViewWithRegion("MyRegion1", typeof(Module1View1));

            TheRegionManager.RegisterViewWithRegion("MyRegion1", typeof(Module1View2));
        }
    }
}
همان طور که مشاهده می‌کنید از ModuleExportAttribute برای شناسایی ماژول توسط MefBootstrapper استفاده کردیم و نوع آن را Module1Imp1 قرار دادیم.  ImportAttribute استفاده شده در این کلاس و خاصیت TheRegionManager برای این است که در هنگام ساخت Instance از این کلاس IRegionManager موجود در Container باید در اختیار این کلاس قرار گیرد(نشان دهنده وابستگی مستقیم این کلاس با IRegionManager است). روش دیگر این است که در سازنده این کلاس هم این اینترفیس را تزریق کنیم.
در متد Initialize برای RegionManager دو View ساخته شده را رجیستر کردیم. این کار باید به تعداد View‌های موجود در ماژول انجام شود.
Shell
در پروژه اصلی بک Page به نام Shell ایجاد کنید و کد‌های زیر را در آن کپی کنید.
<UserControl x:Class="NavigationViaViewModel.Shell"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://www.codeplex.com/prism" FlowDirection="RightToLeft" FontFamily="Tahoma">

    <Grid x:Name="LayoutRoot"
          Background="White">
        <TextBlock Text="لیست کتاب‌ها به همراه طبقه بندی آن ها"
                   FontSize="19"
                   Foreground="Black"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Top" />
        <ContentControl HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        prism:RegionManager.RegionName="MyRegion1" />
    </Grid>
</UserControl>
همانند مثال قبلی یک ContentControl داریم و به وسیله RegionName که یک AttachedProperty است یک Region به نام MyRegion1 ایجاد کردیم. تمام ماژول‌های این مثال در این محدوده نمایش داده خواهند شد.
Bootstrapper
حال نیاز به یک Bootstrapper داریم. برای این کار یک کلاس به نام TheBootstrapper بسازید:
using Microsoft.Practices.Prism.MefExtensions;
using Microsoft.Practices.Prism.Modularity;
using System.ComponentModel.Composition.Hosting;
using System.Windows;

namespace NavigationViaViewModel
{
    public class TheBootstrapper : MefBootstrapper
    {
        protected override void InitializeShell()
        {
            base.InitializeShell();

            Application.Current.RootVisual = (UIElement)Shell;
        }

        protected override DependencyObject CreateShell()
        {
            return Container.GetExportedValue<Shell>();
        }

        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();        
            AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
        }

        protected override IModuleCatalog CreateModuleCatalog()
        {
            ModuleCatalog moduleCatalog = new ModuleCatalog();
    
            moduleCatalog.AddModule
            (
                new ModuleInfo
                {
                    InitializationMode = InitializationMode.WhenAvailable,
                    Ref = "Module1.xap",
                    ModuleName = "Module1Impl",
                    ModuleType = "Module1.Module1Impl, Module1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                }
            );

            return moduleCatalog;
        }
    }
}
متد CreateShell اولین متد در این کلاس است که اجرا خواهد شد. بعد از متد CreateShell، متد InitializeShell اجرا خواهد شد. خاصیت Shell دقیقا به مقدار برگشتی متد CreateShell اشاره خواهد کرد. در متد InitializeShell  مقدار خاصیت Shell به RootVisual این پروژه اشاره می‌کند(مانند MainWindow در کلاس Application پروژه‌های WPF).
متد ConfigureAggregateCatalog برای مدیریت کاتالوگ‌ها و ماژول‌ها که هر کدام در یک اسمبلی جدا وجود خواهند شد استفاده می‌شود. در این متد من از AssemblyCatalog استفاده کردم. AssemblyCatalog  تمام کلاس هایی که ExportAttribute را به همراه دارند شناسایی می‌کند و آن‌ها را در Container نگهداری خواهد کرد(^). مانند یک ServiceLocator در Microsoft unity Service Locator(^) .
متد آخر به نام CreateModuleCatalog است و باید در آن تمام ماژول‌های برنامه را به کلاس ModuleCatalog اضافه کنیم. در مثال پست قبلی به دلیل استفاده از UnityBootstrapper باید این کار را از طریق BuildEvent ‌ها مدیریت می‌کردیم ولی در این جا Mef به راحتی این کار را انجام خواهد داد.
تغییرات زیر را در فایل App.Xaml قرار دهید و پروژه را اجرا کنید.
public partial class App : Application
 {
        public App()
        {
            this.Startup += this.Application_Startup;                 
            InitializeComponent();
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
           var bootstrapper = new TheBootstrapper();
            bootstrapper.Run(); 
        }
}
با کلیک بر روی ماژول عملیات راهبری برای ماژول انجام خواهد شد.

دریافت سورس پروژه
ادامه دارد..
مطالب
خلاصه‌ای از روش‌های ارسال داده‌های سمت سرور به کدهای جاوا اسکریپتی در ASP.NET MVC
روش‌های زیادی برای ارسال داده‌های سمت سرور تهیه شده در یک برنامه‌ی ASP.NET به کدهای سمت کاربر JavaScript ایی وجود دارند که تعدادی از مهم‌ترین‌های آن‌ها را در این مطلب بررسی خواهیم کرد.

روش اول: دریافت اطلاعات سمت سرور به کمک درخواست‌های Ajax

استفاده از Ajax یکی از روش‌های کلاسیک دریافت اطلاعات سمت سرور در کدهای جاوا اسکریپتی است.
<script type="text/javascript">
var products = [];
$(function() {
    $.getJSON("/home/products", function(response) {
        products = response.products;
    });
});
</script>
برای نمونه در اینجا با استفاده از امکانات jQuery، درخواست Ajax ایی به سرور ارسال شده و سپس نتیجه‌ی دریافتی، به آرایه‌ی جاوا اسکریپتی products نسبت داده شده‌است.
- مزایا: استفاده از Ajax، روشی بسیار متداول و شناخته شده‌است و به کمک انواع و اقسام روش‌های بازگشت JSON از سرور، می‌توان با آن کار کرد.
- معایب: درخواست Ajax، صرفا پس از بارگذاری اولیه‌ی صفحه به سمت سرور ارسال خواهد شد و در این بین، کاربر وقفه‌ای را مشاهده خواهد کرد. همچنین در اینجا بجای یک درخواست از سرور، حداقل دو درخواست باید ارسال شوند؛ یکی برای بارگذاری صفحه‌ی اصلی و دیگری برای دریافت اطلاعات Ajax ایی از سرور به صورت غیرهمزمان.


روش دوم: دریافت اطلاعات از یک فایل جاوا اسکریپتی خارجی

اطلاعات سمت کاربر را از یک فایل جاوا اسکریپتی خارجی الحاق شده‌ی به صفحه‌ی جاری نیز می‌توان تهیه کرد:
 <script src="/file.js"></script>
یک چنین فایلی را می‌توان توسط کدهای سمت سرور نیز بازگشت داد و اطلاعات آن‌را تهیه و پر کرد. در این حالت فقط کافی است که ContentType شیء Response را از نوع application/javascript مشخص کنیم و سپس یک خروجی متنی جاوا اسکریپتی را از سمت سرور بازگشت دهیم.
این روش نیز تقریبا مانند حالت یک درخواست Ajax ایی کار می‌کند و اطلاعات مورد نیاز را در طی یک درخواست جداگانه، پس از بارگذاری صفحه‌ی اصلی، از سرور دریافت خواهد کرد. البته در حالت کار با Ajax، می‌توان در طی یک callback، نتیجه را دریافت کرد و سپس عکس العمل نشان داد؛ اما در اینجا callback ایی وجود ندارد.


روش سوم: استفاده از SignalR

در SignalR ابتدا سعی می‌شود تا با استفاده از Web Sockets ارتباطی ماندگار بین کلاینت و سرور برقرار شود و سپس در این حالت، سرور می‌تواند مدام اطلاعاتی، مانند تغییرات داده‌های خود را به سمت کاربر، جهت نمایش و یا محاسبات خاص خود ارسال کند. اگر حالت Web Socket میسر نباشد (توسط سرور یا کلاینت پشتیبانی نشود)، به حالت‌های دیگری مانند server events, forever frames, long polling سوئیچ خواهد کرد. اطلاعات بیشتر


روش چهارم: قرار دادن اطلاعات سمت سرور در کدهای HTML صفحه

روش متداول دیگری جهت تامین اطلاعات جاوا اسکریپتی سمت کاربر، قرار دادن آن‌ها در ویژگی‌های data-* ارائه شده در HTML5 است.
<ul>
@foreach (var product in products)
{
  <li id="product@product.Id" data-rank="@product.Rank">@product.Name</li>
}
</ul>
در اینجا لیستی از محصولات، به صورت متداولی از کنترلر دریافت گردیده و سپس ویژگی data-rank هر ردیف نمایش داده شده نیز توسط این اطلاعات سمت سرور مقدار دهی شده‌اند.
اکنون برای دسترسی به مقدار data-rank سطری مانند product1، در کدهای جاوا اسکریپتی صفحه می‌توان نوشت:
<script type="text/javascript">
var product1Rank = $("#product1").data("rank");
</script>
این روش برای قرار دادن اطلاعات ثابت اشیاء، روش مرسومی است.


روش پنجم: قرار دادن اطلاعات سمت سرور در کدهای جاوا اسکریپتی صفحه

این روش همانند روش چهارم است، با این تفاوت که اینبار اطلاعات مورد نیاز، مستقیما به یک متغیر جاوا اسکریپتی انتساب داده شده‌است:
 <script type="text/javascript">
var product1Name = "@product1.Name";
</script>
مزیت این روش، عدم ارسال درخواست اضافه‌تری به سرور برای دریافت اطلاعات مورد نیاز است. مقدار product1Name در همان بار اول رندر صفحه از سمت سرور، مشخص می‌گردد.


روش ششم: انتساب یک شیء دات نتی به یک متغیر جاوا اسکریپتی

این روش همانند روش پنجم است، با این تفاوت که اینبار قصد داریم بجای یک مقدار ثابت رشته‌ای یا عددی، برای مثال، آرایه‌ای از اشیاء را به یک متغیر جاوا اسکریپتی انتساب دهیم. در اینجا ابتدا اطلاعات مورد نظر را به فرمت JSON تبدیل می‌کنیم:
//سمت سرور
[HttpGet]
public ActionResult Index()
{
    var array = new[]
    {
        "Afghanistan",
        "Albania",
        "Algeria",
        "American Samoa",
        "Andorra",
        "Angola",
        "Anguilla",
        "Antarctica",
        "Antigua and/or Barbuda"
     };
     ViewBag.JsonString = new JavaScriptSerializer().Serialize(array);
     return View();
}
سپس توسط متد Html.Raw می‌توان این رشته‌ی JSON را که اکنون حاوی آرایه جاوا اسکریپتی سمت سرور است، به یک متغیر جاوا اسکریپتی نسبت داد:
 //سمت کلاینت
<script type="text/javascript">
var jsonArray = @Html.Raw(@ViewBag.JsonString);
</script>
استفاده از Html.Raw در این حالت از این جهت ضروری است که اطلاعاتی مانند [] به صورت encode شده در سمت کاربر نمایش داده نشوند؛ چون Razor به صورت پیش فرض اطلاعات را Encode می‌کند.
و یا اینکار را به صورت خلاصه به شکل زیر نیز می‌توان در سمت کاربر انجام داد:
 <script type="text/javascript">
  var model = @Html.Raw(Json.Encode(Model));
  // your js code here
</script>
در اینجا کار تبدیل اطلاعات مدل به JSON، در همان سمت RazorView انجام شده‌است.
مطالب دوره‌ها
به روز رسانی غیرهمزمان قسمتی از صفحه به کمک jQuery در ASP.NET MVC
یک صفحه شلوغ و سنگین را در نظر بگیرید. برای مثال قرار است ابتدا مطلب خاصی در سایت نمایش یابد و سپس ادامه صفحه که شامل انبوهی از لیست نظرات مرتبط با آن مطلب است به صورت غیرهمزمان و Ajax ایی بدون توقف پردازش صفحه، در فرصتی مناسب از سرور دریافت و به صفحه اضافه گردد (به روز رسانی قسمتی از صفحه در فرصت مناسب). در این حالت چون نمایش اولیه صفحه سریع صورت می‌گیرد، کاربر نهایی آنچنان احساس کند بودن بازکردن صفحات سایت را نخواهد داشت. در ادامه نحوه پیاده سازی این روش را به کمک jQuery Ajax بررسی خواهیم کرد.

مدل و کنترلر برنامه

namespace jQueryMvcSample07.Models
{
    public class BlogPost
    {
        public int Id { set; get; }
        public string Title { set; get; }
        public string Body { set; get; }
    }
}

using System.Web.Mvc;
using System.Web.UI;
using jQueryMvcSample07.Models;
using jQueryMvcSample07.Security;

namespace jQueryMvcSample07.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View(); //نمایش یک منوی ساده در ابتدای کار
        }

        [HttpGet]
        public ActionResult ShowSynchronous()
        {
            var model = getModel();
            return View(model); //نمایش همزمان
        }

        private static BlogPost getModel()
        {
            //شبیه سازی یک عملیات طولانی
            System.Threading.Thread.Sleep(3000);
            var model = new BlogPost
            {
                Title = "عنوان ... ",
                Body = "مطلب... "
            };
            return model;
        }

        [HttpGet]
        public ActionResult ShowAsynchronous()
        {
            return View(); //نمایش ابتدایی صفحه
        }

        [HttpPost]
        [AjaxOnly]
        [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
        public ActionResult RenderAsynchronous()
        {
            //دریافت اطلاعات به صورت غیرهمزمان
            var model = getModel();
            return PartialView(viewName: "_Post", model: model);
        }
    }
}
مدل برنامه، بیانگر ساختار اطلاعات مطلبی است که قرار است نمایش یابد.
در کنترلر Home، ابتدا اکشن متد Index آن فراخوانی شده و در این حالت دو لینک زیر نمایش داده می‌شوند:
@{
    ViewBag.Title = "Index";
}
<h2>
    نمایش اطلاعات به صورت همزمان و غیرهمزمان</h2>
<ul>
    <li>
        @Html.ActionLink(linkText: "نمایش همزمان", actionName: "ShowSynchronous", controllerName: "Home")
    </li>
    <li>
        @Html.ActionLink(linkText: "نمایش غیر همزمان", actionName: "ShowAsynchronous", controllerName: "Home")
    </li>
</ul>
لینک اول، به اکشن متد ShowSynchronous اشاره می‌کند و لینک دوم به اکشن متد ShowAsynchronous.
در هر دو صفحه نهایتا از یک Partial View به نام _Post.cshtml برای نمایش اطلاعات استفاده خواهد شد:
@model jQueryMvcSample07.Models.BlogPost
<fieldset>
    <legend>@Model.Title</legend>
    @Model.Body
</fieldset>
زمانیکه کاربر بر روی لینک نمایش همزمان کلیک می‌کند، به صفحه زیر هدایت می‌شود:
@model jQueryMvcSample07.Models.BlogPost
@{
    ViewBag.Title = "ShowSynchronous";
}

<h2>نمایش همزمان</h2>
@{ Html.RenderPartial("_Post", Model); }
این صفحه، یک صفحه متداول است و اطلاعات آن دقیقا در زمان نمایش صفحه اخذ شده و چون در اینجا از یک Sleep عمدی برای تولید اطلاعات استفاده گردیده است، نمایش آن حداقل سه ثانیه طول خواهد کشید.
در حالتیکه کاربر بر روی لینک نمایش غیرهمزمان کلیک می‌کند، صفحه زیر را مشاهده خواهد کرد:
@{
    ViewBag.Title = "ShowAsynchronous";
    var loadInfoUrl = Url.Action(actionName: "RenderAsynchronous", controllerName: "Home");
}
<h2>
    نمایش غیر همزمان</h2>
<div id="info" align="center">
</div>
<div id="progress" align="center" style="display: none">
    <br />
    <img src="@Url.Content("~/Content/images/loadingAnimation.gif")" alt="loading..."  />
</div>
@section JavaScript
{
    <script type="text/javascript">
        $(function () {
            $("#progress").css("display", "block");
            $.ajax({
                type: "POST",
                url: '@loadInfoUrl',
                complete: function (xhr, status) {
                    var data = xhr.responseText;
                    if (xhr.status == 403) {
                        window.location = "/login";
                    }
                    else if (status === 'error' || !data || data == "nok") {
                        alert('خطایی رخ داده است');
                    }
                    else {
                        $("#progress").css("display", "none");
                        $("#info").html(data);
                    }
                }
            });
        });
    </script>
}
نمایش ابتدایی این صفحه بسیار سریع است. در ابتدای کار progress bar ایی فعال شده و سپس از طریق jQuery Ajax درخواست دریافت اطلاعات رندر شده اکشن متدی به نام RenderAsynchronous به سرور ارسال می‌شود. چون عملیات Ajax غیرهمزمان است، کاربر نیازی نیست تا رندر شدن کامل صفحه ابتدا صبر کند و سپس کل صفحه به او نمایش داده شود. در اینجا ابتدا صفحه به صورت کامل نمایان شده و سپس درخواستی Ajax ایی به سرور ارسال می‌گردد. در پایان عملیات، Partial View یاد شده رندر گردیده و در div ایی با id مساوی info نمایش داده می‌شود.
به این ترتیب می‌توان حس سریع بودن سایت را زمانیکه قسمتی از صفحه نیاز به زمان بیشتری برای نمایش اطلاعات دارد، به کاربر منتقل کرد.

دریافت پروژه کامل این قسمت
jQueryMvcSample07.zip 
مطالب دوره‌ها
نحوه برقراری ارتباطات بین صفحات، سیستم راهبری و ViewModelها در قالب پروژه WPF Framework
هدف از قالب پروژه WPF Framework ایجاد یک پایه، برای شروع سریع یک برنامه تجاری WPF جدید است. بنابراین فرض کنید که این قالب، هم اکنون در اختیار شما است و قصد دارید یک صفحه جدید، مثلا تغییر مشخصات کاربری را به آن اضافه کنید. کدهای کامل این قابلیت هم اکنون در قالب پروژه موجود است و به این ترتیب توضیح جزئیات روابط آن در اینجا ساده‌تر خواهد بود.

1) ایجاد صفحه تغییر مشخصات کاربر
کلیه Viewهای برنامه، در پروژه ریشه، ذیل پوشه Views اضافه خواهند شد. همچنین چون در آینده تعداد این فایل‌ها افزایش خواهند یافت، بهتر است جهت مدیریت آن‌ها، به ازای هر گروه از قابلیت‌ها، یک پوشه جدید را ذیل پوشه Views اضافه کرد.


همانطور که ملاحظه می‌کنید در اینجا پوشه UserInfo به همراه یک فایل جدید XAML به نام ChangeProfile.xaml، ذیل پوشه Views پروژه ریشه اصلی اضافه شده‌اند.
ChangeProfile.xaml از نوع Page است؛ از این جهت که اگر به فایل MainWindow.xaml که سیستم راهبری برنامه در آن تعبیه شده است مراجعه کنید، یک چنین تعریفی را ملاحظه خواهید نمود:
<CustomControls:FrameFactory
                    x:Name="ActiveScreen"            
                    HorizontalContentAlignment="Stretch"
                    VerticalContentAlignment="Stretch"     
                    NavigationUIVisibility="Hidden"            
                    Grid.Column="1" 
                    Margin="0" />
سورس کامل کنترل سفارشی FrameFactory.cs را در پروژه Infrastructure برنامه می‌توانید مشاهده کنید. FrameFactory در حقیقت یک کنترل Frame استاندارد است که مباحث تزریق وابستگی‌ها و همچنین راهبری خودکار سیستم در آن تعریف شده‌اند.
مرحله بعد، تعریف محتویات فایل ChangeProfile.xaml است. در این فایل اطلاعات انقیاد داده‌ها از ViewModel مرتبط که در ادامه توضیح داده خواهد شد دریافت می‌گردد. مثلا مقدار خاصیت ChangeProfileData.Password، از ViewModel به صورت خودکار تغذیه خواهد شد.
در این فایل یک سری DynamicResource را هم برای تعریف دکمه‌های سبک مترو ملاحظه می‌کنید. کلیدهای متناظر با آن در فایل Icons.xaml که در فایل App.xaml برای کل برنامه ثبت شده است، تامین می‌گردد.


2) تنظیم اعتبارسنجی صفحه اضافه شده
پس از اینکه صفحه جدید اضافه شد، نیاز است وضعیت دسترسی به آن مشخص شود:
/// <summary>
/// تغییر مشخصات کاربر جاری
/// </summary>
[PageAuthorization(AuthorizationType.FreeForAuthenticatedUsers)]
public partial class ChangeProfile
برای این منظور به فایل code behind این صفحه یعنی ChangeProfile.xaml.cs مراجعه و تنها، ویژگی فوق را به آن اضافه خواهیم کرد. ویژگی PageAuthorization به صورت خودکار توسط فریم ورک تهیه شده خوانده و اعمال خواهد شد. برای نمونه در اینجا کلیه کاربران اعتبارسنجی شده در سیستم می‌توانند مشخصات کاربری خود را تغییر دهند.
در مورد نحوه تعیین نقش‌های متفاوت در صورت نیاز، در قسمت قبل بحث گردید.


3) تغییر منوی برنامه جهت اشاره به صفحه جدید
خوب، ما تا اینجا یک صفحه جدید را تهیه کرده‌ایم. در مرحله بعد باید مدخلی را در منوی برنامه جهت اشاره به آن تهیه کنیم.
منوی برنامه در فایل MainMenu.xaml قرار دارد. اطلاعات متناظر با دکمه ورود به صفحه تغییر مشخصات کاربری نیز به شکل ذیل تعریف شده است:
                <Button Style="{DynamicResource MetroCircleButtonStyle}"
                        Height="55" Width="55"  
                        Command="{Binding DoNavigate}"
                        CommandParameter="\Views\UserInfo\ChangeProfile.xaml"
                        Margin="2">
                    <Rectangle Width="28" Height="17.25">
                        <Rectangle.Fill>
                            <VisualBrush Stretch="Fill" Visual="{StaticResource appbar_user_tie}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </Button>
به ازای هر صفحه جدیدی که تعریف می‌شود تنها کافی است CommandParameter ایی مساوی مسیر فایل XAML مورد نظر، در فایل منوی برنامه قید شود. منوی اصلی دارای ViewModel ایی است به نام MainMenuViewModel.cs که در پروژه Infrastructure پیشتر تهیه شده است.
در این ViewModel تعاریف DoNavigate و پردازش پارامتر دریافتی به صورت خودکار صورت خواهد گرفت و سورس کامل آن در اختیار شما است. بنابراین تنها کافی است CommandParameter را مشخص کنید، DoNavigate کار هدایت به آن‌را انجام خواهد داد.


4) ایجاد ViewModel متناظر با صفحه
مرحله آخر افزودن یک صفحه، تعیین ViewModel متناظر با آن است. عنوان شد که اطلاعات مورد نیاز جهت عملیات Binding در این فایل قرار می‌گیرند و اگر به فایل ChangeProfileViewModel.cs مراجعه کنید (نام آن مطابق قرارداد، یک کلمه ViewModel را نسبت به نام View متناظر بیشتر دارد)، چنین خاصیت عمومی را در آن خواهید یافت.


مطابق قراردادهای توکار قالب تهیه شده:
- نیاز است ViewModel تعریف شده از کلاس پایه BaseViewModel مشتق شود تا علاوه بر تامین یک سری کدهای تکراری مانند:
 public abstract class BaseViewModel : DataErrorInfoBase, INotifyPropertyChanged, IViewModel
سبب شناسایی این کلاس به عنوان ViewModel و برقرار تزریق وابستگی‌های خودکار در سازنده آن نیز گردد.
- پس از اضافه شدن کلاس پایه BaseViewModel نیاز است تکلیف خاصیت public override bool ViewModelContextHasChanges را نیز مشخص کنید. در اینجا به سیستم راهبری اعلام می‌کنید که آیا در ViewModel جاری تغییرات ذخیره نشده‌ای وجود دارند؟ فقط باید true یا false را بازگردانید. برای مثال خاصیت uow.ContextHasChanges برای این منظور بسیار مناسب است و از طریق پیاده سازی الگوی واحد کار به صورت خودکار چنین اطلاعاتی را در اختیار برنامه قرار می‌دهد.

در ViewModelها هرجایی که نیاز به اطلاعات کاربر وارد شده به سیستم داشتید، از اینترفیس IAppContextService در سازنده کلاس ViewModel جاری استفاده کنید. اینترفیس IUnitOfWork امکانات ذخیره سازی اطلاعات و همچنین مشخص سازی وضعیت Context جاری را در اختیار شما قرار می‌دهد.
کلیه کدهای کار کردن با یک موجودیت باید در کلاس سرویس متناظر با آن قرار گیرند و این کلاس سرویس توسط اینترفیس آن مانند IUsersService در اینجا باید توسط سازنده کلاس در اختیار ViewModel قرار گیرد.
تزریق وابستگی‌ها در اینجا خودکار بوده و تنظیمات آن در فایل IocConfig.cs پروژه Infrastructure قرار دارد. این کلاس آنچنان نیازی به تغییر ندارد؛ اگر پیش فرض‌های نامگذاری آن‌را مانند کلاس‌های Test و اینترفیس‌های ITest، در لایه سرویس برنامه رعایت شوند.
مطالب
آیا برنامه نویس‌های دات نت باید نگران دنیای 64 بیتی باشند؟

جواب ساده و کوتاه: خیر!
کدمدیریت شده‌ی شما در هر دو پلتفرم 32 بیتی - x86 و x64 بدون نیاز به هیچگونه تغییری و بدون نگرانی اجرا خواهد شد.
گزیده‌ای از MSDN :
اگر کد شما 100 درصد مدیریت شده است (managed code ایی که به صورت خالص از دات نت فریم ورک استفاده می‌کند و هیچگونه وابستگی خارجی دیگری به کتابخانه‌های دیگر ندارد)، تنها با کپی شدن در یک محیط x64 دارای CLR ایی 64 بیتی (دات نت فریم ورک 64 بیتی)، بدون هیچگونه مشکلی اجرا خواهد شد.

سؤال: چرا و چگونه؟!
کامپایلرهای دات نتی (تفاوتی نمی‌کند که چه زبانی مورد استفاده باشد)، کد شما را به IL‌ ترجمه می‌کنند و IL اساسا درکی از پروسسور ندارد. JIT است که در آخرین لحظه در این مورد تصمیم گیری می‌کند.

این نگرانی از کجا حاصل شده است؟
نگارش R2 ویندوز 2008 سرور، فقط 64 بیتی خواهد بود و ویندوز سرور 2008 فعلی، آخرین سروری از مایکروسافت است که هر دو نسخه‌ی 32 بیتی و 64 بیتی را دارد. بنابراین دیر یا زود تمام برنامه نویس‌های ویندوزی "مجبور" خواهند شد دنیای 64 بیتی را تجربه کنند. (البته اگر تاکنون آن‌را تجربه نکرده‌اند)
و البته هنوز یک سری از محیط‌های توسعه، کامپایلر مخصوص 64 بیتی ندارند (مانند دلفی که قرار است در طول سال جاری اولین تجربه‌ی 64 بیتی خود را ارائه دهد)

نکته:
در صفحه‌ی build ویژوال استودیو، شما می‌توانید نوع پلتفرم مورد نظر را نیز تعیین کنید:



پیش فرض آن بر روی Any CPU‌ است و در این حالت کد کامپایل شده‌ی شما بدون مشکل بر روی پلتفرم‌هایی که مشاهده می‌کنید اجرا خواهد شد و تنها پیشنیاز اجرای آن، نصب نسخه‌ی دات نت فریم ورک مخصوص آن پلتفرم است، بدون اینکه نیاز باشد برنامه نویس نگران جزئیات خاصی در مورد خصوصیات ویژه‌ی آن پلتفرم‌ ویژه باشد.


سؤال: اگر کد ما خالص نبود چطور؟ (منظور اینکه 100 درصد دات نتی نبود)

حالت الف) اگر از کامپوننت‌های خارجی استفاده می‌کنید (حتی اگر 100 درصد دات نتی هم باشند) حتما اطمینان حاصل کنید که برای پلتفرم خاصی کامپایل نشده‌اند (همان Any CPU‌‌ مورد استفاده بوده)، زیرا کد شما که برای تمام CPU ها کامپایل شده، در محیط 64 بیتی، تنها توانایی بارگذاری اسمبلی‌های 64 بیتی را خواهد داشت (64 بیتی رفتار می‌کند) و با مواجه شدن با اسمبلی‌هایی که برای یک پروسسور خاص دیگر کامپایل شده‌اند، با خطای BadImageFormatException خاتمه می‌یابد.

حالت ب) استفاده از API ویندوز یا DLL های غیر دات نتی
باید با هماهنگی با تولید کننده‌ی مربوطه حتما از نگارش 64 بیتی استفاده شود و همچنین برنامه‌ی شما باید توانایی استفاده از اشاره‌گرهای 64 بیتی را داشته باشد. اندازه‌ی نوع داده‌ای IntPtr در یک محیط 32 بیتی 4 است و در یک محیط 64 بیتی 8 خواهد بود (IntPtr.Size). اگر در حین اجرای ترجمه‌ی API یک کتابخانه به اشتباه بجای استفاده از IntPtr از int‌ استفاده شده باشد، ممکن است کد شما در یک محیط 32 بیتی سال‌ها بدون مشکل اجرا شود، اما در اولین اجرای خود در یک محیط 64 بیتی، کرش خواهد کرد. (بدلیل overflow حاصل)
IntPtr به اندازه‌ی کافی هوشمند است تا سایز خودش را مطابق پلتفرم تنظیم کند و مشکل ساز نشود.

مثال:

[DllImport("kernel32.dll")]
public static extern void GetSystemInfo([MarshalAs(UnmanagedType.Struct)] ref SYSTEM_INFO lpSystemInfo);

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
internal _PROCESSOR_INFO_UNION uProcessorInfo;
public uint dwPageSize;
public IntPtr lpMinimumApplicationAddress;
public int lpMaximumApplicationAddress;
public IntPtr dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort dwProcessorLevel;
public ushort dwProcessorRevision;
}

[StructLayout(LayoutKind.Explicit)]
public struct _PROCESSOR_INFO_UNION
{
[FieldOffset(0)]
internal uint dwOemId;
[FieldOffset(0)]
internal ushort wProcessorArchitecture;
[FieldOffset(2)]
internal ushort wReserved;
}

در این مثال که از API‌ ویندوز استفاده می‌شود، به اشتباه نوع lpMaximumApplicationAddress‌ به صورت int تعریف شده است (بجای IntPtr). این کد بدون مشکل در یک برنامه‌ی 32 بیتی کار می‌کند اما همین برنامه در یک محیط 64 بیتی یا کرش خواهد کرد یا مقدار lpMaximumApplicationAddress منفی گزارش می‌شود.