مسیریابی در +Angular 2
عموما از مسیریابی جهت حرکت بین Viewهای مختلف برنامه استفاده میشود، اما کارهای بیشتری را نیز میتوان با آن انجام داد؛ مانند ارسال اطلاعات، به مسیریابیها، پیش بارگذاری اطلاعات، جهت نمایش در Viewها، گروه بندی و محافظت از مسیریابیها، پویانمایی و انیمیشن و همچنین بهبود کارآیی، با بارگذاری async مسیرهای مختلف.
کار سیستم مسیریاب +Angular 2 زمانی شروع میشود که تغییری را در آدرس درخواستی از برنامه مشاهده میکند؛ یا از طریق درخواست آدرسی توسط مرورگر و یا هدایت به قسمتی خاص، از طریق کدنویسی. سپس مسیریاب به آرایهی تنظیم شدهی مسیرهای سیستم مراجعه میکند تا بتواند تطابقی را بین آدرس درخواستی و یکی از کلیدهای تنظیم شدهی در آن پیدا کند. در این حالت اگر تطابقی یافت نشود، کارمسیریابی خاتمه خواهد یافت. در غیراینصورت کار ادامه یافته و سپس مسیریاب، محافظهای مسیر درخواستی را بررسی میکند تا مشخص شود که آیا کاربر مجاز به هدایت به این قسمت خاص از برنامه هست یا خیر؟ در صورت مثبت بودن پاسخ، مرحلهی بعد، پیش بارگذاری اطلاعات درخواستی جهت نمایش View مرتبط است. در ادامه کامپوننت متناظر با مسیریابی فعالسازی میشود. سپس قالب این کامپوننت را در قسمتی که توسط router-outlet مشخص میگردد، جایگذاری کرده و نمایش میدهد.
تعریف مسیر پایه یا Base path
اولین مرحلهی کار با سیستم مسیریابی +Angular 2، تعریف یک base path است. مسیرپایه، به زیرپوشهای اشاره میکند که برنامهی ما در آن قرار گرفتهاست:
www.mysite.com/myapp
مسیریاب از این مسیرپایه جهت ساخت آدرسهای مسیریابی استفاده میکند. مقدار آن نیز به صورت ذیل در فایل index.html برنامه، درست پس از تگ head تعیین میگردد:
<!DOCTYPE html> <html> <head> <base href="/">
<base href="/myapp/">
تعیین مسیرپایه جهت ارائهی نهایی
استفاده از مسیر پایه / برای حالت توسعه و همچنین زمانیکه برنامهی نهایی شما در ریشهی سایت توزیع میشود، بسیار مناسب است. اما اگر برای حالت توسعه از مقدار / و برای حالت توزیع از مقدار /myapp/ بخواهید استفاده کنید، مدام نیاز خواهید داشت تا فایل index.html نهایی سایت را ویرایش کنید. برای این منظور Angular CLI دارای پرچمی است به نام base-href:
> ng build --base-href /myapp/
حالت پیش فرض تولید برنامههای Angular توسط Angular CLI، تنظیم مسیرپایه در فایل src\index.html به صورت خودکار به / میباشد.
تعریف مسیریاب Angular
مسیریاب Angular در ماژولی به نام RouterModule قرار گرفتهاست و باید در ابتدای کار import شود. این ماژول شامل سرویسی است جهت هدایت کاربران به صفحات دیگر و مدیریت URLها، تنظیماتی برای تعریف جزئیات مسیریابیها و تعدادی دایرکتیو که برای فعالسازی و نمایش مسیرها از آنها استفاده میشود. برای مثال دایرکتیو RouterLink آن یک المان قابل کلیک HTML را به مسیر و کامپوننتی خاص در برنامه متصل میکند. RouterLinkActive، شیوهنامهها را به لینک فعال انتساب میدهد و RouterOutlet محل نمایش قالب کامپوننت فعال شده را مشخص میکند.
یک مثال: در ادامه، یک پروژهی جدید مبتنی بر Angular CLI را به نام angular-routing-lab به همراه تنظیمات ابتدایی مسیریابی آن ایجاد میکنیم:
> ng new angular-routing-lab --routing
> npm install bootstrap --save
"apps": [ { "styles": [ "../node_modules/bootstrap/dist/css/bootstrap.min.css", "styles.css" ],
در ادامه اگر به فایل src\app\app-routing.module.ts مراجعه کنید، یک چنین محتوایی را خواهید یافت:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', children: [] } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
میتوان این قسمت را خلاصه کرد و فایل app-routing.module.ts را نیز حذف کرد و سپس import لازم و تعریف ماژول آنرا به ماژول آغازین برنامه یا همان src\app\app.module.ts نیز منتقل کرد. اما پس از مدتی تنظیمات مسیریابی آن، فایل ماژول اصلی برنامه را بیش از اندازه شلوغ خواهند کرد. بنابراین Angular-CLI تصمیم به ایجاد یک ماژول مستقل را برای تعریف تنظیمات مسیریابی برنامه گرفتهاست. سپس تعریف آن را به فایل src\app\app.module.ts به صورت خودکار اضافه میکند:
import { AppRoutingModule } from './app-routing.module'; @NgModule({ imports: [ AppRoutingModule ],
اگر به قسمت import مربوط به NgModule فایل src\app\app-routing.module.ts دقت کنید، این ماژول به همراه متد forRoot معرفی شدهاست.
@NgModule({ imports: [RouterModule.forRoot(routes)],
الف) forRoot
- کار آن تعریف دایرکتیوهای مسیریابی، مدیریت تنظیمات مسیریابی و ثبت سرویس مسیریابی است.
- نکتهی مهم اینجا است که متد forRoot تنها یکبار باید در طول عمر یک برنامه تعریف شود.
- این متد آرایهای از تنظیمات مسیریابیهای تعریف شده را دریافت میکند.
ب) forChild
- کار آن تعریف دایرکتیوهای مسیریابی و مدیریت تنظیمات مسیریابی است؛ اما سرویس مسیریابی را مجددا ثبت نمیکند.
- از این متد در جهت تعریف مسیریابیهای ماژولهای ویژگیهای مختلف برنامه و نظم بخشیدن به آنها استفاده میشود.
بنابراین زمانیکه از forRoot استفاده میشود، سرویس مسیریابی تنها یکبار ثبت خواهد شد و تنها یک وهله از آن موجود خواهد بود. در ادامه هر کدام از ماژولهای دیگر برنامه میتوانند forChild خاص خودشان را داشته باشند.
اکنون تمام کامپوننتهای قید شدهی در قسمت declaration، امکان دسترسی به دایرکتیوهای مسیریابی را پیدا میکنند. همچنین از آنجائیکه AppRoutingModule به همراه متد forRoot است، سرویس مسیریابی نیز در کل برنامه قابل دسترسی است.
تنظیمات اولیه مسیریابی برنامه
آرایهی const routes: Routes فایل src\app\app-routing.module.ts در ابتدای کار خالی است. در اینجا کار تعریف URL segments و سپس اتصال آنها به کامپوننتهای متناظری جهت فعالسازی و نمایش قالب آنها صورت میگیرد. این نمایش نیز در محل router-outlet تعریف شدهی در فایل src\app\app.component.html انجام میشود:
<h1> {{title}} </h1> <router-outlet></router-outlet>
در ادامه برای تکمیل مثال جاری، دو کامپوننت جدید خوشآمد گویی و همچنین یافتن نشدن مسیرها را به برنامه اضافه میکنیم:
>ng g c welcome >ng g c PageNotFound
@NgModule({ declarations: [ AppComponent, WelcomeComponent, PageNotFoundComponent ],
سپس فایل src\app\app-routing.module.ts را به نحو ذیل تکمیل نمائید:
import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { WelcomeComponent } from './welcome/welcome.component'; import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: 'welcome', component: WelcomeComponent }, { path: '', redirectTo: 'welcome', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
یک نکته: افزونهی auto import، کار تعریف کامپوننتها را در VSCode بسیار ساده میکند و امکان تشکیل خودکار قسمت import را با ارائهی یک intellisense به همراه دارد.
سپس کار تکمیل آرایهی Routes انجام شدهاست. همانطور که مشاهده میکنید، این آرایه متشکل است از اشیایی که به همراه خاصیت path و سایر پارامترهای مورد نیاز هستند.
کار خاصیت path، تعیین URL segment متناظری است که این مسیریابی را فعال میکند. برای مثال اولین شیء تعریف شده با آدرسهایی مانند www.mysite.com/welcome متناظر است.
{ path: 'welcome', component: WelcomeComponent },
چند نکته:
- در حین تعریف مقدار خاصیت path، هیچ / آغاز کنندهای تعریف نشدهاست.
- مقدار خاصیت path، حساس به کوچکی و بزرگی حروف است.
- WelcomeComponent تعریف شده، یک رشته نیست و ارجاعی را به کامپوننت مرتبط دارد. به همین جهت نیاز به import statement ابتدایی را دارد و وجود آن توسط کامپایلر بررسی میشود.
تعیین مسیریابی پیش فرض سایت
اما زمانیکه برنامه برای بار اول بارگذاری میشود، چطور؟ در این حالت هیچ URL segment ایی وجود ندارد. بنابراین برای تنظیم مسیرپیش فرض سایت، خاصیت path، به یک رشتهی خالی همانند دومین شیء تنظیمات مسیریابی، تنظیم میشود:
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
مدیریت مسیریابی آدرسهای ناموجود در سایت
تنظیم سومی را نیز در اینجا مشاهده میکنید:
{ path: '**', component: PageNotFoundComponent },
یک نکته: ترتیب مسیریابیها در آرایهی تعریف آنها اهمیت دارد. در اینجا از استراتژی «اولین تطابق یافته، برنده خواهد بود» استفاده میشود. بنابراین تنظیم ** باید در انتهای لیست ذکر شود؛ در غیراینصورت هیچکدام از مسیریابیهای تعریف شدهی پس از آن پردازش نخواهند شد.
مدیریت تغییرات آدرسهای برنامه
در طول عمر برنامه ممکن است نیاز به تغییر آدرسهای برنامه باشد. برای مثال بجای مسیر welcome مسیر home نمایش داده شود:
const routes: Routes = [ { path: 'home', component: WelcomeComponent }, { path: 'welcome', redirectTo: 'home', pathMatch: 'full' }, { path: '', redirectTo: 'welcome', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ];
نکته: redirectToها قابلیت تعریف زنجیرهای را ندارند. به این معنا که اگر ریشهی سایت درخواست شود، ابتدا به مسیر welcome هدایت خواهیم شد. مسیر welcome هم یک redirectTo دیگر به مسیر home را دارد. اما در اینجا کار به این redirectTo دوم نخواهد رسید و این پردازش، زنجیرهای نیست. بنابراین مسیریابی پیشفرض را نیز باید ویرایش کرد و به home تغییر داد:
const routes: Routes = [ { path: 'home', component: WelcomeComponent }, { path: 'welcome', redirectTo: 'home', pathMatch: 'full' }, { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ];
نکته: redirectToها میتوانند local و یا absolute باشند. تعریف محلی آنها مانند ذکر home و welcome در اینجا است و تنها سبب تغییر یک URL segment میشود. اما اگر در ابتدای مقادیر redirectToها یک / قرار دهیم، به معنای تعریف یک مسیر مطلق است و کل URL را جایگزین میکند.
تعیین محل نمایش قالبهای کامپوننتها
زمانیکه یک کامپوننت فعالسازی میشود، قالب آن در router-outlet نمایش داده خواهد شد. برای این منظور فایل src\app\app.component.html را گشوده و به نحو ذیل تغییر دهید:
<nav class="navbar navbar-default"> <div class="container-fluid"> <a class="navbar-brand">{{title}}</a> <ul class="nav navbar-nav"> <li> <a [routerLink]="['/home']">Home</a> </li> </ul> </div> </nav> <div class="container"> <router-outlet></router-outlet> </div>
یک نکته: چون کامپوننت welcome از طریق مسیریابی نمایش داده میشود و دیگر به صورت مستقیم با درج تگ selector آن در صفحه فعالسازی نخواهد شد، میتوان به تعریف کامپوننت آن مراجعه کرده و selector آنرا حذف کرد.
@Component({ //selector: 'app-welcome', templateUrl: './welcome.component.html', styleUrls: ['./welcome.component.css'] })
تا اینجا اگر دستور ng serve -o را صادر کنیم (کار build درون حافظهای جهت محیط توسعه و نمایش خودکار برنامه در مرورگر)، چنین خروجی در مرورگر نمایان خواهد شد:
اگر به آدرس تنظیم شدهی در مرورگر دقت کنید، http://localhost:4200/home آدرسی است که در ابتدای نمایش سایت نمایان خواهد شد. علت آن نیز به تنظیم مسیریابی پیش فرض سایت برمیگردد.
و اگر یک مسیر غیرموجود را درخواست دهیم، قالب کامپوننت PageNotFound ظاهر میشود:
هدایت کاربران به قسمتهای مختلف برنامه
کاربران را میتوان به روشهای مختلفی به قسمتهای گوناگون برنامه هدایت کرد؛ برای مثال با کلیک بر روی المانهای قابل کلیک HTML و سپس اتصال آنها به کامپوننتهای برنامه. استفادهی کاربر از bookmark مرورگر و یا ورود مستقیم و دستی آدرس قسمتی از برنامه و یا کلیک بر روی دکمههای forward و back مرورگر. تنها مورد اول است که نیاز به تنظیم دارد و سایر قسمتها به صورت خودکار مدیریت خواهند شد. نمونهی آنرا نیز با تعریف لینک Home پیشتر مشاهده کردید:
<a [routerLink]="['/home']">Home</a>
- زمانیکه کاربر بر روی این لینک کلیک میکند، اولین path متناظر با routerLink یافت شده و فعالسازی خواهد شد.
- علت تعریف مقدار routerLink به صورت [] این است که آرایهی پارامترهای لینک را مشخص میکند. بنابراین چون آرایهاست، نیاز به [] دارد. اولین پارامتر این آرایه مفهوم root URL segment را دارد. در اینجا حتما نیاز است URL segment را با یک / شروع کرد. به علاوه باید دقت داشت که خاصیت path تنظیمات مسیریابی، حساس به حروف کوچک و بزرگ است. بنابراین این مورد را باید در اینجا نیز مدنظر داشت.
- پارامترهای دیگر routerLink میتوانند مفهوم پارامترهای این segment و یا حتی segments دیگری باشند.
یک نکته: چون در مثال فوق، آرایهی تعریف شده تنها دارای یک عضو است، آنرا میتوان به صورت ذیل نیز خلاصه نویسی کرد (one-time binding):
<a routerLink="/home">Home</a>
تفاوت بین آدرسهای HTML 5 و Hash-based
زمانیکه مسیریاب Angular کار پردازش آدرسهای رسیده را انجام میدهد، اینکار در سمت کلاینت صورت میگیرد و تنها URL segment مدنظر را تغییر داده و این درخواست را به سمت سرور ارسال نمیکند. به همین جهت سبب reload صفحه نمیشود. دو روش در اینجا جهت مدیریت سمت کلاینت آدرسها قابل استفاده است:
الف) HTML 5 Style
- آدرسی مانند http://localhost:4200/home، یک آدرس به شیوهی HTML 5 است. در اینجا مسیریاب Angular با استفاده از HTML 5 history pushState سبب به روز رسانی History مرورگر شده و آدرسها را بدون ارسال درخواستی به سمت سرور، در همان سمت کلاینت تغییر میدهد.
- این روش حالت پیش فرض Angular است و نحوهی نمایش آن بسیار طبیعی به نظر میرسد.
- در اینجا URL rewriting سمت سرور نیز جهت هدایت آدرسها، به برنامهی Angular ضروری است. برای مثال زمانیکه کاربری آدرس http://localhost:4200/home را مستقیما در مرورگر وارد میکند، این درخواست ابتدا به سمت سرور ارسال خواهد شد و چون چنین صفحهای در سمت سرور وجود ندارد، پیغام خطای 404 را دریافت میکند. اینجا است که URL rewriting سمت سرور به فایل index.html برنامه، جهت مدیریت یک چنین حالتهایی ضروری است.
برای نمونه اگر از وب سرور IIS استفاده میکنید، تنظیم ذیل را به فایل web.config در قسمت system.webServer اضافه کنید (کار کرد آن هم وابستهاست به نصب و فعالسازی ماژول URL Rewrite بر روی IIS):
<rewrite> <rules> <rule name="Angular 2+ pushState routing" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> <add input="{REQUEST_FILENAME}" pattern=".*\.[\d\w]+$" negate="true" /> <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" /> </conditions> <action type="Rewrite" url="/index.html" /> </rule> </rules> </rewrite>
ب) Hash-based
- آدرسی مانند http://localhost:4200/#/home یک آدرس به شیوهی Hash-based بوده و مخصوص مرورگرهایی است بسیار قدیمی که از HTML 5 پشتیبانی نمیکنند. اینبار قطعات قرار گرفتهی پس از علامت # دارای نام URL fragments بوده و قابلیت پردازش در سمت کلاینت را دارا میباشند.
- اگر علاقمند به استفادهی از این روش هستید، نیاز است خاصیت useHash را به true تنظیم کنید:
@NgModule({ imports: [RouterModule.forRoot(routes, { useHash: true })],
آشنایی با دستور APPLY در SQL Server
ساخت ربات تلگرامی با #C
Additional information: The remote server returned an error: (502) Bad Gateway.
رو میده
ممنون میشم راهنماییم کنید
یاعلی
بهبود ظاهر کامنتها با بکارگیری Markdown
Markdown زبان سبکی است برای تعیین شیوهنامهی نمایش متون ساده. اگر پیشتر با سیستم ارسال نظرات Github و یا Stackoverflow کار کرده باشید، قطعا با آن آشنایی دارید. توضیحات کامل و جزئیات آنرا میتوانید در آدرس markdownguide.org مطالعه کنید. خوشبختانه امکان استفادهی از Markdown در OpenAPI spec نیز وجود دارد که سبب بهبود ظاهر مستندات نهایی حاصل از آن خواهد شد.
در قسمت سوم، سعی کردیم مثالی را توسط remarks، به قسمت Patch اضافه کنیم که ظاهر آن، آنچنان مطلوب به نظر نمیرسد و بهتر است آنرا به صورت یک قطعه کد نمایش داد:
برای بهبود این ظاهر میتوان از Markdown استفاده کرد. بنابراین ابتدا تمام backslashهای اضافه شده را که جهت نمایش خطوط جدید اضافه شده بودند، حذف میکنیم. در Markdown خطوط جدید با درج حداقل 2 فاصله (space) و یک سطر جدید مشخص میشوند. همچنین استفادهی از ** سبب ضخیم شدن نمایش عبارتها میشود. برای اینکه قطعه کد نوشته شده را در Markdown به صورت کدی با پس زمینهای مشخص نمایش دهیم، پیش از شروع هر سطر آن نیاز است یک tab و یا 4 فاصله (space) درج شوند:
/// <remarks> /// Sample request (this request updates the author's **first name**) /// /// PATCH /authors/id /// [ /// { /// "op": "replace", /// "path": "/firstname", /// "value": "new first name" /// } /// ] /// </remarks>
که نسبت به حالت قبلی بسیار بهتر به نظر میرسد.
در نگارش فعلی، استفادهی از Markdown برای توضیحات remarks، پارامترها و response codes پشتیبانی میشود؛ اما نه برای قسمت summary که برای نگارش بعدی درنظر گرفته شدهاست. همچنین از قابلیتهای پیشترفتهی Markdown هم استفاده نکنید (در کل نیاز به مقداری سعی و خطا دارد تا مشخص شود چه قابلیتهایی را پشتیبانی میکند).
سفارشی سازی مقدماتی UI به کمک تنظیمات API آن
جائیکه تنظیمات میانافزار Swashbuckle.AspNetCore در کلاس Starup تعریف میشوند، میتوان تغییراتی را نیز در UI آن اعمال کرد:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... app.UseSwaggerUI(setupAction => { setupAction.SwaggerEndpoint( url: "/swagger/LibraryOpenAPISpecification/swagger.json", name: "Library API"); setupAction.RoutePrefix = ""; setupAction.DefaultModelExpandDepth(2); setupAction.DefaultModelRendering(Swashbuckle.AspNetCore.SwaggerUI.ModelRendering.Model); setupAction.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None); setupAction.EnableDeepLinking(); setupAction.DisplayOperationId(); }); // ... } } }
همچنین چون DefaultModelRendering به Model تنظیم شدهاست، اینبار بجای مثال، مشخصات مدل را به صورت پیشفرض نمایش میدهد:
کار DisplayOperationId نمایش Id هر Operation است؛ مانند get_api_authors. در اینجا Operation همان مداخل API ما هستند و به عنوان هر قسمت، Tag گفته میشود؛ مانند Authors و یا Books:
با فعالسازی EnableDeepLinking، آدرسهایی مانند tagName/# و یا tagName/OperationId/# قابلیت مرور و بازشدن خودکار را پیدا میکنند (tagName همان نام کنترلر است و OperationId همان اکشن متدی که عمومی شدهاست). برای مثال اگر آدرس https://localhost:5001/index.html#/Books/get_api_authors__authorId__books را در یک برگهی جدید مرورگر باز کنیم، بلافاصله گروه Books، باز شده و سپس به اکشن متد یا مدخلی که Id آن ذکر شدهاست، هدایت میشویم:
اعمال تغییرات پیشرفته در UI
Swagger-UI در اصل از یک سری فایل html، css، js و فونت تشکیل شدهاست که آنها را میتوانید در آدرس src/Swashbuckle.AspNetCore.SwaggerUI مشاهده کنید. برای مثال فایل index.html آنرا در اینجا میتوانید مشاهده کنید. اصل آن در div ای با id مساوی swagger-ui رخ میدهد و در این قسمت است که رابط کاربری آن به صورت پویا تولید شده و رندر خواهد شد. بررسی فایلهای js و css آن در این مخزن کد مشکل است؛ چون نگارش فشرده شدهی آن هستند. به همین جهت میتوان به مخزن کد اصلی Swagger-UI که نگارش جایگذاری شدهی آن (embedded) توسط Swashbuckle.AspNetCore ارائه میشود، رجوع کرد. برای مثال در پوشهی src/styles آن، اصل فایلهای css آن برای سفارشی سازی وجود دارند.
پس از اعمال تغییرات خود، میتوانید css و یا js سفارشی خود را به نحو زیر به تنظیمات app.UseSwaggerUI سیستم معرفی کنید:
setupAction.InjectStylesheet("/Assets/custom-ui.css"); setupAction.InjectJavaScript("/Assets/custom-js.js");
برای اعمال تغییرات اساسی و تزریق صفحهی index.html جدیدی، میتوان به صورت زیر عمل کرد:
setupAction.IndexStream = () => GetType().Assembly.GetManifestResourceStream( "OpenAPISwaggerDoc.Web.EmbeddedAssets.index.html");
<Project Sdk="Microsoft.NET.Sdk.Web"> <ItemGroup> <None Remove="EmbeddedAssets\index.html" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="EmbeddedAssets\index.html" /> </ItemGroup> </Project>
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-07.zip
NHibernate کتابخانهی تبدیل شده پروژه بسیار محبوب Hibernate جاوا به سی شارپ است و یکی از ORM های بسیار موفق، به شمار میرود. در طی تعدادی مقاله قصد آشنایی با این فریم ورک را داریم.
چرا نیاز است تا از یک ORM استفاده شود؟
تهیه قسمت و یا لایه دسترسی به دادهها در یک برنامه عموما تا 30 درصد زمان کل تهیه یک محصول را تشکیل میدهد. اما باید در نظر داشت که این پروسهی تکراری هیچ کار خارق العادهای نبوده و ارزش افزودهی خاصی را به یک برنامه اضافه نمیکند. تقریبا تمام برنامههای تجاری نیاز به لایه دسترسی به دادهها را دارند. پس چرا ما باید به ازای هر پروژه، این کار تکراری و کسل کننده را بارها و بارها تکرار کنیم؟
هدف NHibernate ، کاستن این بار از روی شانههای یک برنامه نویس است. با کمک این کتابخانه، دیگر رویه ذخیره شدهای را نخواهید نوشت. دیگر هیچگاه با ADO.Net سر و کار نخواهید داشت. به این صورت میتوان عمده وقت خود را صرف قسمتهای اصلی و طراحی برنامه کرد تا کد نویسی یک لایه تکراری. همچنین عدهای از بزرگان اینگونه ابزارها اعتقاد دارند که برنامه نویسهایی که لایه دسترسی به دادهها را خود طراحی میکنند، مشغول کلاهبرداری از مشتریهای خود هستند! (صرف زمان بیشتر برای تهیه یک محصول و همچنین وجود باگهای احتمالی در لایه دسترسی به دادههای طراحی شده توسط یک برنامه نویس نه چندان حرفهای)
برای مشاهده سایر مزایای استفاده از یک ORM لطفا به مقاله "5 دلیل برای استفاده از یک ابزار ORM" مراجعه نمائید.
در ادامه برای معرفی این کتابخانه یک سیستم ثبت سفارشات را با هم مرور خواهیم کرد.
بررسی مدل سیستم ثبت سفارشات
در این مدل سادهی ما، مشتریها (customers) امکان ثبت سفارشات (orders) را دارند. سفارشات توسط یک کارمند (employee) که مسؤول ثبت آنها است به سیستم وارد میشود. هر سفارش میتواند شامل یک یا چند (one-to-many) آیتم (order items) باشد و هر آیتم معرف یک محصول (product) است که قرار است توسط یک مشتری (customer) خریداری شود. کلاس دیاگرام این مدل به صورت زیر میتواند باشد.
نگاشت مدل
زمانیکه مدل سیستم مشخص شد، اکنون نیاز است تا حالات (دادهها) آنرا در مکانی ذخیره کنیم. عموما اینکار با کمک سیستمهای مدیریت پایگاههای داده مانند SQL Server، Oracle، IBM DB2 ، MySql و امثال آنها صورت میگیرد. زمانیکه از NHibernate استفاده کنید اهمیتی ندارد که برنامه شما قرار است با چه نوع دیتابیسی کار کند؛ زیرا این کتابخانه اکثر دیتابیسهای شناخته شده موجود را پشتیبانی میکند و برنامه از این لحاظ مستقل از نوع دیتابیس عمل خواهد کرد و اگر نیاز بود روزی بجای اس کیوال سرور از مای اس کیوال استفاده شود، تنها کافی است تنظیمات ابتدایی NHibernate را تغییر دهید (بجای بازنویسی کل برنامه).
اگر برای ذخیره سازی دادهها و حالات سیستم از دیتابیس استفاده کنیم، نیاز است تا اشیاء مدل خود را به جداول دیتابیس نگاشت نمائیم. این نگاشت عموما یک به یک نیست (لزومی ندارد که حتما یک شیء به یک جدول نگاشت شود). در گذشتهی نچندان دور کتابخانهی NHibernate ، این نگاشت عموما توسط فایلهای XML ایی به نام hbm صورت میگرفت. این روش هنوز هم پشتیبانی شده و توسط بسیاری از برنامه نویسها بکار گرفته میشود. روش دیگری که برای تعریف این نگاشت مرسوم است، مزین سازی اشیاء و خواص آنها با یک سری از ویژگیها میباشد که فریم ورک برتر این عملیات Castle Active Record نام دارد.
اخیرا کتابخانهی دیگری برای انجام این نگاشت تهیه شده به نام Fluent NHibernate که بسیار مورد توجه علاقمندان به این فریم ورک واقع گردیده است. با کمک کتابخانهی Fluent NHibernate عملیات نگاشت اشیاء به جداول، بجای استفاده از فایلهای XML ، توسط کدهای برنامه صورت خواهند گرفت. این مورد مزایای بسیاری را همانند استفاده از یک زبان برنامه نویسی کامل برای تعریف نگاشتها، بررسی خودکار نوعهای دادهای و حتی امکان تعریف منطقی خاص برای قسمت نگاشت برنامه، به همراه خواهد داشت.
آماده سازی سیستم برای استفاده از NHibernate
در ادامه بجای دریافت پروژه سورس باز NHibernate از سایت سورس فورج، پروژه سورس باز Fluent NHibernate را از سایت گوگل کد دریافت خواهیم کرد که بر فراز کتابخانهی NHibernate بنا شده است و آنرا کاملا پوشش میدهد. سورس این کتابخانه را با checkout مسیر زیر توسط TortoiseSVN میتوان دریافت کرد.
البته احتمالا برای دریافت آن از گوگل کد با توجه به تحریم موجود نیاز به پروکسی خواهد بود. برای تنظیم پروکسی در TortoiseSVN به قسمت تنظیمات آن مطابق تصویر ذیل مراجعه کنید:
همچنین جهت سهولت کار، آخرین نگارش موجود در زمان نگارش این مقاله را از این آدرس نیز میتوانید دریافت نمائید.
پس از دریافت پروژه، باز کردن فایل solution آن در VS و سپس build کل مجموعه، اگر به پوشههای آن مراجعه نمائید، فایلهای زیر قابل مشاهده هستند:
Nhibernate.dll : اسمبلی فریم ورک NHibernate است.
NHibernate.Linq.dll : اسمبلی پروایدر LINQ to NHibernate میباشد.
FluentNHibernate.dll : اسمبلی فریم ورک Fluent NHibernate است.
Iesi.Collections.dll : یک سری مجموعههای ویژه مورد استفاده NHibernate را ارائه میدهد.
Log4net.dll : فریم ورک لاگ کردن اطلاعات NHibernate میباشد. (این فریم ورک نیز جهت عملیات logging بسیار معروف و محبوب است)
Castle.Core.dll : کتابخانه پایه Castle.DynamicProxy2.dll است.
Castle.DynamicProxy2.dll : جهت اعمال lazy loading در فریم ورک NHibernate بکار میرود.
System.Data.SQLite.dll : پروایدر دیتابیس SQLite است.
Nunit.framework.dll : نیز یکی از فریم ورکهای بسیار محبوب آزمون واحد در دات نت فریم ورک است.
برای سادگی مراجعات بعدی، این فایلها را یافته و در پوشهای به نام lib کپی نمائید.
برپایی یک پروژه جدید
پس از دریافت Fluent NHibernate ، یک پروژه Class Library جدید را در VS.Net آغاز کنید (برای مثال به نام NHSample1 ). سپس یک پروژه دیگر را نیز از نوع Class Library به نام UnitTests به این solution ایجاد شده جهت انجام آزمونهای واحد برنامه اضافه نمائید.
اکنون به پروژه NHSample1 ، ارجاع هایی را به فایلهای FluentNHibernate.dll و سپس NHibernate.dll در که پوشه lib ایی که در قسمت قبل ساختیم، قرار دارند، اضافه نمائید.
در ادامه یک پوشه جدید به پروژه NHSample1 به نام Domain اضافه کنید. سپس به این پوشه، کلاس Customer را اضافه نمائید:
namespace NHSample1.Domain
{
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string PostalCode { get; set; }
public string City { get; set; }
public string CountryCode { get; set; }
}
}
using FluentNHibernate.Mapping;
namespace NHSample1.Domain
{
class CustomerMapping : ClassMap<Customer>
{
}
}
using FluentNHibernate.Mapping;
namespace NHSample1.Domain
{
class CustomerMapping : ClassMap<Customer>
{
public CustomerMapping()
{
Not.LazyLoad();
Id(c => c.Id).GeneratedBy.HiLo("1000");
Map(c => c.FirstName).Not.Nullable().Length(50);
Map(c => c.LastName).Not.Nullable().Length(50);
Map(c => c.AddressLine1).Not.Nullable().Length(50);
Map(c => c.AddressLine2).Length(50);
Map(c => c.PostalCode).Not.Nullable().Length(10);
Map(c => c.City).Not.Nullable().Length(50);
Map(c => c.CountryCode).Not.Nullable().Length(2);
}
}
}
سپس وضعیت نگاشت تک تک خواص کلاس Customer را مشخص میکنیم. توسط Id(c => c.Id).GeneratedBy.HiLo به سیستم اعلام خواهیم کرد که فیلد Id از نوع identity است که از 1000 شروع خواهد شد. مابقی موارد هم بسیار واضح هستند. تمامی خواص کلاس Customer ذکر شده، نال را نمیپذیرند (منهای AddressLine2) و طول آنها نیز مشخص گردیده است.
با کمک Fluent NHibernate ، بحث بررسی نوعهای دادهای و همچنین یکی بودن موارد مطرح شده در نگاشت با کلاس اصلی Customer به سادگی توسط کامپایلر بررسی شده و خطاهای آتی کاهش خواهند یافت.
برای آشنایی بیشتر با lambda expressions میتوان به مقاله زیر مراجعه کرد:
Step-by-step Introduction to Delegates and Lambda Expressions
ادامه دارد...
کوکیهایی که باید HTTPS only شوند
کوکیهای پیشفرض برنامههای ASP.NET به صورت HTTP Only به سمت کلاینت ارسال میشوند. این کوکیها توسط اسکریپتها قابل خوانده شدن نیستند و به همین جهت یکی از راههای مقاومت بیشتر در برابر حملات XSS به شمار میروند. پس از ارتقاء به HTTPS، این کوکیها را هم میتوان HTTPs Only کرد تا فقط به کلاینتهایی که از طریق آدرس HTTPS سایت به آن وارد شدهاند، ارائه شود:
1) کوکی آنتیفورجری توکن
AntiForgeryConfig.RequireSsl = true;
<configuration> <system.web> <authentication mode="Forms"> <forms requireSSL="true" cookieless="UseCookies"/> </authentication> </system.web> </configuration>
3) تمام httpCookies
<configuration> <system.web> <httpCookies httpOnlyCookies="true" requireSSL="true" /> </system.web> </configuration>
4) کوکیهای Role manager
<configuration> <system.web> <roleManager cookieRequireSSL="true" /> </system.web> </configuration>
5) کوکیهای OWIN Authentication و ASP.NET Identity 2.x
var options = new CookieAuthenticationOptions() { CookieHttpOnly = true, CookieSecure = CookieSecureOption.Always, ExpireTimeSpan = TimeSpan.FromMinutes(10) };
فعالسازی اجبار به استفادهی از HTTPS
با استفاده از فیلتر RequireHttps، دسترسی به تمام اکشن متدهای برنامه تنها به صورت HTTPS میسر خواهد شد:
filters.Add(new RequireHttpsAttribute(permanent: true));
using System.Web.Mvc; namespace MyWebsite { internal static class FilterConfig { internal static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new RequireHttpsAttribute(permanent: true)); } } }
همچنین در متد Application_BeginRequest نیز میتوان بررسی کرد که آیا درخواست ارسالی یک درخواست HTTPS است یا خیر؟ اگر خیر، میتوان کاربر را به صورت خودکار به نگارش HTTPS آن هدایت دائم کرد:
protected void Application_BeginRequest(Object sender, EventArgs e) { if (!HttpContext.Current.Request.IsSecureConnection) { var builder = new UriBuilder { Scheme = "https", Host = Request.Url.Host, // use the RawUrl since it works with URL Rewriting Path = Request.RawUrl }; Response.Status = "301 Moved Permanently"; Response.AddHeader("Location", builder.ToString()); } }
فعالسازی HSTS جهت اطلاع به مرورگر که این سایت تنها از طریق HTTPS قابل دسترسی است و تمام درخواستهای HTTP را به صورت خودکار از طریق HTTPS انجام بده:
<httpProtocol> <customHeaders> <add name="Strict-Transport-Security" value="max-age=16070400; includeSubDomains" />
<rewrite> <rules> <rule name="Redirect to HTTPS" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="off" ignoreCase="true" /> <add input="{HTTP_HOST}" negate="true" pattern="localhost" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule>
اصلاح تمام آدرسهای مطلقی که توسط برنامه تولید میشوند
اگر در برنامهی خود از Url.Action برای تولید آدرسها استفاده میکنید، با ذکر پارامتر protocol آن، آدرس تولیدی آن بجای یک مسیر نسبی، یک مسیر مطلق خواهد بود. اگر پیشتر این پروتکل را به صورت دستی به http تنظیم کردهاید، روش صحیح آن به صورت زیر است که با آدرس جدید HTTPS سایت هم سازگار است:
var fullBaseUrl = Url.Action(result: MVC.Home.Index(), protocol: this.Request.Url.Scheme);
اصلاح تمام آدرسهایی که پیشتر توسط برنامه تولید شدهاند
یک نمونه آن در مطلب «به روز رسانی تمام فیلدهای رشتهای تمام جداول بانک اطلاعاتی توسط Entity framework 6.x» بحث شدهاست.
اصلاح فایل robots.txt و درج آدرس HTTPS جدید
اگر در فایل robots.txt سایت، آدرس مطلق Sitemap را به صورت HTTP درج کرده بودید، آنرا به HTTPS تغییر دهید:
User-agent: * Sitemap: https://www.dntips.ir/Sitemap
LocalDB FAQ
اگر به تصویر فوق دقت کنید، یک child process جدید به نام sqlservr.exe نیز به همراه برنامهی آزمایشی ما به صورت خودکار اجرا شدهاست. این child process به همراه پارامترهای ذیل است (که توسط NET Framework. مقدار دهی میشوند و مدیریت نهایی آن خودکار است):
"C:\Program Files\Microsoft SQL Server\120\LocalDB\Binn\\sqlservr.exe" -c -SMSSQL12E.LOCALDB -sLOCALDB#5657074F -d"C:\Users\Vahid\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\master.mdf" -l"C:\Users\Vahid\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\mastlog.ldf" -e"C:\Users\Vahid\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\error.log"
اما LocalDB یک بانک اطلاعاتی user-mode است و در پروفایل کاربر جاری سیستم اجرا میشود. این بانک اطلاعاتی یک بار بر روی سیستم نصب میشود و در هر برنامهای که از آن استفاده میکنید، یک child process مجزای خاص خودش را (sqlservr.exe) اجرا خواهد کرد. اجرا و خاتمهی این child processها نیز خودکار هستند و نیازی به دخالت مستقیم برنامه ندارند.
البته به نظر توسعهی SQL Server CE متوقف شدهاست و دیگر پشتیبانی نمیشود. بنابراین گزینهی ترجیح داده شدهی برای کارهایی با حجمهای بانک اطلاعاتی زیر 10 گیگابایت ، میتواند LocalDB باشد. به علاوه اینکه قابلیتهای T-SQL بیشتری را نیز پشتیبانی میکند و همچنین پشتیبانی منظمی نیز از آن وجود دارد. برای مثال پیش نمایش نگارش 2016 آن نیز موجود است.
در ادامه، یک سری پرسش و پاسخ متداول جهت کار با LocalDB را مرور خواهیم کرد.
محل دریافت آخرین نگارش مستقل آن کجاست؟
همانطور که عنوان شد، یکی از مهمترین اهداف LocalDB، سهولت توزیع آن است و عدم نیاز به یک Admin سیستم، برای نصب و نگهداری آن. نگارش 2014 SP1 آنرا از آدرس ذیل میتوانید دریافت کنید:
https://www.microsoft.com/en-us/download/details.aspx?id=46697
در اینجا نسخههای متعددی وجود دارند. برای مثال اگر سیستم شما 64 بیتی است، تنها نیاز است ENU\x64\SqlLocalDB.msi را دریافت و نصب کنید:
پارامترهای نصب خاموش آن برای توزیع سادهی برنامه کدامند؟
اگر میخواهید نصاب LocalDB را به همراه setup برنامهی خود توزیع کنید، میتوانید روش توزیع خاموش را با ذکر پارامترهای ذیل، مورد استفاده قرار دهید:
msiexec /i SqlLocalDB.msi /qn IACCEPTSQLLOCALDBLICENSETERMS=YES
رشتهی اتصالی مخصوص آن کدام است؟
<connectionStrings> <add name="Sample35Context" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\test.mdf;Integrated Security=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
الف) ذکر وهلهی مدنظر
در اینجا وهلهی MSSQLLocalDB ذکر شدهاست؛ اما چه وهلههایی بر روی سیستم نصب هستند و چطور میتوان وهلهی دیگری را ایجاد کرد؟ برای این منظور، به پارامترهای sqlservr.exe ابتدای بحث دقت کنید. اکثر آنها به پوشهی ذیل اشاره میکنند:
C:\Users\your_user_name_here\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances
در این پوشه، وهلههای موجود و نصب شدهی بر روی سیستم شما نمایش داده میشوند که یکی از آنها را میتوانید در رشتهی اتصالی فوق ذکر کنید.
به علاوه، این لیست را توسط برنامهی کمکی SqlLocalDB.exe، به همراه پارامتر info یا i نیز میتوانید دریافت و بررسی کنید:
برنامهی کمکی SqlLocalDB.exe به همراه نصاب LocalDB، نصب میشود و توسط آن میتوان نگارشهای مختلف نصب شدهرا با پارامتر v و وهلهی مختلف موجود را با پارامتر i مشاهده کرد.
همچنین اگر میخواهید وهلهی جدیدی را بجز وهلهی پیش فرض MSSQLLocalDB ایجاد کنید، میتوانید از پارامتر create آن به نحو ذیل استفاده نمائید:
For LocalDB SQL EXPRESS 2014 "C:\Program Files\Microsoft SQL Server\120\Tools\Binn\SqlLocalDB.exe" create "v12.0" 12.0 -s For LocalDB SQL Express 2012 "C:\Program Files\Microsoft SQL Server\110\Tools\Binn\SqlLocalDB.exe" create "v11.0" 11.0 -s
ب) ذکر DataDirectory
در رشتهی اتصالی فوق، پارامتر DataDirectory نیز ذکر شدهاست تا بتوان مسیر بانک اطلاعاتی را به صورت نسبی و بدون ذکر عبارت دقیق آن که ممکن است در سیستمهای دیگر متفاوت باشد، پردازش کرد. این پارامتر در برنامههای وب به پوشهی استاندارد app_data اشاره میکند و نیازی به تنظیم اضافهتری ندارد. اما در برنامههای دسکتاپ باید به نحو ذیل به صورت دستی، در آغاز برنامه مقدار دهی شود:
AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory);
AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "db"));
محل نصب بانکهای اطلاعاتی پیش فرض آن کدام است؟
ذکر AttachDbFilename در رشتهی اتصالی فوق، اختیاری است. در صورت عدم ذکر آن، بانک اطلاعاتی ایجاد شده را در یکی از مسیرهای ذیل میتوانید جستجو کنید:
C:\Users\USERNAME\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances C:\Users\USERNAME\AppData\Local\Microsoft\VisualStudio\SSDT
آیا میتوان فایلهای mdf و ldf آنرا به نگارش کامل SQL Server متصل (attach) کرد؟
بله. اما باید دقت داشته باشید که SQL Server به محض اتصال یک بانک اطلاعاتی با نگارش پایینتر به آن، ابتدا شماره نگارش آنرا به روز میکند. یعنی دیگر نخواهید توانست این بانک اطلاعاتی را با نگارش پایینتر LocalDB باز کنید و یک چنین پیام خطایی را دریافت خواهید کرد:
The database xyz cannot be opened because it is version 706. This server supports version 663 and earlier. A downgrade path is not supported.
چگونه محتوای بانکهای اطلاعاتی LocalDB را با VS.NET مشاهده کنیم؟
از منوی view گزینهی server explorer را انتخاب کنید. بر روی data connections کلیک راست کرده و گزینهی Add connection را انتخاب کنید.
در صفحهی باز شده، گزینهی Microsoft SQL server را انتخاب کنید. در صفحهی بعد، ذکر server name مطابق data source رشتهی اتصالی بحث شده و سپس انتخاب گزینهی attach a database file کفایت میکند:
پس از کلیک بر روی ok، امکان کار با اجزای این بانک اطلاعاتی را خواهید داشت:
چگونه از LocalDB با EF استفاده کنیم؟
EF 6.x به صورت پیش فرض از بانک اطلاعاتی LocalDB استفاده میکند و تنها داشتن یک چنین تنظیمی در فایل کانفیگ برنامه، برای کار با آن کافی است:
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <connectionStrings> <add name="Sample35Context" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\test.mdf;Integrated Security=True;" providerName="System.Data.SqlClient" /> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> </configuration>
البته باید دقت داشت که اسمبلی EntityFramework.SqlServer نیز به صورت خودکار به همراه بستهی نیوگت EF 6.x به برنامه اضافه میشود که استفادهی از connection factory ذکر شده را میسر میکند.
استفادهی از LocalDB به همراه برنامههای وب چگونه است؟
سه نکته را باید در حین استفادهی از LocalDB، در برنامههای وب اجرا شدهی بر روی IIS مدنظر داشت:
الف) LocalDB یک بانک اطلاعاتی user-mode است و child process آن تحت مجوز اکانت تنظیم شدهی برای آن کار میکند.
ب) همانطور که عنوان شد، در رشتهی اتصالی ذکر شده، پارامتر DataDirectory به پوشهی استاندارد app_data اشاره میکند که فایلهای قرار گرفتهی در آن توسط IIS محافظت میشوند و از طریق وب قابل دسترسی و دانلود نیستند.
ج) child process مربوط به LocalDB، نیاز به دسترسی write، برای کار با فایلهای mdf و ldf خود دارد.
برای مورد الف نیاز است تا به تنظیمات application pool برنامه مراجعه کرده و سپس بر روی آن کلیک راست کرد و گزینهی advanced settings را انتخاب نمود. در اینجا گزینهی load user profile باید true باشد:
تنظیم load user profile ضروری است اما کافی نیست. پس از آن باید setProfileEnvironment را نیز به true تنظیم کرد. تنظیم این مورد در کنسول مدیریتی IIS به صورت زیر است.
ابتدا ریشهی اصلی سرور را انتخاب کنید و سپس به configuration editor آن وارد شوید:
در ادامه از دارپ داون آن، گزینهی system.applicationHost و زیر شاخهی applicationPools آنرا انتخاب کنید:
در اینجا application pool defaults و سپس در آن processModel را نیز باز کنید:
اکنون امکان ویرایش setProfileEnvironment را به true خواهید داشت:
پس از این تنظیم، ابتدا بر روی دکمهی apply سمت راست صفحه کلیک کرده و سپس نیاز است یکبار IIS را نیز ریست کنید تا تنظیمات اعمال شوند.
در ادامه برای تنظیم دسترسی write (موارد ب و ج)، ابتدا بر روی پوشهی app_data برنامه، کلیک راست کرده و برگهی security آنرا باز کنید. سپس بر روی دکمهی edit کلیک کرده و در صفحهی باز شده بر روی دکمهی add کلیک کنید تا بتوان به کاربر application pool برنامه دسترسی write داد:
در اینجا iis apppool\TestLocalDB را وارد کرده و بر روی دکمهی check name کلیک کنید.
iis apppool آن که مشخص است. عبارت TestLocalDB نام application pool ایی است که برای برنامهی وب خود ایجاد کردهایم (بهتر است به ازای هر برنامهی وب، یک application pool مجزا تعریف شود).
در اینجا بر روی OK کلیک کرده و به این کاربر جدید اضافه شده، دسترسی full control را بدهید تا برنامه و یوزر آن بتواند فایلهای mdf و ldf را ایجاد کرده و به روز رسانی کنند.
پس از تنظیم load user profile و همچنین set profile environment و دادن دسترسی write به کاربر application pool برنامه، اکنون child process مربوط به local db را میتوان ذیل پروسهی IIS مشاهده کرد و برنامه قادر به استفادهی از LocalDB خواهد بود:
تغییرات مهندسی NET Core.
CoreFx یا هستهی NET Core.، متشکل است از صدها بستهی نیوگت. در نگارش بعدی (نگارش 2) تنها یک Microsoft.NETCore.App وجود خواهد داشت تا دیگر توسعه دهندهها نیازی به ذکر تک تک بستههای مورد نیاز هسته را نداشته باشند. این تغییر به معنای بالا رفتن حجم برنامههای نهایی نیست و کار تهیه و توزیع برنامههای متکی به خود همانند قبل است. هدف صرفا ساده کردن مدیریت پروژه و کم کردن بستههای نیوگت هسته است.
دستور update-package به صورت خودکار تمام وابستگیهای یک پروژه را به روز میکند و این به روز رسانی شامل تبدیل یک پروژهی MVC 4 به 5 نیز میشود. اما ... اگر نخواهیم اتفاق بیفتد چطور؟ برای رفع این مشکل دستور update-package -safe را صادر کنید. سوئیچ safe سبب میشود تا اگر نگارش 4 بستهای مورد استفادهاست، دیگر به نگارش 5 آن مراجعه نکند.