مطالب
ساخت گزارش Code coverage مربوط به تست‌ها
اگر برای پروژه‌های خود تست نویسی انجام می‌دهید، یکی از موارد مهم، Code coverage مربوط به تست‌ها می‌باشد که نشان می‌دهد چند درصد از کدهای شما تست شده، کدام قسمت از کد، تست نشده‌است و ... .
در این مطلب نحوه‌ی استفاده از ReportGenerator را برای ایجاد گزارش مربوط به Code coverage، ارائه می‌دهیم. ReportGenerator دیتاهای تولید شده‌ی توسط coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover و ... را به یک گزارش قابل درک در فرمت‌های Html, Coberura و CSV تبدیل می‌کند. در  این مطلب چند موردتست نویسی با xUnit در Asp.Net Core  را نوشته‌ام و اکنون می‌خواهیم برای تست‌های نوشته شده، Code coverage آنها را بدست آوریم.
در کد زیر، سه تست برای متد AverageUsersAge نوشته شده است:
[Fact]
public async Task AverageUsersAge_When_Repository_Return_Null_Then_Zero_Should_Be_Returned()
{
    _userRepository.Setup(a => a.GetAllUsers())
        .ReturnsAsync((List<User>)null);
    var result = await _userService.AverageUsersAge();
    result.Should().Be(0);
}
[Fact]
public async Task AverageUsersAge_When_Repository_Return_Empty_Then_Zero_Should_Be_Returned()
{
    _userRepository.Setup(a => a.GetAllUsers())
        .ReturnsAsync(new List<User>());
    var result = await _userService.AverageUsersAge();
    result.Should().Be(0);
}
[Fact]
public async Task AverageUsersAge_When_Repository_Return_List_Of_Users_Then_Average_Of_Age_Should_Be_Retunred()
{

    _userRepository.Setup(a => a.GetAllUsers())
        .ReturnsAsync(UserMockData.People);
    var result = await _userService.AverageUsersAge();
    var expected = (UserMockData.AdultUser.Age + UserMockData.ChildUser.Age + UserMockData.InfantUser.Age) / 3;
    result.Should().Be(expected);
}
اکنون اگر بخواهیم Code coverage مربوط به این تست‌ها را مشاهده کنیم، ابتدا باید پکیج coverlet.collector  را در پروژه‌ی تست نصب کنیم. سپس باید دستور زیر را برای نصب ReportGenerator اجرا کنید؛ درون powershell:
dotnet tool install -g dotnet-reportgenerator-globaltool
اکنون میتوانیم Code coverage تست‌ها را تولید کنیم و با استفاده از ReportGenerator، آن‌را به قالب HTML تبدیل کنیم. اگر به مسیر پروژه تست خود بروید و دستور زیر را وارد کنید:
dotnet test --collect:"XPlat Code Coverage"
در پروژه‌ی تست شما، یک پوشه به نام TestResults ایجاد می‌شود و همچنین یک فایل xml با عنوان coverage.cobertura ایجاد شده‌است که نتیجه‌ی Code coverage مربوط به تست‌های شما در آن قرار دارد. 
اکنون می‌توانید با استفاده از ReportGenerator گزارش تست‌های خود را از فایل ایجاد شده، تهیه کنید. برای این کار باید دستور زیر را در مسیر پروژه تست، در powershell  وارد کنید:
reportgenerator -reports:"C:\Users\Farhad\source\repos\xUnitExample\xUnitExample.Tests\TestResults\*\coverage.cobertura.xml" -targetdir:"coveragereport" -reporttypes:Html
در پارامتر reports باید مسیر فایل xml ایجاد شده مربوط به Code coverage را قرار دهید (با هر بار اجرای دستور "dotnet test --collect:"XPlat Code Coverage یک فایل xml جدید ایجاد می‌شود و ممکن است در سیستم شما مقدار GUID ایجاد شده، تفاوت داشته باشد). 
درون پوشه TestResults یک پوشه دیگر قرار دارد که نام آن پوشه، یک GUID می‎‌باشد و به همین دلیل به جای استفاده از GUID از * استفاده کرده‌ایم.
 اگر دستور بالا را اجرا کنید باید خروجی زیر را مشاهده کنید:
2021-11-18T14:05:02: Arguments
2021-11-18T14:05:02:  -reports:C:\Users\Farhad\source\repos\xUnitExample\xUnitExample.Tests\TestResults\*\coverage.cobertura.xml
2021-11-18T14:05:02:  -targetdir:coveragereport
2021-11-18T14:05:02:  -reporttypes:Html
2021-11-18T14:05:02: Writing report file 'coveragereport\index.html'
2021-11-18T14:05:02: Report generation took 0.3 seconds
اکنون اگر در مسیری که دستور بالا را اجرا کردید بروید، یک پوشه به نام coveragereport مشاهده می‌کنید که یک فایل index.html دارد و اگر آنرا در مرورگر مشاهده کنید، Code coverage مربوط به تست‌های نوشته شده را مشاهده میکنید:


در عکس ارسال شده، تست‌های نوشته شده برای تمامی لایه‌ها به صورت جدا ایجاد شده‌است.
تست مربوط به UserService:

در عکس بالا قسمت‌هایی که تست شده‌اند، با رنگ سبز مشخص می‌شود و اگر قسمتی از کد تست نشده باشد، با رنگ قرمز مشخص می‌شود. 

برای مثال در عکس زیر مشخص شده‌است که برای فایل ApplicationConfiguration هیچ تستی نوشته نشده‌است.


اگر از CICD استفاده میکنید، می‌توانید در قسمت CI پروژه، هربار دستورات بالا را اجرا کنید و Code coverage مربوط به هر Build را به صورت جداگانه در کنار فایل‌های آپلود شده داشته باشد.
نکته: برای اجرای دستورات بالا و ساخت گزارش باید ورژن SDK نصب شده بر روی سیستم شما برابر 2.2.401 یا بیشتر باشد و ورژن Microsoft.NET.Test.Sdk برابر 16.5.0 یا بیشتر باشد.

مطالب
امکان ساخت برنامه‌های دسکتاپ چندسکویی Blazor در دات نت 6
در این مطلب، روش ساخت یک برنامه‌ی دسکتاپ چندسکویی Blazor 6x را که امکان به اشتراک گذاری کدهای خود را با یک برنامه‌ی WinForms دارد، بررسی خواهیم کرد.


ایجاد برنامه‌های ابتدایی مورد نیاز

در ابتدا دو پوشه‌ی جدید BlazorServerApp و WinFormsApp را ایجاد می‌کنیم. سپس از طریق خط فرمان در اولی دستور dotnet new blazorserver و در دومی دستور dotnet new winforms را اجرا می‌کنیم تا دو برنامه‌ی خالی Blazor Server و همچنین Windows Forms، ایجاد شوند. برنامه‌ی WinForms ایجاد شده مبتنی بر NET Core. و یا همان NET 6x. است؛ بجای اینکه مبتنی بر دات نت فریم‌ورک 4x باشد.


ایجاد یک پروژه‌ی کتابخانه‌ی Razor

چون می‌خواهیم کدهای برنامه‌ی BlazorServerApp ما در برنامه‌ی WinForms قابل استفاده باشد، نیاز است فایل‌های اصلی آن‌را به یک پروژه‌ی razor class library منتقل کنیم. به همین جهت برای این پروژه‌، یک پوشه‌ی جدید را به نام BlazorClassLibrary ایجاد کرده و درون آن دستور dotnet new razorclasslib را اجرا می‌کنیم.


انتقال فایل‌های پروژه‌ی Blazor به پروژه‌ی کتابخانه‌ی Razor

در ادامه این فایل‌ها را از پروژه‌ی BlazorServerApp به پروژه‌ی BlazorClassLibrary منتقل می‌کنیم:
- کل پوشه‌ی Data
- کل پوشه‌ی Pages
- کل پوشه‌ی Shared
- فایل App.razor
- فایل Imports.razor_
- کل پوشه‌ی wwwroot

پس از اینکار، نیاز است فایل csproj کتابخانه‌ی class lib را اندکی ویرایش کرد تا بتواند فایل‌های اضافه شده را کامپایل کند:
<Project Sdk="Microsoft.NET.Sdk.Razor">
  <PropertyGroup>
    <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>
- چون برنامه از نوع Blazor Server است، ارجاعی به AspNetCore را نیاز دارد و همچنین برای فایل‌های cshtml آن نیز باید AddRazorSupportForMvc را به true تنظیم کرد.
- به علاوه فایل Error.cshtml.cs انتقالی، نیاز به افزودن فضای نام using Microsoft.Extensions.Logging را خواهد داشت.
- در فایل Imports.razor_ انتقالی نیاز است دو using آخر آن‌را که به BlazorServerApp قبلی اشاره می‌کنند، به BlazorClassLibrary جدید ویرایش کنیم:
@using BlazorClassLibrary
@using BlazorClassLibrary.Shared
- این تغییر فضای نام جدید، شامل ابتدای فایل BlazorClassLibrary\Pages\_Host.cshtml انتقالی هم می‌شود:
@namespace BlazorClassLibrary.Pages
- چون wwwroot را نیز به class library منتقل کرده‌ایم، جهت اصلاح مسیر فایل‌های css استفاده شده‌ی در برنامه، فایل BlazorClassLibrary\Pages\_Layout.cshtml را گشوده و تغییر زیر را اعمال می‌کنیم:
<link rel="stylesheet" href="_content/BlazorClassLibrary/css/bootstrap/bootstrap.min.css" />
<link href="_content/BlazorClassLibrary/css/site.css" rel="stylesheet" />
در مورد این مسیر ویژه، در مطلب «روش ایجاد پروژه‌ها‌ی کتابخانه‌ای کامپوننت‌های Blazor» بیشتر بحث شده‌است.


پس از این تغییرات، برای اینکه برنامه‌ی BlazorServerApp موجود، به کار خود ادامه دهد، نیاز است ارجاعی از پروژه‌ی class lib را به فایل csproj آن اضافه کنیم:
<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <ProjectReference Include="..\BlazorClassLibrary\BlazorClassLibrary.csproj" />
  </ItemGroup>
</Project>
اکنون جهت آزمایش برنامه‌ی Blazor Server، یکبار دستور dotnet run را در ریشه‌ی آن اجرا می‌کنیم تا مطمئن شویم انتقالات صورت گرفته، سبب کار افتادن آن نشده‌اند.


ویرایش برنامه‌ی WinForms جهت اجرای کدهای Blazor

تا اینجا برنامه‌ی Blazor Server ما تمام فایل‌های مورد نیاز خود را از BlazorClassLibrary دریافت می‌کند و بدون مشکل اجرا می‌شود. در ادامه می‌خواهیم کار هاست این class lib را در برنامه‌ی WinForms نیز انجام دهیم. به همین جهت در ابتدا ارجاعی را به class lib به آن اضافه می‌کنیم:
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <ProjectReference Include="..\BlazorClassLibrary\BlazorClassLibrary.csproj" />
  </ItemGroup>
</Project>
سپس کامپوننت جدید WebView را به پروژه‌ی WinForms اضافه می‌کنیم:
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebView.WindowsForms" Version="6.0.101-preview.11.2349" />
  </ItemGroup>
</Project>

در ادامه نیاز است فایل Form1.Designer.cs را به صورت دستی جهت افزودن این WebView اضافه شده، تغییر داد:
namespace WinFormsApp;

partial class Form1
{
    private void InitializeComponent()
    {
      this.blazorWebView1 = new Microsoft.AspNetCore.Components.WebView.WindowsForms.BlazorWebView();

      this.SuspendLayout();

      this.blazorWebView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
      this.blazorWebView1.Location = new System.Drawing.Point(13, 181);
      this.blazorWebView1.Name = "blazorWebView1";
      this.blazorWebView1.Size = new System.Drawing.Size(775, 257);
      this.blazorWebView1.TabIndex = 20;
      this.Controls.Add(this.blazorWebView1);

      this.components = new System.ComponentModel.Container();
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(800, 450);
      this.Text = "Form1";

      this.ResumeLayout(false);
    }

     private Microsoft.AspNetCore.Components.WebView.WindowsForms.BlazorWebView blazorWebView1;
}
کامپوننت WebView را نمی‌توان از طریق toolbox به فرم اضافه کرد؛ به همین جهت باید فایل فوق را به نحوی که مشاهده می‌کنید، اندکی ویرایش نمود.


هاست برنامه‌ی Blazor در برنامه‌ی WinForm

پس از تغییرات فوق، نیاز است فایل‌های wwwroot را از پروژه‌ی class lib به پروژه‌ی WinForms کپی کرد. از این جهت که این فایل‌ها از طریق index.html جدیدی خوانده خواهند شد. پس از کپی کردن این پوشه، نیاز است فایل csproj پروژه‌ی WinForm را به صورت زیر اصلاح کرد:
<Project Sdk="Microsoft.NET.Sdk.Razor">

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebView.WindowsForms" Version="6.0.101-preview.11.2349" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\BlazorClassLibrary\BlazorClassLibrary.csproj" />
  </ItemGroup>
  
  <ItemGroup>
    <Content Update="wwwroot\**">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  
</Project>
Sdk این فایل تغییر کرده‌است تا بتواند از wwwroot ذکر شده استفاده کند. همچنین به ازای هر Build، فایل‌های واقع در wwwroot به خروجی کپی خواهند شد.
در ادامه داخل این پوشه‌ی wwwroot که از پروژه‌ی class lib کپی کردیم، نیاز است فایل index.html جدیدی را که قرار است blazor.webview.js را اجرا کند، به صورت زیر ایجاد کنیم:
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Blazor WinForms app</title>
    <base href="/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
    <link href="WinFormsApp.styles.css" rel="stylesheet" />
</head>

<body>
    <div id="app"></div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="">Reload</a>
        <a>🗙</a>
    </div>

    <script src="_framework/blazor.webview.js"></script>
</body>

</html>
- ساختار این فایل بسیار شبیه به ساختار فایل برنامه‌های Blazor WASM است؛ با این تفاوت که در انتهای آن از blazor.webview.js کامپوننت webview استفاده می‌شود.
- همچنین در این فایل باید مداخل css.‌های مورد نیاز را هم مجددا ذکر کرد.

مرحله‌ی آخر کار، استفاده از کامپوننت webview جهت نمایش فایل index.html فوق است:
using System;
using System.Windows.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
using Microsoft.Extensions.DependencyInjection;
using BlazorServerApp.Data;
using BlazorClassLibrary;

namespace WinFormsApp;

public partial class Form1 : Form
{
private readonly AppState _appState = new();

    public Form1()
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddBlazorWebView();
        serviceCollection.AddSingleton<AppState>(_appState);
        serviceCollection.AddSingleton<WeatherForecastService>();

        InitializeComponent();

        blazorWebView1.HostPage = @"wwwroot\index.html";
        blazorWebView1.Services = serviceCollection.BuildServiceProvider();
        blazorWebView1.RootComponents.Add<App>("#app");

        //blazorWebView1.Dock = DockStyle.Fill;
    }
}


نکته‌ی مهم! حتما نیاز است WebView2 Runtime را جداگانه دریافت و نصب کرد. در غیر اینصورت در حین اجرای برنامه، با خطای نامفهوم زیر مواجه خواهید شد:
System.IO.FileNotFoundException: The system cannot find the file specified. (0x80070002)

در اینجا یک ServiceCollection را ایجاد کرده و توسط آن سرویس‌های مورد نیاز کامپوننت WebView را تامین می‌کنیم. همچنین مسیر فایل index.html نیز توسط آن مشخص شده‌است. این تنظیمات شبیه به فایل Program.cs برنامه‌ی Blazor هستند.

تا اینجا اگر برنامه را اجرا کنیم، چنین خروجی قابل مشاهده‌است:


اکنون برنامه‌ی کامل Blazor Server ما توسط یک WinForms هاست شده‌است و کاربر برای کار با آن، نیاز به نصب IIS یا هیچ وب سرور خاصی ندارد.


تعامل بین برنامه‌ی WinForm و برنامه‌ی Blazor


می‌خواهیم یک دکمه را بر روی WinForm قرار داده و با کلیک بر روی آن، مقدار شمارشگر حاصل در برنامه‌ی Blazor را نمایش دهیم؛ مانند تصویر فوق.
برای اینکار در کدهای فوق، ثبت سرویس جدید AppState را هم مشاهده می‌کنید:
serviceCollection.AddSingleton<AppState>(_appState);
 که چنین محتوایی را دارد:
 namespace BlazorServerApp.Data;

public class AppState
{
   public int Counter { get; set; }
}
این سرویس را به نحو زیر نیز به فایل Program.cs پروژه‌ی Blazor Server اضافه می‌کنیم:
builder.Services.AddSingleton<AppState>();
سپس در فایل Counter.razor آن‌را تزریق کرده و به نحو زیر به ازای هر بار کلیک بر روی دکمه‌ی افزایش مقدار شمارشگر، مقدار آن‌را اضافه می‌کنیم:
@inject BlazorServerApp.Data.AppState AppState

// ...


@code {

    private void IncrementCount()
    {
       // ...
       AppState.Counter++;
    }
}
با توجه به Singleton بودن آن و هاست برنامه‌ی Blazor توسط WinForms، یک وهله از این سرویس، هم در برنامه‌ی Blazor و هم در برنامه‌ی WinForms قابل دسترسی است. برای نمونه یک دکمه را به فرم برنامه‌ی WinForm اضافه کرده و در روال رویدادگردان کلیک آن، کد زیر را اضافه می‌کنیم:
private void button1_Click(object sender, EventArgs e)
{
   MessageBox.Show(
     owner: this,
     text: $"Current counter value is: {_appState.Counter}",
     caption: "Counter");
}
در اینجا می‌توان با استفاده از وهله‌ی سرویس به اشتراک گذاشته شده، به مقدار تنظیم شده‌ی در برنامه‌ی Blazor دسترسی یافت.

کدهای کامل این مطلب را از اینجا می‌توانید دریافت کنید: BlazorDesktopHybrid.zip
مطالب
آشنایی با قابلیت جدید ASP.NET Web Forms Scaffolding
مایکروسافت با افزایش سرعت به روز رسانی توسعه پروژه‌های سورس باز خود جهت پاسخ دادن به نیاز توسعه دهندگان و توسعه ویژوال استادیو مطابق با آخرین تکنولوژی‌های تولید وب سایت، می‌کوشد تعداد بیشتری از توسعه دهندگان را به سمت استفاده از تکنولوژی‌های خود سوق دهد. 

سالها است که برنامه نویسان خبره با توجه به روش کاری خود از امکانات Code Generatorها برای تولید کدهای لایه‌های Data Access ، Logic و یا حتی User Interface استفاده می‌نمایند. پس از عرضه Entity Framework و تولید خودکار کدهای لایه های Data Access و Logic، این بار این امکان علاوه بر ASP.NET MVC در ASP.NET Web Forms نیز فراهم گردیده‌است تا بدون کد نویسی خسته کننده و تکراری، کدهای لایه رابط کاربر (Create-Read-Update-Delete (CRUD را نیز تولید نماییم. 

شروع کار با ASP.NET Scaffolding
پیش نیاز این کار استفاده از Visual Studio 2012 به همراه Web Tools 2012.2 می‌باشد.
  1. اول، ابزار Microsoft ASP.NET Scaffolding را از منوی Tools گزینه Extensions and Updates دریافت و نصب نمایید.
  2. دوم پروژه جدیدی از نوع Visual C# ASP.NET Web Forms Application با فریم ورک 4.5 ایجاد نمایید.
  3. از پنجره NuGet Package manager با دستور install کتابخانه ASP.NET Web Forms Scaffold Generator را دریافت نمایید
    install-package Microsoft.AspNet.Scaffolding.WebForms -pre
  4. کلاس Person را مانند زیر در فولدر Models ایحاد نمایید
     public class Person
        {
            [ScaffoldColumn(false)]
            public int ID { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
    ویژگی ScaffoldColumn را برای ID، برابر false قرار دهید تا از ایجاد این ستون جلوگیری نمائید.
  5. پروژه را Build نمایید.
  6. بر روی پروژه راست کلیک و از گزینه Add، گزینه ...Scaffold را انتخاب نمایید.

  7. از پنجره Add Scaffold باز شده بر روی گزینه Add، کلیک کنید.

  8. پنجره  Add Web Forms Pages مانند زیر باز می‌شود که امکان انتخاب کلاس،Data Context و MasterPage فراهم می‌باشد.

  9. از گزینه Data Context class گزینه New Data Context را انتخاب نمایید. صفحات مورد نیاز را در فولدر Views/Person ایجاد می‌نمایید.
  10. کد‌های تولید شده را می‌توانید بازبینی نمایید پروژه را اجرا تا خروجی کار را مشاهده نمایید.

اشتراک‌ها
کتابخانه hammer.js
A javascript library for multi-touch gestures.
You can get the pre-build versions from the Hammer.js website, or do this by yourself running
npm install -g grunt-cli && npm install && grunt build

 
کتابخانه hammer.js
اشتراک‌ها
تفاوت دستور Delete و Truncate
تفاوت Delete  و  Truncate :
دستور  Delete  جز دستورات  DML  هست یا بعبارتی  Data Manipulation Language میباشد که برای اعمالی چون واکشی ، ذخیره سازی ، تغییرات و حذف مورد استفاده قرار میگیرند
دستور  Truncate  جز دستورات  DDL  هست یا بعبارتی  Data Definition Language می‌باشد و برای ایجاد ,  تغییرات  در ساختار آبجکت‌ها ( مثل جدول ، ایندکس و ..) مورد استفاده قرار میگیرد
دستور Delete  در زمان اجرا قفل گذاری را در سطح ردیف انجام میدهد (row lock) 
دستور Truncate  قفل گذاری را در سطح جدول در نظر میگیرد (table lock)
دستور Delete میتواند شامل فیلتر (where) برای حذف ردیف‌های خاصی باشد
دستور  Truncate  نمیتواند شامل فیلتر (where) باشد و روی حذف تمام جدول عمل میکند
نکته :
با استفاده از دستور Delete  میتوان بخشی از رکوردهای مشخص را حذف نمود ولی با دستور  Truncate  تمام رکوردها ی جدول حذف می‌شوند  (دستور Truncate نتیجه اجرای دو دستور  Drop  و  Create  می‌باشد)
دستور Delete  نسبت به دستور Truncate  کندتر عمل میکند زیرا تمام تغییرات در Log  ذخیره میکند در نتیجه قابلیت  Rollback  ممکن می‌باشد
دستور Truncate  نسبت به دستور Delete سریعتر عمل میکند زیرا به ازای  اجرای آن در فایل  Log  چیزی ثبت نمیشود در نتیجه قابلیت  Rollback  را ندارد
همراه دستور Delete  قابلیت اجرای  تریگر را داریم
در اجرای دستور Truncate  قابلیت اجرای تریگر را نداریم
نکته:
اگر  از Transaction استفاده کنیم هر  دو دستور  Delete  و  Truncate  قابلیت rollback  شدن را دارا هستند  
تفاوت دستور  Delete  و  Truncate
مطالب
اجرای برنامه‌های ASP.NET به کمک وب سرور Apache توسط Mono در Ubuntu
در قسمت قبل نحوه‌ی اجرای برنامه‌های ASP.NET را به کمک وب سرور آزمایشی Mono بررسی کردیم. بدیهی است این وب سرور برای هاست کردن سایت‌ها و خدمات دهی عمومی، مناسب نیست و صرفا جهت کارهای برنامه نویسی طراحی شده است. در ادامه، ابتدا وب سرور معروف آپاچی را نصب کرده و سپس سعی خواهیم کرد تا همان دو برنامه ASP.NET Web forms و ASP.NET MVC قسمت قبل را بر روی آن اجرا کنیم (دو برنامه خالی ASP.NET کامپایل شده که از ویندوز به لینوکس کپی شده بودند).


نصب وب سرور آپاچی
به اینترنت متصل شده، ترمینال Ubuntu را گشوده (با میانبر ctrl+alt+t) و سپس فرمان‌های ذیل را صادر کنید:
 sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install apache2
به این ترتیب Apache web server بر روی سیستم نصب خواهد شد.


نصب ماژول‌های ASP.NET مخصوص آپاچی
سپس نیاز است ASP.NET runtime for Apache را نصب کنیم:
 sudo apt-get install libapache2-mod-mono mono-apache-server4
mod_mono درون پروسه آپاچی اجرا شده و تمام درخواست‌های رسیده به یک وب سایت ASP.NET را به mod-mono-server که کار هاست سایت را انجام می‌دهد، انتقال خواهد داد.
اگر علاقمند به مشاهده تنظیمات آن بودید باید به مسیر etc/apache2/mods-enabled مراجعه کرده و فایل mod_mono.conf را بررسی کنید (اختیاری). برای مثال، در آن حالت اجرا، بر روی ASP.NET 4 تنظیم شده‌است.

تنظیمات آپاچی برای کار با ASP.NET
نیاز است فایل تنظیمات پیش فرض وب سرور آپاچی را جهت معرفی ASP.NET به آن، اندکی ویرایش کنیم:
 sudo gedit /etc/apache2/sites-available/default
در ادیتور باز شده، ذیل قسمت ServerAdmin، موارد زیر را اضافه کنید:
 MonoAutoApplication disabled
AddHandler mono .aspx .ascx .asax .ashx .config .cs .asmx .axd
MonoApplications "/:/var/www"
MonoServerPath default "/usr/bin/mod-mono-server4"
در ادامه به المان Directory /var/www سطرهای زیر را اضافه کنید:
 SetHandler mono
DirectoryIndex index.aspx index.html default.aspx Default.aspx
المان جدید ذیل را در انتهای فایل اضافه کنید تا یک سری از پوشه‌های خاص ASP.NET همانند محیط‌های ویندوزی در آپاچی نیز محافظت شوند:
 <DirectoryMatch "/([bB]in|[Aa]pp_[Cc]ode|[Aa]pp_[Dd]ata|[Aa]pp_[Gg]lobal[Rr]esources|[Aa]pp_[Ll]ocal[Rr]esources)/">
Order deny,allow
Deny from all
</DirectoryMatch>
فایل را ذخیره کرده و ادیتور را ببندید. اکنون وب سرور آپاچی را اجرا و ری استارت کنید:
 sudo service apache2 restart
همچنین سطح دسترسی مسیر var/www که حاوی برنامه‌های ما خواهد بود نیز باید تغییر کند:
 # r,w,exec for user + group
sudo chgrp -R www-data /var/www
sudo chown -R www-data /var/www
sudo chown -R www-data:www-data /var/www
sudo chmod -R 755 /var/www
اکنون اگر آدرس http://127.0.0.1 را در مرورگر وارد کنید، باید پیام «It Works» را مشاهده کنید و اگر خواستید محتوای آن‌را ویرایش کنید، دستور ذیل را صادر نمائید:
 gedit /var/www/index.html

اجرای مثال‌ها

با تنظیمات فوق، برنامه‌های کپی شده در مسیر var/www به کمک مونو و آپاچی اجرا خواهند شد.
دسترسی‌های فعلی کاربر وارد شده به لینوکس اجازه کپی فایل‌ها را به مسیر var/www نمی‌دهد. همچنین می‌خواهیم این کارها را توسط File browser آن انجام دهیم و نه خط فرمان. برای این منظور دستور ذیل را اجرا کنید تا File browser آن با دسترسی مدیریتی اجرا شود:
 sudo nautilus
الان می‌توان بدون مشکل در همان File browser گرافیکی آن، پوشه مثال وب فرم‌های خود را به درون پوشه var/www کپی کرد.
پس از کپی دو برنامه Web forms و MVC ابتدای بحث، نیاز است مجددا فایل تنظیمات آپاچی را ویرایش کنیم:
 sudo gedit /etc/apache2/sites-available/default
اکنون تنظیم برنامه وب فرم را به نحو ذیل به این فایل اضافه کنید:
 AddMonoApplications default "/webforms_test:/var/www/WebFormsApp/"
<Location /webforms_test>
SetHandler mono
</Location>
در تنظیم webforms_test:/var/www/WebFormsApp/، قسمت webforms_test نامی است که در مرورگر وارد خواهد شد و قسمت بعد از : مسیر فایل‌های برنامه و ریشه سایت است.
و تنظیم برنامه MVC به صورت زیر می‌باشد:
 AddMonoApplications default "/mvc_test:/var/www/Mvc4ProjectApp/"
<Location /mvc_test>
SetHandler mono
</Location>
بعد از هر بار تغییر فایل تنظیمات آپاچی باید یکبار وب سرور را توسط دستور sudo service apache2 restart ری استارت کنیم.
اکنون برنامه وب فرم‌ها در مسیر http://127.0.0.1/webforms_test و برنامه MVC در مسیر http://127.0.0.1/mvc_test قابل دسترسی است.


خلاصه بحث
پس از نصب وب سرور آپاچی و ماژول مونوی مخصوص آن، فایل etc/apache2/sites-available/default را به نحو ذیل ویرایش کنید و مسیرهای برنامه‌های خود را در آن تعریف نمائید:

<VirtualHost *:80>
ServerAdmin webmaster@localhost
        MonoAutoApplication disabled
        AddHandler mono .aspx .ascx .asax .ashx .config .cs .asmx .axd
        MonoApplications "/:/var/www"
        MonoServerPath default "/usr/bin/mod-mono-server4"

DocumentRoot "/var/www"
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
                SetHandler mono
                DirectoryIndex index.aspx index.html default.aspx Default.aspx
Options Indexes Includes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all                
</Directory>

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>

        <DirectoryMatch "/([bB]in|[Aa]pp_[Cc]ode|[Aa]pp_[Dd]ata|[Aa]pp_[Gg]lobal[Rr]esources|[Aa]pp_[Ll]ocal[Rr]esources)/">
          Order deny,allow
          Deny from all
        </DirectoryMatch>

        AddMonoApplications default "/webforms_test:/var/www/WebFormsApp/"
        <Location /webforms_test> 
         SetHandler mono
        </Location>

       AddMonoApplications default "/mvc_test:/var/www/Mvc4ProjectApp/"
        <Location /mvc_test> 
         SetHandler mono
        </Location>

ErrorLog ${APACHE_LOG_DIR}/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>


مطالب
آموزش فایرباگ - #7 - CSS Panel
پنل CSS مانند پنل جانبیِ Style که در مقاله‌ی قبل بررسی کردیم است با این تفاوت که امکانات بیشتری برای افرادی که قصد تصریف استایل دارند محیا کرده است.
در این پنل می‌توان به اضافه ، ویرایش و حذف استایل هایی که به صفحه‌ی جاری توسط فایل‌های مختلف اضافه شده اند و یا داخل خود صفحه تعریف شده اند پرداخت.



همچنین در این پنل امکان ویرایش یک فایل css بصورت کامل وجود دارد ، به این صورت که می‌توانید تمام محتویات فایل مورد نظر را در یک Text area ویرایش کنید.

مطابق با روالی که در قسمت قبل پیش گرفتیم عمل می‌کنیم و به ترتیب به تشریح ابزار پنل ، خود پنل ، منوی راست کلیک و پنل جانبی ِ Elements می‌پردازیم.


Options Menu
با راست کلیک کردن بروی تب CSS و یا کلیک کردن بروی فلش کوچک روی تب CSS قابل دسترس است و امکانات زیر را محیا می‌کند:

  • Expand Shorthand Properties : نمایش دستورات css بصورت کامل ، به این معنی که دستوراتی مانند margin که هم بصورت خلاصه و هم بصورت کامل تعریف می‌شوند را بصورت کامل نمایش می‌دهد. مثلا margin را چهار مقدار margin-top , margin-right , margin-bottom , margin-left نمایش می‌دهد.

  • Color As Hex , Color As RGB , Color As HSL : با انتخاب یکی از سه مقدار ذکر شده ، فرمت نمایش رنگ‌ها به حالت انتخاب شده تغییر می‌کند.
    مثلا دستور color : #000000 به این صورت نمایش داده می‌شود :‭ color : rgb(0, 0, 0) 

  • Refresh : این گزینه محتویات پنل را بروز می‌کند.

Panel Toolbar
ابزاری موجود در این پنل مشابه پنل‌های دیگر در بالای پنل و در زیر تب پنل‌ها قرار دارد و شامل ابزارهای زیر می‌شود:

  • Edit Button : این ابزار به دو صورت Live Edit و Source Edit در دسترس هست که با کلیک بروی فلش کوچکی که در سمت راست دکمه قرار دارد می‌توان نوع آن را تغییر داد.
    انتخاب حالت Source Edit ، باعث می‌شود سورس فایل به همان صورتی که به مرورگر ارسال شده نمایش داده شود. ( کامنت‌ها ، فرمت فایل و ... حفظ می‌شود. )
    حالت Live Edit هم باعث نمایش محتویات فایل بصورت مرتب شده می‌شود. ( کامنت‌ها و دستوراتی که توسط مرورگر تفسیر نشده اند نمایش داده نمی‌شوند. )



  • CSS Location Menu : نام فایل جاری که در پنل در حال نمایش است را نمایش می‌دهد و همچنین با کلیک بروی آن ، فایل‌های استایل دیگری که در صفحه بارگزاری شده اند را نمایش می‌دهد. با کلیک بروی هرکدام از فایل‌های نمایش داده شده ، همان فایل در پنل باز می‌شود.

    استایل هایی که در خود صفحه تعریف شده اند با نام خود صفحه در این قسمت نمایش داده می‌شوند و اگر استایل‌های در چندین تگ style تعریف شده باشند ، دومین تگ با #2 ، سومین با #3 و ... مشخص می‌شوند.

    هنگام باز بودن :
    1- فایل هایی که از پوشه‌های مختلف در صفحه بارگذاری شده اند ، با نام پوشه از هم تفکیک شده اند:



    2- با تایپ کردن عبارت دلخواه می‌توان نتایج را محدود کرد:



Panel
منظور از پنل ، قسمتی هست که استایل بصورت فرمت شده و نمایش داده شده است.


 Infotips
توسط این قابلیت ، زمانی که موس را بروی آدرس تصاویر ، نوع فونت و ... ببرید ، پاپ آپ کوچکی باز می‌شود و اطلاعاتی در مورد مقادیر می‌دهد. مثلا اینکه آیا تصویر مورد نظر به درستی بارگذاری شده یا نه ، نمای کوچکی از تصویر ، شکل فونت و ...

 Editing rules
برای ویرایش تعاریف CSS شامل Selector‌ها ، دستورات و مقادیر ، این پنل ابزارهای مفیدی ارائه می‌کند.
برای ویرایش یک selector ، دستور یا مقدار آن بروی آن عبارت کلیک کنید ، در همین حال یک text box ظاهر می‌شود و می‌توانید مقدار جدید را وارد کنید. پس از انجام ویرایش مورد نظر بروی قسمتی از صفحه کلیک کنید یا کلید Tab سپس Esc را بزنید. برای ویرایش دستورات بعدی ، کلید Tab را بزنید و برای لغو تغییر جاری ، کلید Esc را بزنید.

برای ایجاد یک rule جدید ، بروی قسمتی از پنل راست کلیک کرده و سپس گزینه‌ی "New Rule..." را برگزینید.
برای ایجاد یک property هم چند راه وجود دارد:

  • بروی قسمت از فضای خالی تعریف یک استایل دوبار کلیک کنید.
  • در قسمتی از تعریف یک استایل راست کلیک کرده و گزینه‌ی "New Property..." را انتخاب کنید.
  • بروی مقدار آخرین property کلیک کرده و کلید Tab را بزنید.


هنگام ویرایش یا ایجاد یک Rule , Propery یا مقدار بصورت inline ، حاشیه‌ی text box متناسب با مقدار وارد شده رنگی را که نمایانگر حالت ذخیره‌ی مقدار وارد شده است نمایش می‌دهد. برای مثال اگر مقداری که برای یک selector وارد شده است نامعتبر باشد ، رنگ حاشیه‌ی text box قرمز می‌شود.
جدول زیر حالت‌های مختلف را شرح می‌دهد:

رنگ حاشیه
Selectorها
نام Properyها
مقادیر Propertyها و Ruleها
 خاکستری تغییری ایجاد نشده استتغییری ایجاد نشده است
تغییری ایجاد نشده است
 قرمز selector نامعتبر است
نام نامعتبر است
مقدار نامعتبر است
 زرد selector صحیح است اما بروی Element فعلی تاثیر ندارد
نام صحیح است اما مقدار Property غیر مجاز است یا وارد نشده است
 
 سبز selector صحیح است نام و مقدار صحیح هستند
مقدار صحیح است


Auto-completion
زمانی که در حال ایجاد/ویراش کردن یک Rule, Propery یا مقدار آنها هستید ، میتوانید از این قابلیت استفاده کنید. مثلا با وارد کردن # تمام Selector هایی که می‌توانند با # شروع شوند در دسترس شما هستند و با دکمه‌های Up/Down می‌توانید مقادیر ممکن را مرور کنید.
اگر در حال ویرایش یک مقدار عددی هستید ، می‌توانید با دکمه‌های Up/Down مقادیر را یک واحد یک واحد افزایش دهید. با نگه داشتن کلید Shift و فشردن Up/Down می‌توانید مقادیر را 10تا 10تا تغییر دهید و با نگه داشتن Ctrl بجای Sihft ، یک دهم یک دهم.

Toggling styles
با این امکان می‌توانید یک Property را بطور موقت فعال/غیرفعال کنید. با حرکت موس از یک Property یک آیکون قرمز رنگ در کنار آن نمایش داده می‌شود که با کلیک بروی آن ، Property و مقدار آن کمرنگ شده و آیکون قرمز رنگ کنار آن ثابت می‌شود. با کلیک مجدد بروی آن ، Property فعال می‌شود.



Context Menu
این منو زمانی که در پنل راست کلیک کنید ظاهر می‌شود و نسبت به منطقه (Context)ای که در آن راست کلیک کرده اید ، گزینه‌های متفاوتی را مشاهده خواهید کرد. در جدول زیر ، گزینه‌ها ، Contextشان و توضیح هر گزینه آمده است.

 گزینهContext
توضیحات
Copy Location
CSS Location Menuآدرس فایل استایل را در حافظه کپی می‌کند.
Open in New TabCSS Location Menuفایل استایل را در یک تب جدید باز می‌کند.
Copy Image Location
image valuesآدرس تصویر را در حافظه کپی می‌کند.
Open Image in New Tabimage valuesتصویر را در یک تب جدید باز می‌کند.
Copy Colorcolor valuesمقدار رنگ را در حافظه کپی می‌کند.
Copy Rule DeclarationCSS selectorSelector و Propertyها را در حافظه کپی می‌کند.
Copy Style DeclarationCSS selectorفقط Propertyها را در حافظه کپی می‌کند.
New Rule...
همه جای پنل
یک Rule جدید بالای قسمتی که راست کلیک شده ایجاد می‌کند.
Delete "<selector>"
CSS selectorRule را حذف می‌کند.
New Property...
CSS rule
یک Property جدید در Ruleی که در آن راست کلیک شده ایجاد می‌کند.
Edit "<property name>"...
CSS property
Property فعلی به حالت ویرایش درمی آید. ( راه ساده‌تر ، کلیک بروی Property است. )
Delete "<property name>"...CSS propertyProperty فعلی را حذف می‌کند.
Disable "<property name>"...
CSS property
Property فعلی را غیرفعال می‌کند.
Refreshهمه جای پنل
محتویات پنل را بروز رسانی می‌کند.
Inspect in DOM panel
CSS Location Menu, CSS rule
فایل استایل یا Rule را در پنل DOM باز می‌کند.


Elements Side Panel
در این پنل که سمت راست پنل CSS قرار دارد ، با وارد کردن یک CSS Selector می‌توانید Elementهایی که در صفحه با آن مطابقت دارند را مشاهده کنید.
برای وارد کردن CSS Selector هم می‌توان مقدار مورد نظر را در قسمت Try a selector... وارد کرد هم می‌توان بروی یکی از Selectorهای پنل راست کلیک کرد و گزینه‌ی Get Matching Elements را برگزید.
Context Menu این قسمت هم مشابه Context Menu پنل HTML هست و فقط در ورژن 1.11 گزینه‌ی Paste HTML اضافه شده که در این کامنت از مقاله‌ی آموزش فایرباگ - #5 - HTML Panel توضیح داده شده است.

نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 22 - توزیع برنامه توسط IIS
موقعی که از آدرس دامنه رو میزنم چنین خطایی میگیرم و موارد گفته شده نصب هست و نتیجه فایل stdlog خالی هست همچنین نتیجه اجرا از طریق کامند و دستور dotnet  x.dll  روی سرور مشکلی نداره و روی پورت 5000 باز میشه.
ولی Event Viewer خطای زیر رو میده که نمیتونه دستور رو اجرا کنه
Application 'MACHINE/WEBROOT/APPHOST/BWIN.PLUSTEAM.IR' with physical root 'C:\Inetpub\vhosts\plusteam.ir\bwin.plusteam.ir\' failed to start process with commandline 'dotnet .\BetWin.dll', ErrorCode = '0x80070002 : 0.