مطالب
توسعه‌ی Micro Frontends با Webpack
Micro Frontend چیست؟

micro frontend یک الگوی معماری (architecture pattern) می‌باشد؛ جایی که یک front-end app، به چند app  کوچکتر تقسیم می‌شود و هر کدام از آن‌ها به صورت مستقل  توسعه داده و تست می‌شوند.  مفهومی شبیه به مایکروسرویس‌ها است؛ اما برای سورس کد‌های یکپارچه‌ی سمت کلاینت. 


چرا؟
خیلی سخت است که بخواهیم روی سورس کد‌های یکپارچه سمت کلاینت تست نویسی، به‌روز رسانی و هم چنین نگهداری کنیم. این در حالی است که توانایی تیم را به منظور مستقل کار کردن بر روی بخش‌های مختلفی از app، محدود می‌کند. شکستن یک app یکپارچه به micro frontend‌های کوچکتر و قابل مدیریت، این امکان را فراهم میسازد که چندین تیم، به صورت مستقل کار کنند و از فریم ورک‌های ترجیحی خود استفاده کنند.

چگونه؟
اساسا 3 راه برای ادغام کردن ماژول‌های micro frontend  با container app وجود دارد. 

 1-Server integration

هر micro frontend در یک وب سرور  احتمالا جداگانه هاست شده‌است که مسئول رندر کردن و خدمت دادن markup‌های مربوطه می‌باشد. به محض دریافت درخواستی از سمت مرورگر، container app در خواست را برای markup، با برقراری تماس به سرور، برای micro frontend مربوطه انجام میدهد. 
این یک روش ایده آل نمی‌باشد؛ به‌طوریکه چندین تماس به سرور برای رندر کردن محتوا در صفحه برقرار می‌شود و  همچنین مستلزم پیاده سازی استراتژی cache، به منظور کاهش تاخیر است. 

2-Compile time integration

container app دسترسی به کد‌های micro frontend‌ها را در طول توسعه و زمان کامپایل دارد. یکی  از راه‌های انجام این روش این است که micro frontend‌ها را به عنوان بسته‌های npm منتشر کنیم و سپس از آن‌ها به عنوان یک وابستگی در container app استفاده کنیم. 
در حالیکه راه اندازی و پیاده سازی، در این حالت ساده است، اما یک وابستگی محکم بین container app  و micro frontend وجود دارد. هر زمانکه یک micro frontend بروزرسانی می‌شود، نیاز است که container app ،  به منظور یکپارچه کردن بروز رسانی، دوباره استقرار یابد.

3-Run time integration

container app دسترسی به کد‌های micro frontend‌ها را زمانیکه در مرورگر اجرا می‌شوند، دارد. یکی از راه‌های انجام این روش، استفاده از پلاگین Module Federation مربوط به Webpack است که مراقب ساختن، در دسترس قرار دادن و استفاده از وابستگی‌ها در زمان اجرا می‌باشد (در ادامه، این حالت را با جزئیات بیشتری مورد بررسی قرار خواهیم داد). 
در این حالت وابستگی بین container app و micro frontend‌ها وجود ندارد و یکپارچگی در زمان اجرا اتفاق می‌افتد. هر micro frontend می‌تواند به صورت مستقل توسعه داده شود و استقرار یابد، بدون اینکه container app را دوباره استقرار دهیم.
در این حالت راه اندازی در مقایسه با compile-time integration پیچیده‌تر است.



Webpack Module Federation Plugin

پلاگین module federation در Webpack 5.0 معرفی شد که  امکان توسعه app‌های micro frontend را با بارگذاری پویای کد‌های app‌های micro frontend را در container app ، فراهم میسازد. 
همچنین این امکان را فراهم می‌کند که dependency ها را بین remote app‌ها و host app، به منظور جلوگیری از کد‌های تکراری و کاهش دادن سایز build، به اشتراک بگذاریم.
 در این مقاله ما یک مثال را بررسی خواهیم کرد که شامل دو micro frontend ساده می‌باشد و سپس آن‌ها را در یک host app ادغام می‌کنیم. 
ساختار نهایی به‌صورت زیر خواهد بود:



ایجاد کردن اولین Remote app


یک پوشه را به نام remote1 ایجاد کنید و سپس یک فایل را به نام package.json، در پوشه‌ی ایجاد شده، با دستور زیر ایجاد کنید. 
npm init --yes
پوشه‌ی ایجاد شده را در code editor خود باز کنید (من از vs code استفاده می‌کنم) و سپس وابستگی‌های زیر را به فایل package.json اضافه کنید. 
npm install html-webpack-plugin webpack webpack-cli webpack-dev-server --save

1) webpack/ webpack-CLI: برای استفاده از webpack و دستورات webpack CLI
2) html-webpack-plugin/webpack-devserver: سرور توسعه محلی با live reloading

 و همچنین اسکریپت webpack serve را در بخش scripts، به منظور serve کردن application در مرورگر اضافه کنید.
اکنون فایل package.json شما همانند زیر می‌باشد: 
{
  "name": "remote1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "html-webpack-plugin": "^5.3.2",
    "webpack": "^5.57.0",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.3.1"
  }
}

در ادامه، یک پوشه‌ی جدید را به نام public  ایجاد کنید و یک فایل را به نام index.html در پوشه‌ی public اضافه کنید سپس HTML markup زیر را درون فایل index.html اضافه کنید، که شامل یک div نگهدارنده می‌باشد، جائیکه خروجی app در زمان توسعه، در آن قرار میگیرد. 
<!DOCTYPE html>
<html>

<head>
    <title>
        Remote1(Localhost:7001)
    </title>
</head>

<body>
    <div id="dev-remote1"></div>
</body>

</html>

در ادامه یک پوشه‌ی جدید را به نام src  ایجاد کنید و دو فایل را با نام‌های index.js و startup.js در آن قرار دهید. در ادامه به این دو فایل برمیگردیم و کد‌های لازم را در آن قرار میدهیم.
یک فایل جدید را به نام webpack.config.js در ریشه‌ی پروژه ایجاد می‌کنیم که در آن تنظیمات webpack  را قرار میدهیم. در این فایل، دو پلاگین را به نام‌های Webpack و Module Federation، اضافه می‌کنیم.
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  mode: 'development',
  devServer: {
    port: 7001,
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'remote1',
      filename: 'remoteEntry.js',
      exposes: {
        './RemoteApp1': './src/startup',
      },
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
};

فایل remoteEntry.js شامل یک لیست از فایل‌های در معرض قرار داده شده‌ی توسط remote app به همراه مسیر‌های آنها می‌باشد. از این فایل در زمان ادغام کردن remote app در host app استفاده می‌شود.  
index.js نقطه‌ی ورودی remote app ما می‌باشد.  به منظور جلوگیری از eager loading، کد‌های startup را در یک js فایل جداگانه به نام startup.js قرار میدهیم. از این رو فایل index.js  شامل فقط یک import می‌باشد. 
import('./startup');
در درون فایل startup.js ، یک تابع به نام mount را export می‌کنیم. این تابع یک element را دریافت می‌کند؛ جائیکه قرار است خروجی app در آن قرار گیرد. در حالت development، خروجی در یک div نگهدارنده با شناسه dev-remote1 در فایل محلی index.html قرار میگیرد.
const mount = (el) => {
    el.innerHTML = '<div>Remote 1 Content</div>';
  };
  
  if (process.env.NODE_ENV === 'development') {
    const el = document.querySelector('#dev-remote1');
    if (el) {
      mount(el);
    }
  }
  
  export { mount };
فایل‌ها را ذخیره کنید و سپس دستور npm start را جهت مشاهده‌ی خروجی اجرا کنید. در اینجا برنامه بر روی پورت 7001 اجرا می‌شود . ( http://localhost:7001  )


ایجاد کردن دومین Remote app  


در اینجا نیز مراحل، دقیقا شبیه به ایجاد remote app قبلی می‌باشد. یک پوشه را به نام remote2 در کنار پوشه‌ی remote1 ایجاد کنید و یک فایل را به نام package.json، با وابستگی‌های معرفی شده ایجاد کنید و سپس دستور npm install را بزنید تا وابستگی‌ها نصب شوند.
{
  "name": "remote2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "html-webpack-plugin": "^5.3.2",
    "webpack": "^5.57.0",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.3.1"
  }
}
سپس یک فایل را با نام index.html و با محتوای زیر، در پوشه‌ی public ایجاد کنید:
<!DOCTYPE html>
<html>

<head>
  <title>
    Remote2(Localhost:7002)
  </title>
</head>

<body>
  <div id="dev-remote2"></div>
</body>

</html>

در ادامه یک فایل را با نام webpack.config.js در ریشه‌ی پروژه‌ی remote2 ایجاد کنید و محتوای زیر را در آن قرار دهید. مطمئن باشید که پورت اجرایی برنامه 7002 می‌باشد.
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  mode: 'development',
  devServer: {
    port: 7002,
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'remote2',
      filename: 'remoteEntry.js',
      exposes: {
        './RemoteApp2': './src/startup',
      },
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
};

فایل فایل index.js برای remote2
import('./startup');
فایل startup.js  برای remote2
const mount = (el) => {
    el.innerHTML = '<div>Remote 2 Content</div>';
  };
  
  if (process.env.NODE_ENV === 'development') {
    const el = document.querySelector('#dev-remote2');
    if (el) {
      mount(el);
    }
  }
  
  export { mount };

اکنون می‌توانید با اجرای دستور npm start برنامه را بر روی پورت 7002 اجرا کنید . ( http://localhost:7002 ) 

ایجاد کردن Host app و یکپارچه کردن آن با Remote app  ها


 یک پوشه‌ی جدید را به نام container در کنار دو پوشه‌ی قبلی (remote1, remote2) ایجاد کنید. در پوشه‌ی ایجاد شده، یک فایل را به نام package.json ایجاد کنید و محتوای زیر را در آن قرار دهید و سپس دستور npm install را بزنید تا لیست وابستگی‌ها دریافت شود. 
{
  "name": "container",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "html-webpack-plugin": "^5.3.2",
    "webpack": "^5.57.0",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.3.1"
  }
}

اکنون یک پوشه را به نام public، در ریشه‌ی پروژه ایجاد کنید و یک فایل را به نام index.html، در آن قرار دهید. در این فایل دو div  نگهدارنده به منظور هاست کردن محتوا، از هر remote app  قرار دارد.
<!DOCTYPE html>
<html>
  <head> 
    <title>Host App (Localhost:7000)</title>
  </head>
  <body>
    <div id="remote1-app"></div>
    <div id="remote2-app"></div>
  </body>
</html>
یک پوشه به نام src، در ریشه پروژه ایجاد کنید و دو فایل را با نام‌های index.js و startup.js، در آن قرار دهید. کمی جلوتر به این دو فایل می‌پردازیم. 

یک فایل را با نام  webpack.config.js، با تنظیمات زیر در ریشه‌ی پروژه قرار دهید. در اینجا پورت اجرایی برنامه، 7000 تعیین شده‌است:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  mode: 'development',
  devServer: {
    port: 7000,
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'container',
      remotes: {
        remote1: 'remote1@http://localhost:7001/remoteEntry.js',
        remote2: 'remote2@http://localhost:7002/remoteEntry.js',
      },
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
};

برای خصوصیت remotes در پلاگین Module Federation باید remote appهای را تعریف کنیم که container app می‌خواهد به آن دسترسی داشته باشد. خصوصیت remotes شامل زوج کلید/مقدارها  (key/value) می‌باشد و در اینجا کلید، رشته و مقدار هم، رشته است. مقدار (value) برای کلید (key) با نام remote app شروع میشود که آن را در بخش تنظیمات پلاگین module federation مربوط به remote app مربوطه قرار داده‌ایم. سپس @ قرار میگیرد و در ادامه آن، آدرس جایی را که remoteEntry.js مربوط به remote app  قرار دارد، می‌نویسیم.

 
 
دقیقا مثل remote app ها، در فایل index.js مربوط به import ، host app زیر را انجام میدهیم: 
import('./startup');
در فایل remote app ، startup.js ‌ها را همانند زیر import می‌کنیم و سپس آن‌ها را در فایل index.html میزبان سوار می‌کنیم.
import { mount as remote1Mount } from 'remote1/RemoteApp1';
import { mount as remote2Mount } from 'remote2/RemoteApp2';

remote1Mount(document.querySelector('#remote1-app'));
remote2Mount(document.querySelector('#remote2-app'));

در ادامه جهت مشاهده خروجی، app میزبان را با دستور npm start اجرا می‌کنیم. اکنون شما می‌توانید خروجی remote app ‌ها را در host app  ببینید. لازم به ذکر است که در هنگام اجرای دستور npm start  برای host app ، هر دو remote app  ایجاد شده باید در حالت اجرا باشند. 



ملاحظات

Module federation در Webpack  نسخه 5 به بالا، در دسترس قرار دارد. شما می‌توانید وابستگی‌های بین remote app و host app را به اشتراک بگذارید. این کار را با اضافه کردن آن‌ها به تنظیمات پلاگین module federation برای remote app و host app  انجام دهید.
new ModuleFederationPlugin({
  name: 'remote1',
  filename: 'remoteEntry.js',
  exposes: {
    './RemoteApp1': './src/startup',
  },
  shared:['react', 'react-dom']
}),

ارتباط بین host و remote app می‌تواند از طریق callback‌ها انجام شود. 
 

اشتراک‌ها
عرضه کتابخانه HTTP Client Libraries RC
این کتابخانه امکان استفاده از HttpClient برای ارسال درخواست‌ها بر روی HTTP در برنامه‌های مدرنی که با Silverlight 4,5 Windows Phone 7.5,8 و Portable Class Libraries را فراهم می‌کند
عرضه کتابخانه HTTP Client Libraries RC
مطالب
نمایش، ذخیره و چاپ فایل‌های PDF در برنامه‌های Angular
با توجه به اینکه فایل‌های PDF نیز فایل باینری هستند، کلیات نکات مطلب «دریافت و نمایش تصاویر از سرور در برنامه‌های Angular» در مورد آن‌ها هم صادق است. در اینجا به تکمیل این نکات پرداخته و مواردی را مانند ذخیره، چاپ و استفاده از اشیاء نمایشی <object>، <embed> و <iframe> نیز بررسی می‌کنیم. نمایش PDF در اینجا بر اساس امکانات توکار مرورگرها صورت می‌گیرد و نیاز به افزونه‌ی اضافه‌تری ندارد.


کدهای سمت سرور دریافت فایل PDF

در اینجا کدهای سمت سرور برنامه، نکته‌ی خاصی را به همراه نداشته و صرفا یک فایل PDF ساده (محتوای باینری) را بازگشت می‌دهد:
using Microsoft.AspNetCore.Mvc;

namespace AngularTemplateDrivenFormsLab.Controllers
{
    [Route("api/[controller]")]
    public class ReportsController : Controller
    {
        [HttpGet("[action]")]
        public IActionResult GetPdfReport()
        {
            return File(virtualPath: "~/assets/sample.pdf",
                        contentType: "application/pdf",
                        fileDownloadName: "sample.pdf");
        }
    }
}
که در نهایت با آدرس api/Reports/GetPdfReport در سمت کلاینت قابل دسترسی خواهد بود.


سرویس دریافت محتوای باینری در برنامه‌های Angular

برای اینکه HttpClient برنامه‌های Angular بتواند محتوای باینری را بجای محتوای JSON پیش‌فرض آن دریافت کند، نیاز است نوع خروجی سمت سرور آن‌را به blob تنظیم کرد:
import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { HttpClient } from "@angular/common/http";

@Injectable()
export class DownloadPdfDataService {

  constructor(private httpClient: HttpClient) { }

  public getReport(): Observable<Blob> {
    return this.httpClient.get("/api/Reports/GetPdfReport", { responseType: "blob" });
  }
}
به این ترتیب پس از اشتراک به متد getReport این سرویس، اطلاعات باینری این فایل PDF را دریافت خواهیم کرد.


اصلاح Content Security Policy سمت سرور جهت ارائه‌ی محتوای blob

پس از دریافت فایل PDF به صورت یک blob، با استفاده از متد URL.createObjectURL می‌توان آدرس موقت محلی را برای دسترسی به آن تولید کرد و یک چنین آدرس‌هایی به صورت blob:http تولید می‌شوند. در این حالت در Content Security Policy سمت سرور، نیاز است امکان دسترسی به تصاویر و همچنین اشیاء از نوع blob را نیز آزاد معرفی کنید:
img-src 'self' data: blob:
default-src 'self' blob:
object-src 'self' blob:
در غیراینصورت مرورگر نمایش یک چنین تصاویر و یا اشیایی را سد خواهد کرد.


دریافت فایل‌های PDF از سرور و نمایش آن‌ها در یک برنامه‌ی Angular

پس از این مقدمات، کامپوننتی که یک فایل PDF را از سمت سرور دریافت کرده و نمایش می‌دهد، چنین کدی را خواهد داشت:
import { DownloadPdfDataService } from "./../download-pdf-data.service";
import { WindowRefService } from "./../../core/window.service";
import { Component, OnInit } from "@angular/core";
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";

@Component({
  templateUrl: "./view-pdf.component.html",
  styleUrls: ["./view-pdf.component.css"]
})
export class ViewPdfComponent implements OnInit {
  private nativeWindow: Window;
  private pdfBlobUrl: string;
  sanitizedPdfBlobResourceUrl: SafeResourceUrl;

  constructor(private downloadService: DownloadPdfDataService,
    private windowRefService: WindowRefService, private sanitizer: DomSanitizer) { }

  ngOnInit() {
    this.nativeWindow = this.windowRefService.nativeWindow;
    this.downloadService.getReport().subscribe(pdfDataBlob => {
      console.log("pdfDataBlob", pdfDataBlob);
      const urlCreator = this.nativeWindow.URL;
      this.pdfBlobUrl = urlCreator.createObjectURL(pdfDataBlob);
      console.log("pdfBlobUrl", this.pdfBlobUrl);
      this.sanitizedPdfBlobResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfBlobUrl);
    });
  }
}
با این قالب:
<h1>Display PDF Files</h1>

<div *ngIf="sanitizedPdfBlobResourceUrl">
  <h4>using iframe</h4>
  <iframe width="100%" height="600" [attr.src]="sanitizedPdfBlobResourceUrl" type="application/pdf"></iframe>
  <h4>using object</h4>
  <object [attr.data]="sanitizedPdfBlobResourceUrl" type="application/pdf" width="100%"
    height="100%"></object>
  <h4>usin embed</h4>
  <embed [attr.src]="sanitizedPdfBlobResourceUrl" type="application/pdf" width="100%"
    height="100%">
</div>
- در اینجا در ngOnInit، به سرویس پنجره دسترسی یافته و وهله‌ای از آن‌را جهت کار با متد createObjectURL شیء URL آن دریافت می‌کنیم.
- سپس مشترک متد getReport دریافت فایل PDF شده و اطلاعات نهایی آن‌را به صورت pdfDataBlob دریافت می‌کنیم.
- این اطلاعات باینری را به متد createObjectURL ارسال کرده و آدرس موقتی این تصویر را در مرورگر بدست می‌آوریم.
- چون در این حالت Angular این URL را امن سازی می‌کند، یک چنین خروجی unsafe:blob بجای blob تولید خواهد شد که نمایش این مورد نیز توسط مرورگر سد می‌شود. برای رفع این مشکل، می‌توان از سرویس DomSanitizer آن که به سازنده‌ی کلاس تزریق شده‌است استفاده کرد:
this.sanitizedPdfBlobResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfBlobUrl);
تفاوت این مورد با حالت نمایش تصویر، استفاده از متد bypassSecurityTrustResourceUrl بجای متد bypassSecurityTrustUrl است. از این جهت که اشیاء یاد شده نیاز به SafeResourceUrl دارند و نه SafeUrl.
اینبار یک چنین انتسابی به صورت مستقیم کار می‌کند که سه نمونه‌ی این انتساب را به اشیاء iframe ،object و embed، در قالب فوق مشاهده می‌کنید.



افزودن دکمه‌ی چاپ PDF به برنامه

پس از اینکه به this.pdfBlobUrl دسترسی یافتیم، اکنون می‌توان یک iframe مخفی را ایجاد کرد، سپس src آن‌را به این آدرس ویژه تنظیم نمود و در آخر متد print آن‌را فراخوانی کرد که سبب نمایش خودکار دیالوگ چاپ مرورگر می‌شود:
  printPdf() {
    const iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.src = this.pdfBlobUrl;
    document.body.appendChild(iframe);
    iframe.contentWindow.print();
  }


نمایش فایل PDF در یک برگه‌ی جدید

اگر علاقمند بودید تا این فایل PDF را به صورت تمام صفحه و در برگه‌ای جدید نمایش دهید، می‌توان از متد window.open استفاده کرد:
  showPdf() {
    this.nativeWindow.open(this.pdfBlobUrl);
  }


دریافت فایل PDF

بجای نمایش فایل PDF می‌توان دکمه‌ای را بر روی صفحه قرار داد که با کلیک بر روی آن، این فایل توسط مرورگر به صورت متداولی جهت دریافت به کاربر ارائه شود:
  downloadPdf() {
    const fileName = "test.pdf";
    const anchor = document.createElement("a");
    anchor.style.display = "none";
    anchor.href = this.pdfBlobUrl;
    anchor.download = fileName;
    document.body.appendChild(anchor);
    anchor.click();
  }
در اینجا یک anchor جدید به صورت مخفی به صفحه اضافه می‌شود که href آن به this.pdfBlobUrl تنظیم شده‌است. سپس متد click آن فراخوانی خواهد شد. نام این فایل را هم توسط ویژگی download این شیء می‌توان تنظیم نمود.
این روش در مورد تدارک دکمه‌ی دریافت تمام blobهای دریافتی از سرور کاربرد دارد و منحصر به فایل‌های PDF نیست.


کدهای کامل این مطلب را از اینجا می‌توانید دریافت کنید.
مطالب
افزودن یک صفحه‌ی جدید و دریافت و نمایش اطلاعات از سرور به کمک Ember.js
در قسمت قبل با مقدمات برپایی یک برنامه‌ی تک صفحه‌ای وب مبتنی بر Ember.js آشنا شدیم. مثال انتهای بحث آن نیز یک لیست ساده را نمایش می‌دهد. در ادامه همین برنامه را جهت نمایش لیستی از اشیاء JSON دریافتی از سرور تغییر خواهیم داد. همچنین یک صفحه‌ی about را نیز به آن اضافه خواهیم کرد.


پیشنیازهای سمت سرور

- ابتدا یک پروژه‌ی خالی ASP.NET را ایجاد کنید. نوع آن مهم نیست که Web Forms باشد یا MVC.
- سپس قصد داریم مدل کاربران سیستم را توسط یک ASP.NET Web API Controller در اختیار Ember.js قرار دهیم. مباحث پایه‌ای Web API نیز در وب فرم‌ها و MVC یکی است.
مدل سمت سرور برنامه چنین شکلی را دارد:
namespace EmberJS02.Models
{
    public class User
    {
        public int Id { set; get; }
        public string UserName { set; get; }
        public string Email { set; get; }
    }
}
کنترلر Web API ایی که این اطلاعات را در ختیار کلاینت‌ها قرار می‌دهد، به نحو ذیل تعریف می‌شود:
using System.Collections.Generic;
using System.Web.Http;
using EmberJS02.Models;
 
namespace EmberJS02.Controllers
{
    public class UsersController : ApiController
    {
        // GET api/<controller>
        public IEnumerable<User> Get()
        {
            return UsersDataSource.UsersList;
        }
    }
}
در اینجا UsersDataSource.UsersList صرفا یک لیست جنریک ساده از کلاس User است و کدهای کامل آن‌را می‌توانید از فایل پیوست انتهای بحث دریافت کنید.

همچنین فرض بر این است که مسیریابی سمت سرور ذیل را نیز به فایل global.asax.cs، جهت فعال سازی دسترسی به متدهای کنترلر UsersController تعریف کرده‌اید:
using System;
using System.Web.Http;
using System.Web.Routing;
 
namespace EmberJS02
{
    public class Global : System.Web.HttpApplication
    { 
        protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.MapHttpRoute(
               name: "DefaultApi",
               routeTemplate: "api/{controller}/{id}",
               defaults: new { id = RouteParameter.Optional }
               );
        }
    }
}

پیشنیازهای سمت کاربر

پیشنیازهای سمت کاربر این قسمت با قسمت «تهیه‌ی اولین برنامه‌ی Ember.js» دقیقا یکی است.
ابتدا فایل‌های مورد نیاز Ember.js به برنامه اضافه شده‌اند:
 PM> Install-Package EmberJS
سپس یک فایل app.js با محتوای ذیل به پوشه‌ی Scripts اضافه شده‌است:
App = Ember.Application.create();
App.IndexRoute = Ember.Route.extend({
    setupController:function(controller) {
        controller.set('content', ['red', 'yellow', 'blue']);
    }
});
و  در آخر یک فایل index.html با محتوای ذیل کار برپایی اولیه‌ی یک برنامه‌ی مبتنی بر Ember.js را انجام می‌دهد:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-2.1.1.js" type="text/javascript"></script>
    <script src="Scripts/handlebars.js" type="text/javascript"></script>
    <script src="Scripts/ember.js" type="text/javascript"></script>
    <script src="Scripts/app.js" type="text/javascript"></script>
</head>
<body>
    <script type="text/x-handlebars" data-template-name="application">
        <h1>Header</h1>
        {{outlet}}
    </script>
    <script type="text/x-handlebars" data-template-name="index">
        Hello,
        <strong>Welcome to Ember.js</strong>!
        <ul>
            {{#each item in content}}
            <li>
                {{item}}
            </li>
            {{/each}}
        </ul>
    </script>
</body>
</html>
تا اینجا را در قسمت قبل مطالعه کرده بودید.
در ادامه قصد داریم به هدر صفحه، دو لینک Home و About را اضافه کنیم؛ به نحوی که لینک Home به مسیریابی index و لینک About به مسیریابی about که صفحه‌ی جدید «درباره‌ی برنامه» را نمایش می‌دهد، اشاره کنند.


تعریف صفحه‌ی جدید About

برنامه‌های Ember.js، برنامه‌های تک صفحه‌ای وب هستند و صفحات جدید در آن‌ها به صورت یک template جدید تعریف می‌شوند که نهایتا متناظر با یک مسیریابی مشخص خواهند بود.
به همین جهت ابتدا در فایل app.js مسیریابی about را اضافه خواهیم کرد:
App.Router.map(function() {
    this.resource('about');
});
به این ترتیب با فراخوانی آدرس about/ در مرورگر توسط کاربر، منابع مرتبط با این آدرس و قالب مخصوص آن، توسط Ember.js پردازش خواهند شد.
بنابراین به صفحه‌ی index.html برنامه مراجعه کرده و صفحه‌ی about را توسط یک قالب جدید تعریف می‌کنیم:
<script type="text/x-handlebars" data-template-name="about">
    <h2>Our about page</h2>
</script>
تنها نکته‌ی مهم در اینجا مقدار data-template-name است که سبب خواهد شد تا به مسیریابی about، به صورت خودکار متصل و مرتبط شود.

در این حالت اگر برنامه را در حالت معمولی اجرا کنید، خروجی خاصی را مشاهده نخواهید کرد. بنابراین نیاز است تا لینکی را جهت اشاره به این مسیر جدید به صفحه اضافه کنیم:
<script type="text/x-handlebars" data-template-name="application">
    <h1>Ember Demo App</h1>
    <ul class="nav">
        <li>{{#linkTo 'index'}}Home{{/linkTo}}</li>
        <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
    </ul>
    {{outlet}}
</script>
اگر از قسمت قبل به خاطر داشته باشید، عنوان شد که قالب ویژه‌ی application به صورت خودکار با وهله سازی Ember.Application.create به صفحه اضافه می‌شود. اگر نیاز به سفارشی سازی آن وجود داشت، خصوصا جهت تعریف عناصری که باید در تمام صفحات حضور داشته باشند (مانند منوها)، می‌توان آن‌را به نحو فوق سفارشی سازی کرد.
در اینجا با استفاده از امکان یا directive ویژه‌ای به نام linkTo، لینک‌هایی به مسیریابی‌های index و about اضافه شده‌اند. به این ترتیب اگر کاربری برای مثال بر روی لینک About کلیک کند، کتابخانه‌ی Ember.js او را به صورت خودکار به مسیریابی about و سپس نمایش قالب مرتبط با آن (قالب about ایی که پیشتر تعریف کردیم) هدایت خواهد کرد؛ مانند تصویر ذیل:


همانطور که در آدرس صفحه نیز مشخص است، هرچند صفحه‌ی about نمایش داده شده‌است، اما هنوز نیز در همان صفحه‌ی اصلی برنامه قرار داریم. به علاوه در این قسمت جدید، همچنان منوی بالای صفحه نمایان است؛ از این جهت که تعاریف آن به قالب application اضافه شده‌اند.


دریافت و نمایش اطلاعات از سرور

اکنون که با نحوه‌ی تعریف یک صفحه‌ی جدید و برپایی سیم کشی‌های مرتبط با آن آشنا شدیم، می‌خواهیم صفحه‌ی دیگری را به نام Users به برنامه اضافه کنیم و در آن لیست کاربران ارائه شده توسط کنترلر Web API سمت سرور ابتدای بحث را نمایش دهیم.
بنابراین ابتدا مسیریابی جدید users را به صفحه اضافه می‌کنیم تا لیست کاربران، در آدرس users/ قابل دسترسی شود:
App.Router.map(function() {
    this.resource('about');
    this.resource('users');
});
سپس نیاز است مدلی را توسط فراخوانی Ember.Object.extend ایجاد کرده و به کمک متد reopenClass آن‌را توسعه دهیم:
App.UsersLink = Ember.Object.extend({});
App.UsersLink.reopenClass({
    findAll: function () {
        var users = [];
        $.getJSON('/api/users').then(function(response) {
            response.forEach(function(item) {
                users.pushObject(App.UsersLink.create(item));
            });
        });
        return users;
    }
});
در اینجا متد دلخواهی را به نام findAll اضافه کرده‌ایم که توسط متد getJSON جی‌کوئری، به مسیر /api/users سمت سرور متصل شده و لیست کاربران را از سرور به صورت JSON دریافت می‌کند. در اینجا خروجی دریافتی از سرور به کمک متد pushObject به آرایه کاربران اضافه خواهد شد. همچنین نحوه‌ی فراخوانی متد create مدل UsersLink را نیز در اینجا مشاهده می‌کنید (App.UsersLink.create).

پس از اینکه نحوه‌ی دریافت اطلاعات از سرور مشخص شد، باید اطلاعات این مدل را در اختیار مسیریابی Users قرار داد:
App.UsersRoute = Ember.Route.extend({
    model: function() {
        return App.UsersLink.findAll();
    }
});
 
App.UsersController = Ember.ObjectController.extend({
    customHeader : 'Our Users List'
});
به این ترتیب زمانیکه کاربر به مسیر users/ مراجعه می‌کند، سیستم مسیریابی می‌داند که اطلاعات مدل خود را باید از کجا تهیه نماید.
همچنین در کنترلری که تعریف شده، صرفا یک خاصیت سفارشی و دلخواه جدید، به نام customHeader برای نمایش در ابتدای صفحه تعریف و مقدار دهی گردیده‌است.
اکنون قالبی که قرار است اطلاعات مدل را نمایش دهد، چنین شکلی را خواهد داشت:
<script type="text/x-handlebars" data-template-name="users">
    <h2>{{customHeader}}</h2>
    <ul>
        {{#each item in model}}
        <li>
            {{item.Id}}-{{item.UserName}} ({{item.Email}})
        </li>
        {{/each}}
    </ul>
</script>
با تنظیم data-template-name به users سبب خواهیم شد تا این قالب اطلاعات خودش را از مسیریابی users دریافت کند. سپس یک حلقه نوشته‌ایم تا کلیه عناصر موجود در مدل را خوانده و در صفحه نمایش دهد. همچنین در عنوان قالب نیز از خاصیت سفارشی customHeader استفاده شده‌است:




کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید:
EmberJS02.zip
نظرات مطالب
اعتبارسنجی مبتنی بر کوکی‌ها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
با سلام؛ من از روش بالا برای بحث اعتبارسنجی  و دسترسی به کنترل و اکشن استفاده کردم. اگر کوکی منقضی شودبه صفحه لاگین هدایت می‌شود. تغییری در برنامه دادم اگر کوکی منقضی شد در همان صفحه جاری  پنجره‌ای به صورت مدال باز شود لاگین را انجام دهد. فرم مدال بصورت ajax سمت سرور می‌رود هنگام لاگین مدال. برنامه رو دیباگ کردم کوکی را درست می‌سازد و پر می‌کند. ولی هنگامی که روی اکشنی  کلیک میکنم مقدار کوکی ست نشده خالی هست. عدم دسترسی میدهد. به عبارتی user.Identity.IsAuthenticated رو false بر میگردونه. آیا مشکل درخواست‌های اژاکسی می‌باشد؟ با تشکر
مطالب
استفاده از Kendo UI TreeView به همراه یک منبع داده راه دور
یکی دیگر از ویجت‌های Kendo UI، ویجت نمایش ساختارهای درختی است به نام TreeView. در ادامه قصد داریم با نحوه‌ی نمایش آن، به کمک اطلاعات JSON دریافتی از سرور آشنا شویم.



ساختار مورد نیاز یک Kendo UI Tree View

فرض کنید قصد دارید نظرات تو در توی مطلبی را توسط Kendo UI Tree View نمایش دهید. مدل خود ارجاع دهنده‌ی آن می‌تواند چنین شکلی را داشته باشد:
namespace KendoUI11.Models
{
    public class BlogComment
    {
        public int Id { set; get; }
 
        public string Body { set; get; }
 
        public int? ParentId { get; set; }
 
        // مخصوص کندو یو آی هستند
        public bool HasChildren { get; set; }
        public string imageUrl { get; set; }
    }
}
سه خاصیت اول این کلاس همواره در تمام کلاس‌های خود ارجاع دهنده حضور دارند؛ شماره ردیف، متن و شماره Id والد احتمالی.
چند خاصیت بعدی مانند HasChildren و imageUrl مخصوص Kendo UI هستند. از imageUrl اختیاری می‌توان جهت نمایش آیکنی در کنار یک آیتم استفاده کرد و HasChildren به این معنا است که آیا گره جاری دارای عناصر فرزندی می‌باشد یا خیر.


تهیه یک منبع داده نمونه

شکل ابتدای مطلب، از طریق منبع داده ذیل تهیه شده‌است:
using System.Collections.Generic;
 
namespace KendoUI11.Models
{
    /// <summary>
    /// منبع داده فرضی جهت سهولت دموی برنامه
    /// </summary>
    public static class BlogCommentsDataSource
    {
        private static readonly IList<BlogComment> _cachedItems;
        static BlogCommentsDataSource()
        {
            _cachedItems = createBlogCommentsDataSource();
        }
 
        public static IList<BlogComment> LatestComments
        {
            get { return _cachedItems; }
        }
 
        /// <summary>
        /// هدف صرفا تهیه یک منبع داده آزمایشی ساده تشکیل شده در حافظه است
        /// </summary>
        private static IList<BlogComment> createBlogCommentsDataSource()
        {
            var list = new List<BlogComment>();
 
            var comment1 = new BlogComment
            {
                Id = 1, Body = "نظر من این است که", HasChildren = true, ParentId = null
            };
            list.Add(comment1);
 
            var comment12 = new BlogComment
            {
                Id = 2, Body = "پاسخی به نظر اول", HasChildren = true, ParentId = 1
            };
            list.Add(comment12);
 
            var comment12A = new BlogComment
            {
                Id = 3, Body = "پاسخی دیگری به نظر اول", HasChildren = false, ParentId = 1
            };
            list.Add(comment12A);
 
            var comment121 = new BlogComment
            {
                Id = 4, Body = "پاسخی به پاسخ به نظر اول", HasChildren = false, ParentId = 2
            };
            list.Add(comment121);
 
            var comment2 = new BlogComment
            {
                Id = 5, Body = "نظر 2", HasChildren = true, ParentId = null, imageUrl= "images/search.png"
            };
            list.Add(comment2);
 
            var comment21 = new BlogComment
            {
                Id = 6, Body = "پاسخ به نظر 2", HasChildren = false, ParentId = 5
            };
            list.Add(comment21);
 
            return list;
        }
    }
}
در اینجا نحوه‌ی مقدار دهی ParentId و HasChildren را جهت تو در تو سازی اطلاعات، مشاهده می‌کنید.
در این لیست دو رکورد، دارای ParentId مساوی null هستند. از این null بودن‌ها جهت کوئری گرفتن و نمایش ریشه‌های TreeView در ادامه استفاده خواهیم کرد.


بازگشت نظرات با فرمت JSON به سمت کلاینت

در ادامه یک کنترلر ASP.NET MVC را مشاهده می‌کنید که توسط اکشن متد GetBlogComments، رکوردهای مورد نظر را با فرمت JSON به سمت کلاینت ارسال می‌کند:
using System.Linq;
using System.Web.Mvc;
using KendoUI11.Models;
 
namespace KendoUI11.Controllers
{
 
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View(); // shows the page.
        }
 
        [HttpGet]
        public ActionResult GetBlogComments(int? id)
        {
            if (id == null)
            {
                //دریافت ریشه‌ها
                return Json(
                    BlogCommentsDataSource.LatestComments
                        .Where(x => x.ParentId == null) // ریشه‌ها
                        .ToList(),
                    JsonRequestBehavior.AllowGet);
            }
            else
            {
                //دریافت فرزندهای یک ریشه
                return Json(
                    BlogCommentsDataSource.LatestComments
                              .Where(x => x.ParentId == id)
                              .ToList(),
                              JsonRequestBehavior.AllowGet);
            }
        }
    }
}
اگر از سمت Kendo UI، مقدار id تنظیم نشود، به معنای درخواست نمایش ریشه‌ها است. در این حالت رکوردها را بر اساس مواردی که دارای ParentId مساوی null هستند، فیلتر خواهیم کرد.
اگر مقدار id به سمت سرور ارسال شود، یعنی کاربر گره و نودی را گشوده‌است. بر این اساس، تمامی فرزندان این گره را یافته و بازگشت می‌دهیم.


کدهای سمت کاربر نمایش Kendo UI Tree View

برای کار با Kendo UI TreeView نیاز است از منبع داده خاصی به نام HierarchicalDataSource به نحو ذیل استفاده کنیم. در قسمت transport آن مشخص می‌کنیم که اطلاعات باید از چه آدرسی خوانده شوند که در اینجا به آدرس اکشن متد  GetBlogComments اشاره می‌کند.
همچنین نیاز است مشخص کنیم کدامیک از خواص مدل بازگردانده شده، همان hasChildren است که در مثال فوق دقیقا به همین نام نیز تنظیم شده‌است.
<!--نحوه‌ی راست به چپ سازی -->
<div class="k-rtl k-header demo-section">
    <div id="my-treeview"></div>
</div>
 
@section JavaScript
{
    <script type="text/javascript">
        $(function () {
            var dataSource = new kendo.data.HierarchicalDataSource({
                transport: {
                    read: {
                        url: "@Url.Action("GetBlogComments", "Home")",
                        dataType: "json",
                        contentType: 'application/json; charset=utf-8',
                        type: 'GET'
                    }
                },
                schema: {
                    model: {
                        id: "Id",
                        hasChildren: "HasChildren"
                    }
                }
            });
 
            $("#my-treeview").kendoTreeView({
                //استفاده از قالب در صورت نیاز
                template: kendo.template($("#treeview-template").html()),
                checkboxes: {
                    checkChildren: false
                },
                dataSource: dataSource,
                dataTextField: "Body",
                //رخدادها
                select: function (e) { console.log("Selecting: " + this.text(e.node)); },
                check: function (e) { console.log("Checkbox changed :: " + this.text(e.node)); },
                change: function (e) { console.log("Selection changed"); },
                collapse: function (e) { console.log("Collapsing " + this.text(e.node)); },
                expand: function (e) { console.log("Expanding " + this.text(e.node)); }
            });
        });
    </script>
 
    <script id="treeview-template" type="text/kendo-ui-template">
        <strong> #: item.Body # </strong>
    </script>
 
    <style scoped>
        .demo-section {
            width: 100%;
            height: 300px;
        }
    </style>
}
 پس از تنظیم remote data source، اکنون نوبت به تعریف و تنظیم kendoTreeView است.
- در ابتدا به ازای هر ردیف این TreeView، از یک قالب استفاده شده‌است. تعریف این مورد اختیاری است. اگر نیاز به سفارشی سازی نحوه‌ی نمایش هر آیتم را داشتید، می‌توان از قالب‌ها استفاده کرد.
- قسمت checkboxes مشخص می‌کند که آیا نیاز است در کنار هر آیتم یک checkbox نیز نمایش داده شود یا خیر.
- dataSource را به HierarchicalDataSource تنظیم کرده‌ایم.
- dataTextField مشخص می‌کند که کدام فیلد دربرگیرنده‌ی متن هر آیتم TreeView است.
- تعدادی رخداد منتسب به TreeView نیز تنظیم شده‌اند که خروجی آن‌ها را در console تصویر ابتدای بحث مشاهده می‌کنید.


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید.
نظرات مطالب
نحوه تهیه گزارش در SSRS و انتشار آن روی وب سرور
سلام
از صحت آدرس‌های تعریف شده اطمینان پیدا کنید.
در قسمت Reporting Services Configuration Manager
در زیر مجموعه‌های  Report Manager URL  و  Web Service URL
و همچنین
در قسمت Properties  قسمت TargetServerRUL
احتمال دوم، عدم وجود دسترسی کافی برای تنظیمات فوق است
با کاربر مدیر ارشد این کار را انجام دهید 
مطالب
همه چیز در مورد CLR : قسمت اول
در حال حاضر من کتاب CLR Via Csharp ویرایش چهارم نوشته آقای جفری ریچر را مطالعه می‌کنم و نه قسمت از این مقالات، از بخش اول فصل اول آن به پایان رسیده که همگی آن‌ها را تا 9 روز آینده منتشر خواهم کرد. البته سعی شده که مقالات ترجمه صرف نباشند و منابع دیگری هم در کنار آن استفاده شده است. بعضی موارد را هم لینک کرده‌ام. تمام سعی خود را می‌کنم تا ادامه کتاب هم به مرور به طور مرتب ترجمه شود؛ تا شاید نسخه‌ی تقریبا کاملی از این کتاب را به زبان فارسی در اختیار داشته باشیم.
بعد از اینکه برنامه را تحلیل کردید و نیازمندی‌های یک برنامه را شناسایی کردید، وقت آن است که زبان برنامه نویسی خود را انتخاب کنید. هر زبان ویژگی‌های خاص و منحصر به فرد خود را دارد و این ممکن هست انتخاب شما را سخت کند. برای مثال شما در زبان‌های ++unmanaged C/C، کنترل بسیار زیادی روی امور سیستمی از قبیل حافظه و تردها دارید و به هر روشی که می‌خواهید می‌توانید آن‌ها را پیکربندی کنید. در زبان‌هایی چون Visual basic قدیم و مشابه‌های آن عموما اینگونه بود که طراحی یک اپلیکیشن از رابط کاربری گرفته تا اتصال به دیتابیس و اشیاء COM در آن ساده باشد؛ ولی در زبان‌های CLR چطور؟

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

زبان‌های CLR چگونه کار می‌کنند؟
در اولین گام بعد از نوشتن برنامه، کامپایلر آن زبان دست به کار شده و برنامه را برای شما کامپایل می‌کند. ولی اگر تصور می‌کنید که برنامه را به کد ماشین تبدیل می‌کند و از آن یک فایل اجرایی می‌سازد، سخت در اشتباه هستید. کامپایلر هر زبان  CLR، کد‌ها را به یک زبان میانی Intermediate Language به اختصار IL تبدیل می‌کند. فرقی نمی‌کند چه زبانی کار کرده‌اید، کد شما تبدیل شده است به یک زبان میانی مشترک. CLR نمی‌تواند برای تک تک زبان‌های شما یک مفسر داشته باشد. در واقع هر کمپایلر قواعد زبان خود را شناخته و آن را به یک زبان مشترک تبدیل می‌سازد و حالا CLR می‌تواند حرف تمامی زبان‌ها را بفهمد. به فایل ساخته شده  managed module گویند و به زبان‌هایی که از این قواعد پیروی نمی‌کنند unmanaged گفته می‌شود؛ مثل زبان سی ++ که در دات نت هم managed و هم unmanaged داریم که اولی بدون فریم ورک دات نت کار می‌کند و مستقیما به کد ماشین تبدیل می‌شود و دومی نیاز به فریم ورک دات نت داشته و به زبان میانی کامپایل می‌شود. جدول زیر نشان می‌دهد که کد همه‌ی زبان‌ها تبدیل به یک نوع شده است.


 
فایل هایی که ساخته می‌شوند بر دو نوع هستند؛ یا بر اساس استاندارد windows Portable Executable 32bits برای سیستم‌های 32 بیتی و 64 بیتی هستند و یا بر اساس windows Portable Executable 64bits مختص سیستم‌های 64 بیتی هستند که به ترتیب PE32 و +PE32 نامیده می‌شوند که CLR بر اساس این اطلاعات آن‌ها را به کد اجرایی تبدیل می‌کند. زبان‌های CLR همیشه این مزیت را داشته‌اند که اصول امنیتی چون DEP یا Data Execution Prevention و همچنین ASLR یا Address Space Layout Randomization در آن‌ها لحاظ شده باشد.