نظرات مطالب
خلاصه اشتراک‌های روز دو شنبه 16 آبان 1390
سلام
من از reportViewer مایکروسافت برای نشون دادن report های خودم استفاده می کنم
وقتی صفحه رو با ie نگاه می کنم مشکلی وجود نداره اما وقتی صفحه رو با ff نگاه می کنم به دلیل اینکه دکمه print یک ActieX هستش و فقط در ie کار می کنه ؛ در ff دکمه print نمایش داده نمیشه
خیلی جستجو کردم تا راه حلی پیدا کنم اما موفق نشدم
لطفا منو در این زمینه راهنمایی کنید
نظرات مطالب
تعیین اعتبار یک checkBoxList با کمک jQuery
با سلام خدمت استاد نصیری
می دونم که این مطلب به پست شما ربطی نداره ولی خواهش می کنم راهنمایی کنید.

آفای نصیری مطلبی رو پیدا کردم که توسط اون میشه از توابع نوشته شده در C# در Crystal report استفاده کرد:
اما هر کاری می کنم که اون رو در بخش فرمول نویسی در بخش Additional function ببینم اصلا گزینه مربوطه (همون فایل dll)نمایش داده نمی شه.
روی چند سیستم هم این کارو انجام دادم ولی گزینه مورد نظر وجود نداشته!!!

چیکار کنم؟
نظرات مطالب
Attribute Routing در ASP.NET MVC 5
سلام
الان من در قسمت route.config به این صورت کدهام تعریف شده

       public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapMvcAttributeRoutes();
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "List", id = UrlParameter.Optional }
            );                
        }
و اومدم توی کنترل Home و اکشن موبوط به اون که دارای یک پارامتر دریافتی برای پیج هست این کد رو تعریف کردم:
[Route("Page/{page?}")]
        public ActionResult List(int page=1)
        {
اما وقتی برنامه رو اجرا میکنم خطای 404 رو میده. ممنون میشم راهنمایی کنید مشکل از کجاست.
مسیرراه‌ها
React 16x
پیش نیاز ها
کامپوننت ها
ترکیب کامپوننت ها
طراحی یک گرید
مسیریابی 
کار با فرم ها
ارتباط با سرور
احراز هویت و اعتبارسنجی کاربران 
React Hooks  
توزیع برنامه

مدیریت پیشرفته‌ی حالت در React با Redux و Mobx   

       Redux
       MobX  

مطالب تکمیلی 
    مطالب
    بهبود کارآیی کنترل‌های لیستی WPF در حین بارگذاری تعداد زیادی از رکوردها
    کنترل‌های WPF در حالت پیش فرض و بدون اعمال قالب خاصی به آن‌ها عموما خوب عمل می‌کنند. مشکل از جایی شروع می‌شود که قصد داشته باشیم حالت پیش فرض را اندکی تغییر دهیم و یا Visual tree این کنترل‌ها اندکی پیچیده شوند. برای نمونه مدل زیر را در نظر بگیرید:
    using System;
    
    namespace WpfLargeLists.Models
    {
        public class User
        {
            public int Id { set; get; }
            public string FirstName { set; get; }
            public string LastName { set; get; }
            public string Address { set; get; }
            public DateTime DateOfBirth { set; get; }
        }
    }
    قصد داریم فقط 1000 رکورد ساده از این مدل را به یک ListView اعمال کنیم.
                        <ListView ItemsSource="{Binding UsersTab1}" Grid.Row="1" Margin="3">
                            <ListView.View>
                                <GridView>
                                    <GridViewColumn Header="Id" Width="50" DisplayMemberBinding="{Binding Id, Mode=OneTime}" />
                                    <GridViewColumn Header="FirstName" Width="100" DisplayMemberBinding="{Binding FirstName, Mode=OneTime}" />
                                    <GridViewColumn Header="LastName" Width="100" DisplayMemberBinding="{Binding LastName, Mode=OneTime}" />
                                    <GridViewColumn Header="Address" Width="100" DisplayMemberBinding="{Binding Address, Mode=OneTime}" />
                                    <GridViewColumn Header="DateOfBirth" Width="150" DisplayMemberBinding="{Binding DateOfBirth, Mode=OneTime}" />
                                </GridView>
                            </ListView.View>
                        </ListView>
    در اینجا UsersTab1، لیستی حاوی فقط 1000 رکورد از شیء User است. در حالت معمولی این لیست بدون مشکل بارگذاری می‌شود. اما با اعمال مثلا قالب MahApp.Metro، بارگذاری همین لیست، حدود 5 ثانیه با CPU usage صد در صد طول می‌کشد. علت اینجا است که در این حالت WPF سعی می‌کند تا ابتدا در VisualTree، کل 1000 ردیف را کاملا ایجاد کرده و سپس نمایش دهد.


    راه حل توصیه شده برای بارگذاری تعداد بالایی رکورد در WPF  : استفاده از UI Virtualization

    UI Virtualization روشی است که در آن تنها المان‌هایی که توسط کاربر در حال مشاهده هستند، تولید و مدیریت خواهند شد. در این حالت اگر 1000 رکورد را به یک ListBox یا ListView ارسال کنید و کاربر بر اساس اندازه صفحه جاری خود تنها 10 رکورد را مشاهده می‌کند، WPF فقط 10 عنصر را در VisualTree مدیریت خواهد کرد. با اسکرول به سمت پایین، مواردی که دیگر نمایان نیستند dispose شده و مجموعه نمایان دیگری خلق خواهند شد. به این ترتیب می‌توان حجم بالایی از اطلاعات را در WPF با میزان مصرف پایین حافظه و همچنین مصرف CPU بسیار کم مدیریت کرد. این مجازی سازی در WPF به وسیله VirtualizingStackPanel در دسترس است.

    برای اینکه WPF virtualization به درستی کار کند، نیاز است یک سری شرایط مقدماتی فراهم شوند:
    - از کنترلی استفاده شود که از virtualization پشتیبانی می‌کند؛ مانند ListBox و ListView.
    - ارتفاع کنترل لیستی باید دقیقا مشخص باشد؛ یا درون یک ردیف از Grid ایی باشد که ارتفاع آن مشخص است. برای نمونه اگر ارتفاع ردیف Grid ایی که ListView را دربرگرفته است به * تنظیم شده، مشکلی نیست؛ اما اگر ارتفاع این ردیف به Auto تنظیم شده، کنترل لیستی برای محاسبه vertical scroll bar خود دچار مشکل خواهد شد.
    - کنترل مورد استفاده نباید در یک کنترل  ScrollViewer محصور شود؛ در غیر اینصورت virtualization رخ نخواهد داد. علاوه بر آن در خود کنترل باید خاصیت ScrollViewer.HorizontalScrollBarVisibility نیز به Disabled تنظیم گردد.
    - در کنترل در حال استفاده، ScrollViewer.CanContentScroll باید به true تنظیم شود.

    مورد مشخص بودن ارتفاع بسیار مهم است. برای نمونه در برنامه‌ای پس از فعال سازی مجازی سازی، کنترل لیستی کلا از کار افتاد و حرکت scroll bar آن سبب بروز CPU Usage بالایی می‌شد. این مشکل با تنظیم ارتفاع آن به شکل زیر برطرف شد:
     Height="{Binding Path=RowDefinitions[1].ActualHeight, RelativeSource={RelativeSource AncestorType=Grid}}"
    در این تنظیم، ارتفاع کنترل، به ارتفاع سطر دوم گرید دربرگیرنده ListView متصل شده است.

    - پس از اعمال موارد یاد شده، باید VirtualizingStackPanel کنترل را فعال کرد. ابتدا دو خاصیت زیر باید مقدار دهی شوند:
       VirtualizingStackPanel.IsVirtualizing="True"
      VirtualizingStackPanel.VirtualizationMode="Recycling"
    سپس ItemsPanelTemplate کنترل باید به صورت یک VirtualizingStackPanel مقدار دهی شود. برای مثال اگر از ListBox استفاده می‌کنید، تنظیمات آن به نحو زیر است:
     <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
              <VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    و اگر از ListView استفاده می‌شود، تنظیمات آن مشابه ListBox است:
     <ListView.ItemsPanel>
        <ItemsPanelTemplate>
              <VirtualizingStackPanel
                   IsVirtualizing="True"
                   VirtualizationMode="Recycling" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    با این توضیحات ListView ابتدای بحث به شکل زیر تغییر خواهد یافت تا مجازی سازی آن فعال گردد:
                        <ListView ItemsSource="{Binding UsersTab2}" Grid.Row="1" Margin="3"
                                  ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                                  ScrollViewer.CanContentScroll="True"
                                  VirtualizingStackPanel.IsVirtualizing="True"
                                  VirtualizingStackPanel.VirtualizationMode="Recycling">
                            <ListView.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <VirtualizingStackPanel 
                                            IsVirtualizing="True" 
                                            VirtualizationMode="Recycling" />
                                </ItemsPanelTemplate>
                            </ListView.ItemsPanel>
                            <ListView.View>
                                <GridView>
                                    <GridViewColumn Header="Id" Width="50" DisplayMemberBinding="{Binding Id, Mode=OneTime}" />
                                    <GridViewColumn Header="FirstName" Width="100" DisplayMemberBinding="{Binding FirstName, Mode=OneTime}" />
                                    <GridViewColumn Header="LastName" Width="100" DisplayMemberBinding="{Binding LastName, Mode=OneTime}" />
                                    <GridViewColumn Header="Address" Width="100" DisplayMemberBinding="{Binding Address, Mode=OneTime}" />
                                    <GridViewColumn Header="DateOfBirth" Width="150" DisplayMemberBinding="{Binding DateOfBirth, Mode=OneTime}" />
                                </GridView>
                            </ListView.View>
                        </ListView>
    کدهای کامل مثال فوق را از اینجا می‌توانید دریافت کنید: WpfLargeLists.zip
    در این مثال دو برگه را ملاحظه می‌کنید. برگه اول حالت normal ابتدای بحث است و برگه دوم پیاده سازی UI Virtualization را انجام داده است.

    مطالب
    بهینه سازی پروژه‌های Angular
    Angular یکی از محبوب‌ترین فریم ورک‌ها، برای ساختن برنامه‌های تک صفحه‌ای می‌باشد. اگرچه گفتیم تک صفحه‌ای، اما ضرورتا منظور این نیست که پروژه‌ی شما تنها شامل یک صفحه باشد. شما می‌توانید با Angular یک وب سایت را با هزاران صفحه نیز ایجاد کنید. با این حال وقتی بحث از کارآیی باشد، بهتر است همیشه در رابطه با تعدادی فکر کنیم که باعث می‌شوند پروژه، نرم و سریع اجرا شود. 


    #1 Optimize main bundle with Lazy Loading
    وقتی که پروژه را برای حالت ارائه‌ی نهایی (Production ) بدون در نظر گرفتن Lazy Load، بیلد می‌کنیم احتمالا فایل‌های تولید شده زیر را در پوشه‌ی dist خواهیم دید: 

    1. polyfills.js :  برای ساختن برنامه‌های سازگار با انواع مرورگر‌ها می‌باشد. به دلیل اینکه وقتی کد‌ها را با جدیدترین ویژگی‌ها می‌نویسیم، ممکن است که همه‌ی مرورگر‌ها توانایی پشتیبانی از آن ویژگی‌ها را نداشته باشند.
    2. scripts.js : شامل اسکریپت‌هایی می‌باشد که در بخش scripts، در فایل angular.json تعریف کرده‌ایم.
    3.  webpack loader : runtime.js می‌باشد. این فایل شامل webpack utilities‌هایی می‌باشد که برای بارگذاری دیگر فایل‌ها مورد نیاز است.
    4. styles.css : شامل style ‌هایی است که در بخش styles، در فایل angular.json تعریف کرده‌ایم.
    5. main.js : شامل تمامی کد‌ها از قبیل کامپوننت‌ها ( کد‌های مربوط به css ، html ، ts) ، دایرکتیو‌ها، pipes و سرویس‌ها و ماژول‌های ایمپورت شده از جمله third party‌های می‌باشد.

    همانطور که متوجه هستید، فایل main.js در طول زمان بزرگتر و بزرگتر خواهد شد که این یک مشکل است. در این حالت برای مشاهده‌ی وب سایت، مرورگر نیاز دارد که فایل main.js را دانلود کرده و سپس در صفحه،  آن را اجرا و رندر کند که این یک چالش برای کاربران موبایل با اینترنت ضعیف و هم چنین کاربران دسکتاپ می‌باشد. 
    آسان‌ترین راه برای برطرف کردن این مشکل این است که پروژه را به چندین ماژول lazy load، تقسیم کنیم. وقتی که از lazy module‌ها استفاده می‌کنیم، انگیولار chunk مربوط به آن را تولید می‌کند که در ابتدا بارگذاری نخواهد شد؛ مگر اینکه مورد نیاز باشند (معمولا با فعال سازی یک مسیر اتفاق می‌افتد). 
    وقتی که از lazy loading استفاده می‌کنیم، بعد از فرایند build، فایل‌های جدیدی تولید خواهند شد، مثل  4.386205799sfghe4.js که یک  چانک از  یک lazy module می‌باشد و در زمان راه اندازی صفحه اول اجرا نخواهد شد که نتیجه‌ی آن داشتن فایل main.js ای با حجم کم می‌باشد. بنابراین بارگذاری صفحه‌ی اول، خیلی سریع انجام خواهد شد. 

    با این حال، بارگذاری هر قسمت می‌تواند بر روی کارآیی تاثیر داشته باشد (بارگذاری ممکن است کند باشد). خوشبختانه انگیولار یک راه را برای برطرف کردن این مشکل فراهم کرده است ( PreloadingStrategy ) . بعد از اینکه فایل main.js  به صورت کامل بارگذاری و اجرا شد، کار پیش واکشی ماژول‌ها را انجام می‌دهد و زمانیکه کاربری مسیری را درخواست می‌دهد، آْن مسیر را بدون درنگ مشاهده خواهد کرد.

    #2 Debug bundles with Webpack Bundle Analyzer 
    حتی ممکن است بعد از تقسیم کردن منطق برنامه به چند ماژول lazy load، شما یک فایل main.js بزرگ داشته باشید. در این حالت می‌توانید بهینه سازی بیشتری را با استفاده از Webpack Bundle Analyzer انجام دهید. با استفاده از این پکیج می‌توانید آمار‌هایی را در رابطه با هر باندل داشته باشید. در ابتدا با استفاده از دستور زیر پکیج آن‌را نصب کنید:
    npm install --save-dev webpack-bundle-analyzer
    سپس فایل package.json را باز کرده و در بخش scripts، مدخل زیر را اضافه کنید:
    "bundle-report": "ng build --prod --stats-json && webpack-bundle-analyzer dist/stats.json"
    توجه کنید که اگر خروجی برنامه شما مستقیما در dist می‌باشد، به صورت بالا عمل کنید؛ ولی اگر خروجی برنامه شما در پوشه‌ی dist/YourApplicationName باشد، آن را به حالت زیر ویرایش کنید:
    "bundle-report": "ng build --prod --stats-json && webpack-bundle-analyzer dist/YourApplicationName/stats.json"
    در نهایت دستور زیر را اجرا کنید:
    npm run bundle-report
    دستور بالا یک بیلد را برای پروژه برای حالت ارائه‌ی نهایی  (Production) همراه با  آمار‌هایی در رابطه با هر باندل ایجاد می‌کند. در اینجا می‌توانیم ببینیم که چه ماژولها/فایل‌هایی در هر باندل استفاده شده‌است. این مورد فوق العاده کمک می‌کند. هم چنین می‌توانیم به صورت بصری ببینیم که چه چیز‌هایی در هر ماژول شامل شده‌اند که بهتر بود آنجا نباشند:


    #3 Use Lazy Loading for images that are not visible in page 
    وقتی که صفحه اصلی را در اولین بار، بارگذاری می‌کنیم، می‌توانیم تصاویری را داشته باشیم که در صفحه‌ی نمایش، نمایان نباشند (منظور viewport می‌باشد) و کاربر برای دیدن آن تصاویر باید صفحه را به پایین اسکرول کند. با این وجود وقتی که صفحه بارگذاری می‌شود، تصاویر هم بلافاصله دانلود می‌شوند. اگر تعداد تصاویر زیاد باشند این مورد می‌تواند بر روی performance تاثیر منفی داشته باشد. برای برطرف کردن این مشکل می‌توان از lazy loading تصاویر استفاده کرد. در این حالت تصاویر زمانی بارگذاری می‌شوند که کاربر به آن‌ها می‌رسد. یک JavaScript API به نام Intersection Observer API وجود دارد که باعث می‌شود پیاده سازی lazy load خیلی آسان شود. علاوه بر این می‌توان یک دایرکتیو را با قابلیت استفاده مجدد طراحی کرد ( lazy loading برای تصاویر با استفاده از Intersection Observer).

    #4 Use virtual scrolling for large lists  
    با استفاده از virtual scrolling  می‌توان المنت‌ها را در Dom بر اساس بخش‌های قابل مشاهده‌ای از یک لیست، Load  یا unload کرد که برنامه را فوق العاده سریع می‌کند.
     
    #5 Use FOUT instead of FOIT for fonts  
    در بیشتر وب سایت‌ها می‌توان فونت‌های سفارشی زیبایی را به جای فونت‌های معمول دید. با این حال برای استفاده از فونت‌های فراهم شده توسط سرویس‌های دیگر لازم است که مرورگر آن‌ها را دانلود و parse  کند. اگر از فونت‌های سفارشی استفاده کنیم، مثل  Google Fonts، چه اتفاقی می‌افتد؟ در اینجا دو سناریو وجود دارد: 
    • در این حالت مرورگر منتظر می‌ماند تا فونت دانلود شود و آن را parse  کند و تنها بعد از آن متن را بر روی صفحه نمایش می‌دهد. متن روی صفحه تا زمانیکه فونت دانلود و parse  نشده باشد، قابل مشاهده نیست؛ این FOIT است (Flash of invisible text) .
    • مرورگر در ابتدا متن را با استفاده از فونت معمول نمایش می‌دهد و بعد از آن سعی می‌کند که ساختار‌های فونت خارجی را دریافت کند. وقتی که دانلود انجام شد و سپس آن را parse  کرد، فونت سفارشی دانلود شده، با فونت معمول جایگزین خواهد شد؛ این FOUT است ( Flash of unstyled text ).

    بیشتر مرورگر‌ها از FOIT  استفاده می‌کنند و تنها Internet Explorer از FOUT استفاده می‌کند. برای برطرف کردن این مشکل می‌توان از توصیف‌گر font-display استفاده کرد و به مرورگر بگوییم که می‌خواهیم در ابتدا متن را با فونت معمول نمایش دهیم و جایگزینی فونت، بعد از دانلود باشد (بیشتر).
    مطالب
    شروع به کار با AngularJS 2.0 و TypeScript - قسمت دهم - کار با فرم‌ها - قسمت اول
    هر برنامه‌ی وبی، نیاز به کار با فرم‌های وب را دارد و به همین جهت، AngularJS 2.0 به همراه دو نوع از فرم‌ها است: فرم‌های مبتنی بر قالب‌ها و فرم‌های مبتنی بر مدل‌ها.
    کار با فرم‌های مبتنی بر قالب‌ها ساده‌تر است؛ اما کنترل کمتری را بر روی مباحث اعتبارسنجی داده‌های ورودی توسط کاربر، در اختیار ما قرار می‌دهند. اما فرم‌های مبتنی بر مدل‌ها هر چند به همراه اندکی کدنویسی بیشتر هستند، اما کنترل کاملی را جهت اعتبارسنجی ورودی‌های کاربران، ارائه می‌دهند. در این قسمت فرم‌های مبتنی بر قالب‌ها (Template-driven forms) را بررسی می‌کنیم.


    ساخت فرم مبتنی بر قالب‌های ثبت یک محصول جدید

    در ادامه‌ی مثال این سری، می‌خواهیم به کاربران، امکان ثبت اطلاعات یک محصول جدید را نیز بدهیم. به همین جهت فایل‌های جدید product-form.component.ts و product-form.component.html را به پوشه‌ی App\products برنامه اضافه می‌کنیم (جهت تعریف کامپوننت فرم جدید به همراه قالب HTML آن).
    الف) محتوای کامل product-form.component.html
    <form #f="ngForm" (ngSubmit)="onSubmit(f.form)">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">
                    Add Product
                </h3>
            </div>
            <div class="panel-body form-horizontal">
                <div class="form-group">
                    <label for="productName" class="col col-md-2 control-label">Name</label>
                    <div class="controls col col-md-10">
                        <input ngControl="productName" id="productName" required
                               #productName="ngForm"
                               (change)="log(productName)"
                               minlength="3"
                               type="text" class="form-control"
                               [(ngModel)]="productModel.productName"/>
                        <div *ngIf="productName.touched && productName.errors">
                            <label class="text-danger" *ngIf="productName.errors.required">
                                Name is required.
                            </label>
                            <label class="text-danger" *ngIf="productName.errors.minlength">
                                Name should be minimum {{ productName.errors.minlength.requiredLength }} characters.
                            </label>
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <label for="productCode" class="col col-md-2 control-label">Code</label>
                    <div class="controls col col-md-10">
                        <input ngControl="productCode" id="productCode" required
                               #productCode="ngForm"
                               type="text" class="form-control"
                               [(ngModel)]="productModel.productCode"/>
                        <label class="text-danger" *ngIf="productCode.touched && !productCode.valid">
                            Code is required.
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <label for="releaseDate" class="col col-md-2 control-label">Release Date</label>
                    <div class="controls col col-md-10">
                        <input ngControl="releaseDate" id="releaseDate" required
                               #releaseDate="ngForm"
                               type="text" class="form-control"
                               [(ngModel)]="productModel.releaseDate"/>
                        <label class="text-danger" *ngIf="releaseDate.touched && !releaseDate.valid">
                            Release Date is required.
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <label for="price" class="col col-md-2 control-label">Price</label>
                    <div class="controls col col-md-10">
                        <input ngControl="price" id="price" required
                               #price="ngForm"
                               type="text" class="form-control"
                               [(ngModel)]="productModel.price"/>
                        <label class="text-danger" *ngIf="price.touched && !price.valid">
                            Price is required.
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <label for="description" class="col col-md-2 control-label">Description</label>
                    <div class="controls col col-md-10">
                        <textarea ngControl="description" id="description" required
                                  #description="ngForm"
                                  rows="10" type="text" class="form-control"
                                  [(ngModel)]="productModel.description"></textarea>
                        <label class="text-danger" *ngIf="description.touched && !description.valid">
                            Description is required.
                        </label>
                    </div>
                </div>
                <div class="form-group">
                    <label for="imageUrl" class="col col-md-2 control-label">Image</label>
                    <div class="controls col col-md-10">
                        <input ngControl="imageUrl" id="imageUrl" required
                               #imageUrl="ngForm"
                               type="text" class="form-control"
                               [(ngModel)]="productModel.imageUrl"/>
                        <label class="text-danger" *ngIf="imageUrl.touched && !imageUrl.valid">
                            Image is required.
                        </label>
                    </div>
                </div>
            </div>
            <footer class="panel-footer">
                <button [disabled]="!f.valid"
                        type="submit" class="btn btn-primary">
                    Submit
                </button>
            </footer>
        </div>
    </form>

    ب) محتوای کامل product-form.component.ts
    import { Component } from 'angular2/core';
    import { Router } from 'angular2/router';
    import { IProduct } from './product';
    import { ProductService } from './product.service';
     
    @Component({
        //selector: 'product-form',
        templateUrl: 'app/products/product-form.component.html'
    })
    export class ProductFormComponent {
     
        productModel = <IProduct>{}; // creates an empty object of an interface
     
        constructor(private _productService: ProductService, private _router: Router) { }
     
        log(productName): void {
            console.log(productName);
        }
     
        onSubmit(form): void {
            console.log(form);
            console.log(this.productModel);
     
            this._productService.addProduct(this.productModel)
                .subscribe((product: IProduct) => {
                    console.log(`ID: ${product.productId}`);
                    this._router.navigate(['Products']);
                });
        }
    }

    اکنون ریز جزئیات و تغییرات این دو فایل را قدم به قدم بررسی خواهیم کرد.

    تا اینجا در فایل product-form.component.html یک فرم ساده‌ی HTML ایی مبتنی بر بوت استرپ 3 را تهیه کرده‌ایم. نکات ابتدایی آن، دقیقا مطابق است با مستندات بوت استرپ 3؛ از لحاظ تعریف form-horizontal و سپس ایجاد یک div با کلاس form-group و قرار دادن المان‌هایی با کلاس‌های form-control در آن. همچنین برچسب‌های تعریف شده‌ی با ویژگی for، در این المان‌ها، جهت بالارفتن دسترسی پذیری به عناصر فرم، اضافه شده‌اند. این مراحل در مورد تمام فرم‌های استاندارد وب صادق هستند و نکته‌ی جدیدی ندارند.

    در ادامه تعاریف AngularJS 2.0 را به این فرم اضافه کرد‌ه‌ایم. در اینجا هر کدام از المان‌های ورودی، تبدیل به Controlهای AngularJS 2.0 شده‌اند. کلاس Control، خواص ویژه‌ای را در اختیار ما قرار می‌دهد. برای مثال value یا مقدار این المان چیست؟ وضعیت touched و untouched آن چیست؟ (آیا کاربر فوکوس را به آن منتقل کرده‌است یا خیر؟) آیا dirty است؟ (مقدار آن تغییر کرده‌است؟) و یا شاید هم pristine است؟ (مقدار آن تغییری نکرده‌است). علاوه بر این‌ها دارای خاصیت valid نیز می‌باشد (آیا اعتبارسنجی آن موفقیت آمیز است؟)؛ به همراه خاصیت errors که مشکلات اعتبارسنجی موجود را باز می‌گرداند.
    <div class="form-group">
        <label for="description" class="col col-md-2 control-label">Description</label>
        <div class="controls col col-md-10">
            <textarea ngControl="description" id="description" required
                      #description="ngForm"
                      rows="10" type="text" class="form-control"
                      [(ngModel)]="productModel.description"></textarea>
            <label class="text-danger" *ngIf="description.touched && !description.valid">
                Description is required.
            </label>
        </div>
    </div>
    در اینجا کلاس مفید دیگری به نام ControlGroup نیز درنظر گرفته شده‌است. برای مثال هر فرم، یک ControlGroup است (گروهی متشکل از کنترل‌ها، در صفحه). البته می‌توان یک فرم بزرگ را به چندین ControlGroup نیز تقسیم کرد. تمام خواصی که برای کلاس Control ذکر شدند، در مورد کلاس ControlGroup نیز صادق هستند. با این تفاوت که این‌بار اگر به خاصیت valid آن مراجعه کردیم، یعنی تمام کنترل‌های قرار گرفته‌ی در آن گروه معتبر هستند و نه صرفا یک تک کنترل خاص. به همین ترتیب خاصیت errors نیز تمام خطاهای اعتبارسنجی یک گروه را باز می‌گرداند.
    هر دو کلاس Control و ControlGroup از کلاس پایه‌ای به نام AbstractControl مشتق شده‌اند و این کلاس پایه است که خواص مشترک یاد شده را به همراه دارد.

    بنابراین برای کار ساده‌تر با یک فرم AngularJS 2.0، کل فرم را تبدیل به یک ControlGroup کرده و سپس هر کدام از المان‌های ورودی را تبدیل به یک Control مجزا می‌کنیم. کار برقراری این ارتباط، با استفاده از دایرکتیو ویژه‌ای به نام ngControl انجام می‌شود. بنابراین دایرکتیو ngControl، با نامی دلخواه و معین، به تمام المان‌های ورودی، انتساب داده شده‌است.
    هرچند در این مثال نام ngControl‌ها با مقدار id هر کنترل یکسان درنظر گرفته شده‌است، اما ارتباطی بین این دو نیست. مقدار id جهت استفاده‌ی در DOM کاربرد دارد و مقدار ngControl توسط AngularJS 2.0 استفاده می‌شود. جهت رسیدن به کدهایی یکدست، بهتر است این نام‌ها را یکسان درنظر گرفت؛ اما هیچ الزامی هم ندارد.

    برای بررسی جزئیات این اشیاء کنترل، در المان productName، یک متغیر محلی را به نام productName# تعریف کرده‌ایم و آن‌را به دایرکتیو ngControl انتساب داده‌ایم. این انتساب توسط ngForm انجام شده‌است. زمانیکه AngularJS 2.0 یک متغیر محلی تنظیم شده‌ی به ngForm را مشاهده می‌کند، آن‌را به صورت خودکار به ngControl همان المان ورودی متصل می‌کند. سپس این متغیر محلی را به متد log ارسال کرده‌ایم. این متد در کلاس کامپوننت جاری تعریف شده‌است و کار آن نمایش شیء Control جاری در کنسول developer tools مرورگر است.
    <input ngControl="productName" id="productName" required
           #productName="ngForm"
           (change)="log(productName)"
           minlength="3"
           type="text" class="form-control"
           [(ngModel)]="productModel.productName"/>


    همانطور که در تصویر مشاهده می‌کنید، عناصر یک شیء Control، در کنسول نمایش داده شده‌اند و در اینجا بهتر می‌توان خواصی مانند valid و امثال آن‌را که به همراه این کنترل وجود دارند، مشاهده کرد. برای مثال خاصیت dirty آن true است چون مقدار آن المان ورودی، تغییر کرده‌است.

    بنابراین تا اینجا با استفاده از دایرکتیو ngControl، یک المان ورودی را به یک شیء Control متصل کردیم. همچنین نحوه‌ی تعریف یک متغیر محلی را در المانی و سپس ارسال آن را به کلاس متناظر با کامپوننت فرم، نیز بررسی کردیم.


    افزودن اعتبارسنجی به فرم ثبت محصولات

    به کنترل‌هایی که به صورت فوق توسط ngControl ایجاد می‌شوند، اصطلاحا implicitly created controls می‌گویند؛ یا به عبارتی ایجاد آن‌ها به صورت «ضمنی» توسط AngularJS 2.0 انجام می‌شود که نمونه‌ای از آن‌را در تصویر فوق نیز مشاهده کردید. این نوع کنترل‌های ضمنی، امکانات اعتبارسنجی محدودی را در اختیار دارند؛ که تنها سه مورد هستند:
    الف) required
    ب) minlength
    ج) maxlength

    این‌ها ویژگی‌های استاندارد اعتبارسنجی HTML 5 نیز هستند. نمونه‌ای از اعمال این موارد را با افزودن ویژگی required، به المان‌های فرم ثبت محصولات فوق، مشاهده می‌کنید.
    سپس نیاز داریم تا خطاهای اعتبارسنجی را در مقابل هر المان ورودی نمایش دهیم.
    <textarea ngControl="description" id="description" required
              #description="ngForm"
              rows="10" type="text" class="form-control"></textarea>
    <div class="alert alert-danger" *ngIf="description.touched && !description.valid">
        Description is required.
    </div>
    پس از افزودن ویژگی required به یک المان، افزودن و نمایش خطاهای اعتبارسنجی، شامل سه مرحله‌ی زیر است:
    الف) ایجاد یک div ساده جهت نمایش پیام خطای اعتبار سنجی
    ب) افزودن یک متغیر محلی با # و تنظیم شده‌ی به ngForm، جهت دسترسی به شیء کنترل ایجاد شده
    ج) استفاده از این متغیر محلی در دایرکتیو ساختاری ngIf* جهت دسترسی به خاصیت valid آن کنترل. بر مبنای مقدار این خاصیت است که تصمیم گرفته می‌شود، پیام اجباری بودن پر کردن فیلد نمایش داده شود یا خیر.
    در اینجا یک سری کلاس بوت استرپ 3 هم جهت نمایش بهتر این پیام خطای اعتبارسنجی، اضافه شده‌اند.

    علت استفاده از خاصیت touched این است که اگر آن‌را حذف کنیم، در اولین بار نمایش فرم، ذیل تمام المان‌های ورودی، پیام اجباری بودن تکمیل آن‌ها نمایش داده می‌شود. با استفاده از خاصیت touched، اگر کاربر به المانی مراجعه کرد و سپس آن‌را تکمیل نکرد، آنگاه پیام خطای اعتبارسنجی را دریافت می‌کند.



    بهبود شیوه نامه‌ی پیش فرض المان‌های ورودی اطلاعات در AngularJS 2.0

    می‌خواهیم اگر اعتبارسنجی یک المان ورودی با شکست مواجه شد، یک حاشیه‌ی قرمز، در اطراف آن نمایش داده شود. این مورد را با توجه به اینکه AngularJS 2.0، شیوه نامه‌های ویژه‌ای را به صورت خودکار به المان‌ها اضافه می‌کند، می‌توان به صورت سراسری به تمام فرم‌ها اضافه کرد. برای این منظور فایل app.component.css واقع در ریشه‌ی پوشه‌ی app را گشوده و تنظیمات ذیل را به آن اضافه کنید:
    .ng-touched.ng-invalid{
        border: 1px solid red;
    }

    ویژگی‌های اضافه شده‌ی در حالت شکست اعتبارسنجی؛ مانند ng-invalid


    ویژگی‌های اضافه شده‌ی در حالت موفقیت اعتبارسنجی؛ مانند ng-valid



    مدیریت چندین ویژگی اعتبارسنجی یک المان با هم

    گاهی از اوقات نیاز است برای یک المان ورودی، چندین نوع اعتبارسنجی مختلف را تعریف کرد. برای مثال فرض کنید که ویژگی‌های required و همچنین minlength، برای نام محصول تنظیم شده‌اند. در این حالت ذکر productName.valid خیلی عمومی است و هر دو حالت اجباری بودن فیلد و حداقل طول آن‌را با هم به همراه دارد:
    <div class="alert alert-danger" *ngIf="productName.touched && !productName.valid">
       Name is required.
    </div>
    بنابراین در این حالت از روش ذیل استفاده می‌شود:
    <div *ngIf="productName.touched && productName.errors">
        <div class="alert alert-danger" *ngIf="productName.errors.required">
            Name is required.
        </div>
        <div class="alert alert-danger" *ngIf="productName.errors.minlength">
            Name should be minimum 3 characters.
        </div>
    </div>
    خاصیت errors نیز یکی دیگر از خواص شیء کنترل است. اگر نال بود، یعنی خطایی وجود ندارد و در غیراینصورت، به ازای هر نوع اعتبارسنجی تعریف شده، خواصی به آن اضافه می‌شوند. بنابراین ذکر productName.errors.required به این معنا است که آیا خاصیت errors، دارای کلیدی به نام required است؟ اگر بله، یعنی این فیلد هنوز پر نشده‌است.
    همچنین چون در این حالت productName.touched نیاز است چندین بار تکرار شود، می‌توان آن‌را در یک div محصور کننده‌ی دو div مورد نیاز جهت نمایش خطاهای اعتبارسنجی قرار داد. به علاوه بررسی نال نبودن productName.errors نیز در div محصور کننده صورت گرفته‌است و دیگر نیازی نیست این بررسی را به ngIfهای داخلی اضافه کرد.

    نکته 1
    اگر علاقمند بودید تا جزئیات خاصیت errors را مشاهده کنید، آن‌را می‌توان توسط pipe توکاری به نام json به صورت موقت نمایش داد و بعد آن‌را حذف کرد:
     <div *ngIf="productName.touched && productName.errors">
      {{ productName.errors | json }}

    نکته 2
    بجای ذکر مستقیم عدد سه در «minimum 3 characters»، می‌توان این عدد را مستقیما از تعریف ویژگی minlength نیز استخراج کرد:
     Name should be minimum {{ productName.errors.minlength.requiredLength }} characters.


    بررسی ngForm

    شبیه به ngControl که یک المان ورودی را به یک کنترل AngularJS 2.0 متصل می‌کند، دایرکتیو دیگری نیز به نام ngForm وجود دارد که کل فرم را به شیء ControlGroup بایند می‌کند و برخلاف ngControl، نیازی به ذکر صریح آن وجود ندارد. هر زمانیکه AngularJS 2.0، المان استاندارد فرمی را در صفحه مشاهده می‌کند، این اتصالات را به صورت خودکار برقرار خواهد کرد.
    ngForm دارای خاصیتی است به نام ngSumbit که از نوع EventEmitter است (نمونه‌ای از آن را در مبحث کامپوننت‌های تو در تو پیشتر ملاحظه کرده‌اید). بنابراین از آن می‌توان جهت اتصال رخداد submit فرم، به متدی در کلاس کامپوننت خود، استفاده کرد. متد متصل به این رخداد، زمانی فراخوانی می‌شود که کاربر بر روی دکمه‌ی submit کلیک کند:
     <form #f="ngForm" (ngSubmit)="onSubmit(f.form)">
    همچنین در اینجا متغیر محلی f جهت دسترسی به شیء ControlGroup و ارسال آن به متد onSubmit تعریف شده‌است (شبیه به متغیرهای محلی دسترسی به ngControl که پیشتر جهت نمایش خطاهای اعتبارسنجی، اضافه کردیم).

    پس از تعریف این رخداد و اتصال آن در قالب کامپوننت، اکنون می‌توان متد onSubmit را در کلاس آن نیز اضافه کرد.
    onSubmit(form): void {
       console.log(form);
    }
    فعلا هدف از این متد، نمایش جزئیات شیء form دریافتی، در کنسول developer tools است.



    غیرفعال کردن دکمه‌ی submit در صورت وجود خطاهای اعتبارسنجی

    در قسمت بررسی ngForm، یک متغیر محلی را به نام f ایجاد کردیم که به شیء ControlGroup فرم جاری اشاره می‌کند. از این متغیر و خاصیت valid آن می‌توان با کمک property binding به خاصیت disabled یک دکمه، آن‌را به صورت خودکار فعال یا غیرفعال کرد:
    <button [disabled]="!f.valid"
            type="submit" class="btn btn-primary">
        Submit
    </button>
    هر زمانیکه کل فرم از لحاظ اعتبارسنجی مشکلی نداشته باشد، دکمه‌ی submit فعال می‌شود و برعکس.



    نمایش فرم افزودن محصولات توسط سیستم Routing

    با نحوه‌ی تعریف مسیریابی‌ها در قسمت قبل آشنا شدیم. برای نمایش فرم افزودن محصولات، می‌توان تغییرات ذیل را به فایل app.component.ts اعمال کرد:
    //same as before...
    import { ProductFormComponent }  from './products/product-form.component';
     
    @Component({
        //same as before…
        template: `
                    //same as before…
                        <li><a [routerLink]="['AddProduct']">Add Product</a></li>
                   //same as before…
        `,
        //same as before…
    })
    @RouteConfig([
        //same as before…
        { path: '/addproduct', name: 'AddProduct', component: ProductFormComponent }
    ])
    //same as before...
    ابتدا به RouteConfig، مسیریابی کامپوننت فرم افزودن محصولات اضافه شده‌است. سپس ماژول این کلاس در ابتدای فایل import شده و در آخر routerLink آن به قالب سایت و منوی بالای سایت اضافه شده‌است.



    اتصال المان‌های فرم به مدلی جهت ارسال به سرور

    برای اتصال المان‌های فرم به یک مدل، این مدل را به صورت یک خاصیت عمومی، در سطح کلاس کامپوننت فرم، تعریف می‌کنیم:
     productModel = <IProduct>{}; // creates an empty object of an interface
    اگر از اینترفیسی مانند IProduct که در قسمت‌های قبل این سری تعریف شد، نیاز است شیء جدیدی ساخته شود، الزاما نیازی نیست تا یک کلاس جدید را از آن مشتق کرد و بعد متغیر new ClassName را تهیه کرد. در TypeScript می‌توان به صورت خلاصه از syntax فوق نیز استفاده کرد.
    پس از تعریف خاصیت productModel، اکنون کافی است با استفاده از two-way data binding، آن‌را به المان‌های فرم نسبت دهیم. برای مثال:
    <textarea ngControl="description" id="description" required
              #description="ngForm"
              rows="10" type="text" class="form-control"
              [(ngModel)]="productModel.description"></textarea>
    در اینجا با استفاده از ngModel و انقیاد دو طرفه، کار اتصال به خاصیت توضیحات شیء محصول انجام شده‌است. اکنون بلافاصله تغییرات اعمالی به فرم، به مدل متناظر منعکس می‌شود و برعکس. این ngModel را به تمام المان‌های ورودی فرم متصل خواهیم کرد.
    پس از تعریف یک چنین اتصالی، دیگر نیازی به مقدار دهی پارامتر onSubmit(f.form) نیست. زیرا شیء productModel، در متد onSumbit در دسترس است و این شیء همواره حاوی آخرین تغییرات اعمالی به المان‌های فرم است.

    پس از اینکه فرم را به مدل آن متصل کردیم، فایل product.service.ts را گشوده و متد جدید addProduct را به آن اضافه کنید:
    addProduct(product: IProduct): Observable<IProduct> {
        let headers = new Headers({ 'Content-Type': 'application/json' }); // for ASP.NET MVC
            let options = new RequestOptions({ headers: headers });
     
        return this._http.post(this._addProductUrl, JSON.stringify(product), options)
            .map((response: Response) => <IProduct>response.json())
            .do(data => console.log("Product: " + JSON.stringify(data)))
            .catch(this.handleError);
    }
    کار این متد، ارسال شیء محصول به یک اکشن متد برنامه‌ی ASP.NET MVC جاری است. با جزئیات کار با obsevables درمطلب «دریافت اطلاعات از سرور» پیشتر آشنا شده‌ایم.
    نکته‌ی مهم اینجا است که content type پیش فرض ارسالی متد post آن، plain text است و در این حالت ASP.NET MVC شیء JSON دریافتی از کلاینت را پردازش نخواهد کرد. بنابراین نیاز است تا هدر content type را به صورت صریحی در اینجا ذکر نمود؛ در غیراینصورت در سمت سرور، شاهد نال بودن مقادیر دریافتی از کاربران خواهیم بود.
    امضای سمت سرور متد دریافت اطلاعات از کاربر، چنین شکلی را دارد (تعریف شده در فایل Controllers\HomeController.cs):
     [HttpPost]
    public ActionResult AddProduct(Product product)
    {

    اشیاء هدرها و تنظیمات درخواست، در متد addProduct سرویس ProductService، در ماژول‌های ذیل تعریف شده‌اند که باید به ابتدای فایل product.service.ts اضافه شوند:
     import { Headers, RequestOptions } from 'angular2/http';

    پس از تعریف متد addProduct در سرویس ProductService، اکنون با استفاده از ترزیق این سرویس به سازنده‌ی کلاس فرم ثبت یک محصول جدید، می‌توان متد this._productService.addProduct را جهت ارسال productModel به سمت سرور، در متد onSubmit فراخوانی کرد:
    //Same as before…
    import { IProduct } from './product';
    import { ProductService } from './product.service';
     
    @Component({
    //Same as before…
    })
    export class ProductFormComponent {
     
        productModel = <IProduct>{}; // creates an empty object of an interface
     
        constructor(private _productService: ProductService, private _router: Router) { }
     
        //Same as before… 
    
        onSubmit(form): void {
            console.log(form);
            console.log(this.productModel);
     
            this._productService.addProduct(this.productModel)
                .subscribe((product: IProduct) => {
                    console.log(`ID: ${product.productId}`);
                    this._router.navigate(['Products']);
                });
        }
    }
    همانطور که ذکر شد، از آنجائیکه شیء productModel حاوی آخرین تغییرات اعمالی توسط کاربر است، اکنون می‌توان پارامتر form متد onSubmit را حذف کرد.
    در اینجا پس از فراخوانی متد addProduct، متد subscribe، در انتهای زنجیره، فراخوانی شده‌است. کار آن هدایت کاربر به صفحه‌ی نمایش لیست محصولات است. در اینجا this._router از طریق تزریق وابستگی‌های سرویس مسیریاب به سازنده‌ی کلاس، تامین شده‌است. نمونه‌ی آن‌را در قسمت «افزودن دکمه‌ی back با کدنویسی» مربوطه به مطلب آشنایی با مسیریابی، پیشتر مطالعه کرده‌اید.



    کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: MVC5Angular2.part10.zip


    خلاصه‌ی بحث

    فرم‌های template driven در AngularJS 2.0 به این نحو طراحی می‌شوند:
     1) ابتدا فرم HTML را به حالت معمولی آن طراحی می‌کنیم؛ با تمام المان‌های آن.
     2) به تمام المان‌های فرم، دیراکتیو ngControl را متصل می‌کنیم، تا AngularJS 2.0 آن‌را تبدیل به یک کنترل خاص خودش کند. کنترلی که دارای خواصی مانند valid و touched است.
     3) سپس برای دسترسی به این کنترل ایجاد شده‌ی به صورت ضمنی، یک متغیر محلی آغاز شده‌ی با # را به تمام المان‌ها اضافه می‌کنیم.
     4) اعتبارسنجی‌هایی را مانند required  به المان‌های فرم اضافه می‌کنیم.
     5) از متغیر محلی تعریف شده و ngIf* برای بررسی خواصی مانند valid و touched برای نمایش خطاهای اعتبارسنجی کمک گرفته می‌شود.
     6) پس از تعریف فرم، تعریف ngControlها، تعریف متغیر محلی شروع شده‌ی با # و افزودن خطاهای اعتبارسنجی، اکنون نوبت به ارسال این اطلاعات به سرور است. بنابراین رخداد ngSubmit را باید به متدی در کلاس کامپوننت جاری متصل کرد.
     7) اکنون که با کلیک بر روی دکمه‌ی submit فرم، متد onSubmit متصل به ngSubmit فراخوانی می‌شود، نیاز است بین المان‌های فرم HTML و کلاس کامپوننت، ارتباط برقرار کرد. این‌کار را توسط two-way data binding و تعریف ngModel بر روی تمام المان‌های فرم، انجام می‌دهیم. این ngModelها، به یک خاصیت عمومی که متناظر است با وهله‌ای از شیء مدل فرم، متصل هستند. بنابراین این مدل، در هر لحظه، بیانگر آخرین تغییرات کاربر است و از آن می‌توان برای ارسال اطلاعات به سرور استفاده کرد.
     8) پس از اتصال فرم به کلاس متناظر با آن، اکنون سرویس محصولات را تکمیل کرده و به آن متد HTTP Post را جهت ارسال اطلاعات سمت کاربر، به سرور، اضافه می‌کنیم. در اینجا نکته‌ی مهم، تنظیم content type ارسالی به سمت سرور است. در غیراینصورت فریم ورک سمت سرور قادر به تشخیص JSON بودن این اطلاعات نخواهد شد.
    پاسخ به بازخورد‌های پروژه‌ها
    تنظیم عناصر گزارش
    - مراجعه کنید به مجموعه مثال‌های این کتابخانه که همراه سورس آن است. مثلا (^ و ^ و ^)
    - به علاوه برچسب PdfReport را که در سایت پیگیری کنید این موارد بحث شدن:
    «سفارشی سازی Header و Footer در PdfReport»

    ضمنا در PdfReport یک هدر و یک فوتر بیشتر وجود ندارد. اما به ازای هر صفحه، یکبار callback آن‌ها فراخوانی خواهند شد. یعنی می‌تونید در صفحات مختلف، هدرها و فوترهای متفاوتی رو طراحی کنید یا اینکه همه رو ثابت در نظر بگیرید.
    فایل‌های پروژه‌ها
    PdfRpt-1.5.zip
    - کاهش حجم نهایی فایل تولیدی با کش کردن تصاویر
    - به تاریخ نمایش داده شده در DefaultFooter ، پشتیبانی از RTL اضافه شد.
    - یک تغییر کوچک: هر جایی PdfPTable بود به PdfGrid تبدیل شد.
    - چندین مثال جدید اضافه شدند (
    ^):
    نحوه استفاده از html برای تعریف header و همچنین footer
    نحوه تعریف بارکد
    و مثال InlineProviders برای ساده سازی تعاریف هدرها و فوترهای سفارشی
    نظرات مطالب
    ASP.NET MVC #23
    با عرض سلام و تشکر چند سوال داشتم
    1- تنظیم .* در iis5  با خطای wrong extension format مواجه می‌شود آیا راهی برای اصلاح آن وجود دارد.
    2- اگر سیستم مسریابی را پسونددار کنیم چگونه به روش مناسبی می‌توانیم همه جای پروژه را کنترل کنیم که مسیریابی دچار مشکل نشود ازجمله در area
    3- چگونه بفهمیم که iis یکپارچه است یا کلاسیک
    4
    - آیا iis7 مد یکپارچه آن در ویندوز سرور 2003 و 2008 قابل نصب است
    5-آیا برای ویندوز 8 تنظیم خاصی نیاز دارد . من یک مثال ساده را اجرا کردم و برنامه را بر روی iis قرار دادم با خطای 403 forbidden مربوط به صفحه آغازین مواجه شدم
    6- طبق روش گفته شده در آدرس زیر نمی‌توان یک صفحه آغازین دستی درست کرد و در iis تنظیم کرد مثلا deafualt.aspx و در لود آن مستقیما ادامه کار را به داخل مسیریابی mvc  هدایت کرد
    http://weblog.west-wind.com/posts/2013/Aug/15/IIS-Default-Documents-vs-ASPNET-MVC-Routes