مطالب
پیدا کردن منشاء خطا در برنامه با آنالیز فایل‌های Dump

هنگامیکه خطاهای غیر منتظره‌ای در برنامه‌ی مدیریت شده‌ی شما رخ می‌دهند، شما اطلاعات کمی را در مورد این مساله دارید. اگرچه شما می‌توانید تا حدودی جلوی این نوع خطاهای غیرمنتظره را با ابزارهای خطایابی و یا لاگر، رصد کنید ولی همیشه اینطور نیست؛ در این حال ذخیره، تجزیه و تحلیل Dump‌های حافظه، ممکن است آخرین گزینه برای شما باشد. خوشبختانه ویژوال استودیو، ابزاری عالی برای تجزیه و تحلیل Dump‌های حافظه است! در این مطلب به شما نشان می‌دهیم که چگونه Dump‌های حافظه را جمع آوری کرده و توسط ویژوال استودیو راه حل مشکلات درج شده‌ی در آن‌ها را پیدا کنید.

ابزارهایی وجود دارند که حافظه را مورد کاوش قرار داده و فعالیت‌هایی را که یک پروسس انجام می‌دهد، مانیتور می‌کنند. در حال حاضر ابزارهای مختلفی برای اینکار وجود دارند؛ از جمله Visual Studio ،ProcDump ،DebugDiag و WinDbg که ما در این پست از ProcDump استفاده می‌کنیم. 

برای شروع، من یک برنامه‌ی ساده را ایجاد کردم که شامل یک button است و با فشردن آن، یک خطای نامشخص اتفاق می‌افتد. برنامه را اجرا میکنیم. سپس به TaskManager رفته و آی‌دی پروسس برنامه را پیدا میکنیم: 

  

آیدی پروسس ما، 10896 می‌باشد.

ProcDump را دانلود کرده و آن‌را توسط CMD، به این صورت اجرا می‌کنیم تا تمامی فعالیت‌های پروسس موردنظر را زیرنظر بگیرد و فایل Dump ای را تولید کند:

 procdump.exe -ma -e 10896


حالا نوبت به کلیک بر روی Button، جهت ایجاد خطا می‌رسد. بر روی دکمه کلیک کرده و منتظر می‌شویم تا Dump، از حافظه جمع آوری و در سیستم تولید شود. عملیات با موفقیت انجام شده و فایل Dump در آدرس مشخص شده، ایجاد می‌شود. 

 

پیدا کردن منشاء خطا  

بعد از ایجاد فایل Dump، نوبت به پیدا کردن منشا خطا و رسیدن به کد موردنظر می‌رسد. ویژوال استودیو را باز کنید و فایل Dump را درون VS درگ/دراپ کنید. 

  

در پنجره‌ای که باز می‌شود، می‌توانید مشخصات کاملی از برنامه را مشاهده کنید. سمت راست، چند گزینه وجود دارند که با توجه به نوع برنامه (مدیریت شده یا محلی) و زبان برنامه نویسی، باید آن‌ها را انتخاب کنید. از آنجائیکه برنامه‌ی ما با زبان سی شارپ ایجاد شده، گزینه‌ی اول یعنی Debug with Managed only را انتخاب می‌کنیم.

بعد از انتخاب این گزینه، بلافاصله به کدی که باعث ایجاد خطا می‌شود، هدایت می‌شویم

 

کلام آخر اینکه سعی کنید تا حد ممکن، خودتان خطاها را مدیریت کنید و از ابزارهای خطایاب مانند AppCenter نیز استفاده کنید. اخیرا WPF و WinForm نیز به AppCenter اضافه شده‌اند. 

مطالب
ساخت گزارش 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 یا بیشتر باشد.

نظرات مطالب
UrlRewriter توسط Intelligencia.UrlRewriter
من می‌خوام علاوه بر اینکه وقتی به یه صفحه جدید میرم آدرس عوض بشه، توی همون صفحه هم با ایجاد تغییراتی آدرس صفحه ام عوض بشه. مثلا وقتی کاربر سرچ می‌کنه صفحه تغییر نمی‌کنه و نتایج سرچ توی همون صفحه نشون داده میشه اما می‌خوام آدرس عوض بشه. به این صورت که عبارت سرچ شده توی آدرس بیاد. یا مثلا وقتی از داخل دراپ دان لیست یک ویژگی خاص محصول انتخاب میشه (که اینم به نوعی سرچ هست) اون ویژگی توی آدرس همون صفحه نشون داده بشه.
برای این کار از کدوم روش استفاده کنم بهتر و راحت تره؟ url rewriting, url routing, url friendly ؟
اگه یک راهنمایی هم در مورد اینکه چطور باید این کار رو انجام بدم بکنید ممنون میشم. یعنی وقتی صفحه عوض نمیشه من این تغییر رو دقیقا کجا باید اعمال کنم؟
نظرات مطالب
معرفی کتابخانه PdfReport
با تشکر؛ اگر بخواهیم از pdf report در برنامه‌های سازمانی استفاده کنیم با هر بار درخواست گزارش ،  یک نسخه فایل pdf در کلاینت‌ها دانلود می‌شود  ، و این به مرور باعث میشه فایل‌های زیادی در هر کلاینت بخاطر گزارش‌های مورد درخواستش ذخیره بشه . آیا این روش کار من  اشکالی داره؟ در حالت ویندوزی میشه یک فایل رو بازنویسی کرد و در پوشه اجرائی برنامه فقط یک فایل گزارش تولید میشه ولی در محیط وب  نتونستم راه حلی پیدا کنم ، اگر امکانش هست راهنمائی بفرمائید.
نظرات مطالب
ASP.NET MVC #17
با سلام
من از روش ایجاد فایل web.config برای upload فایل استفاده کردم. جواب هم داد. ولی مشکل این هست که در داخل خود صفحات هم به آن فایل‌ها دسترسی پیدا نمیکنه.
اون صفحه خطای عدم اجازه جهت دسترسی به پوشه ای که مستقیم در مرروگر وارد شده را چه طور سفارشی کنم؟
نظرات مطالب
ساخت دیتابیس sqlite با EF6 Code First
سلام؛ مثال را دانلود کردم و نتایج به شرح زیر است:
1- مثال شما کاملا صحیح و درست کار می‌کند ( احتمالا با VS2013 نوشته اید)
2-با VS2015 سعی کردم پروژه ای مطابق مثال شما بسازم ولی با خطایی که در سایت مشخص کردید برخوردم و برای رفع خطا مطابق دستورات شما رفتار کردم با این حال همچنان با خطا مواجه شدم. خطای Raised شده حاوی عبارت زیر است:
the underlying provider failed to open
تلاش‌های بنده تا در این لحظه حل نشده است.
از شما خواهشمندم یک مثال با VS2015 ایجاد کنید. و در سایت قرار دهید. چرا که وقتی با Nuget  نسخه جدید SQLite.Codefirst و وابسته‌های آن را نصب می‌کنم با نسخه ای که شما از آن در پروژه استفاده کرده اید متفاوت است ( جدید‌تر است)
نظرات مطالب
راه اندازی StimulSoft Report در ASP.NET MVC
با سلام؛ از روش مورد اشاره مقاله استفاده کردم. کد فایل report.chtml به شکل زیر تغییر یافت :
 @Html.Stimulsoft().StiMvcViewer("MVCViewer1", new StiMvcViewerOptions()
           {
               Actions = new StiMvcViewerOptions.ActionOptions()
               {
                   GetReportSnapshot =
                   Url.Action(
                       MVC.TableProduct.Report.ActionNames.CustomReportSnapshot,
                   MVC.TableProduct.Report.Name, new { area = MVC.TableProduct.Name }, "http"),
                   ViewerEvent =
                   Url.Action(
                       MVC.TableProduct.Report.ActionNames.CustomViewerEvent,
                       MVC.TableProduct.Report.Name, new { area = MVC.TableProduct.Name }, "http"),
                   PrintReport =
                   Url.Action(
                       MVC.TableProduct.Report.ActionNames.CustomPrintReport,
                       MVC.TableProduct.Report.Name, new { area = MVC.TableProduct.Name },"http"),
               },
               Server = new StiMvcViewerOptions.ServerOptions()
               {
                   PassFormValues = true,
                   GlobalReportCache = false,
                   Controller = MVC.TableProduct.Report.Name

               },
               Exports = new StiMvcViewerOptions.ExportOptions()
               {
                   ShowExportToPdf = true,
                   ShowExportToCsv = true
               },
               Toolbar = new StiMvcViewerOptions.ToolbarOptions()
               {
                   ShowDesignButton = false,
                   ShowEditorButton = false,
                   ShowParametersButton = false,
                   ShowViewModeButton = true
               },

               Localization = "~/Content/Stimulsoft/Localization/fa.xml",
               Width = Unit.Percentage(100),
               Theme = StiTheme.Office2013,

           })
در این کد مسیر Action‌ها به درستی ایجاد شده است. برای مثال برای متد getReportSnapshot  آدرس زیر تولید شده است :
http://localhost:14425/tableproduct/customreportsnapshot 
این آدرس کاملا صحیح بوده و با PostMan قابل فراخوانی است. اما همچنان مشکل فوق پابرجا بوده و گزارش نشان داده نشده و هیچ یک از متد‌های پرینت فراخوانی نمی‌شوند.
نظرات مطالب
EF Code First #14
پستها را خواندم، درست است؛ با این روش که شما فرمودید، میتوان رکوردهای جدید از قدیم را تشخیص داد(با استفاده از id) ولی موردی که باقی می‌ماند این است که سمت کلاینت ممکن است برخی از OrderLine‌ها ویرایش شوند و برخی نشوند و ما دقیقا نمیدانیم کدامها ویرایش شده اند و کدامها نشده اند، تا در سرور state آنها را بصورت  Unchanged    و یا Modified   قرار دهیم.  آیا روشی برای تشخیص این مورد وجود دارد؟ 
نظرات مطالب
آغاز به کار با Twitter Bootstrap در ASP.NET MVC
یک مشکلی که من با این کد بهش برخوردم این بود که اگر اسکریپتی به وابستگی به اسکریپت‌های دیگه داشته باشه ممکن هست دچار مشکل بشه
برای مثال جی کوئری و پلاگین هاش
به نظر میرسه ترتیب معرفی اسکریپت‌ها رو رعایت نمی‌کنه
نظرات مطالب
خودکار کردن تعاریف DbSetها در EF Code first
عکس عمل کنید. ابتدا تنظیمات، بعد موجودیت‌ها اضافه شوند.
ضمنا اگر احیانا گذارتان به انجمنی افتاد این «به مشکل برخوردم» رو باید توضیح بدید. باید خطای حاصل رو ذکر کنید (علاوه بر روشی که طی شده).