+ شما در ASP.Net همیشه میتونید نحوه کامپایل شدن را در وب کانفیگ هم تعیین کنید. به این صورت:
compilation defaultLanguage="c#" debug="false"
برای مطالعه بیشتر
http://aspnetresources.com/articles/debug_code_in_production.aspx
و یا استفاده از روش زیر که در آن retail را باید true کنید:
http://msdn.microsoft.com/en-us/library/ms228298(VS.80).aspx
مشکلات استفاده از bool در طراحی API
EF Code First #12
در متد Program.Main هم میتونید تنظیمات اولیه ObjectFactory رو قرار بدید (شبیه به Application_Start برنامههای وب).
بنابراین در برنامههای وب «context/session per http request» داریم؛ در برنامههای ویندوزی «context per operation or per form». یعنی میتونید بسته به معماری برنامه ویندوزی خود، context را در سطح یک فرم تعریف کنید و مدیریت؛ و یا در سطح یک عملیات کوتاه مانند یک کلیک. تمام مباحث ObjectFactory.GetInstance، uow.SaveChanges و یا Dispose آن هم دستی است و زیر ساختی برای مدیریت خودکار آنها همانند برنامههای مثلا ASP.NET MVC وجود ندارد. حداکثر اینکه یک سری base class را شبیه به مثال Web forms زده شده تهیه کنید، تا میزان کدهای تکراری را کاهش بدید.
SignalR
Async library for .NET to help build real-time, multi-user interactive web applications.
The real-time web is a set of technologies and practices that enable users to receive information as soon as it is published by its authors, rather than requiring that they or their software check a source periodically for updates.
- تکنولوژی جدید WebSocket (^) که خوشبختانه پشتیبانی کاملی از اون در دات نت 4.5 (چهار نقطه پنج! نه چهار و نیم!) وجود داره. اما تمام مرورگرها و تمام وب سرورها از این تکنولوژی پشتیبانی نمیکنند و تنها برخی نسخههای جدید قابلیت استفاده از آخرین ورژن WebSocket رو دارند که میشه به کروم 16 به بالا و فایرفاکس 11 به بالا و اینترنت اکسپلورر 10 اشاره کرد (برای استفاده از این تکنولوژی در ویندوز نیاز به IIS 8.0 است که متاسفانه فقط در ویندوز 8.0 موجوده):
Chrome 16, Firefox 11 and Internet Explorer 10 are currently the only browsers supporting the latest specification (RFC 6455). - یه روش دیگه Server-sent Events نام داره که دادههای جدید رو به فرم رویدادهای DOM به سمت کلاینت میفرسته(^).
- روش دیگهای که موجوده به Forever Frame معروفه که در این روش یک iframe مخفی درون کد html مسئول تبادل دادههاست. این iframe مخفی بهصورت یک بلاک Chunked (^) به سمت کلاینت فرستاده میشه. این iframe که مسئول رندر دادههای جدید در سمت کلاینت هست ارتباط خودش رو با سرور تا ابد! (برای همین بهش forever میگن) حفظ میکنه. هر وقت رویدادی سمت سرور رخ میده با استفاده از این روش دادهها بهصورت تگهای script به این فریم مخفی فرستاده میشوند و چون مرورگرها محتوای html رو به صورت افزایشی (incrementally) رندر میکنن بنابراین این اسکریپتها بهترتیب زمان دریافت اجرا میشوند. (البته ظاهرا عبارت forever frame در صنعت عکاسی! معروفتره بنابراین در جستجو در زمینه این روش ممکنه کمی مشکل داشته باشین) (^).
- روش آخر که در کتابخونه SignalR ازش استفاده میشه long-polling نام داره. در روش polling معمولی پس از ارسال درخواست توسط کلاینت، سرور بلافاصله نتیجه حاصله رو به سمت کلاینت میفرسته و ارتباط قطع میشه. بنابراین برای دادههای جدید درخواست جدیدی باید به سمت سرور فرستاده بشه که تکرار این روش باعث افزایش شدید بار بر روی سرور و کاهش کارآمدی اون میشه. اما در روش long-polling پس از برقراری ارتباط کلاینت با سرور این ارتباط تا مدت زمان معینی (که توسط یه مقدار تایم اوت مشخص میشه و مقدار پیشفرضش 2 دقیقه است) برقرار میمونه. بنابراین کلاینت میتونه بدون ایجاد مشکلی در کارایی، دادههای جدید رو از سرور دریافت کنه. به این روش در برنامهنویسی وب اصطلاحا برنامهنویسی کامت (Comet Programming) میگن (^ ^).
- کلاس سطح پایین PersistentConnection
- کلاس سطح بالای Hub
PM> Install-Package SignalR.Sample
PM> Install-Package SignalR
Microsoft.Web.Infrastructure Newtonsoft.Json SignalR SignalR.Hosting.AspNet SignalR.Hosting.Common
jquery-1.6.4.js jquery.signalR-0.5.1.js
using SignalR.Hubs; namespace SimpleChatWithSignalR { public class SimpleChat : Hub { public void SendMessage(string message) { Clients.reciveMessage(message); } } }
<input type="text" id="msg" /> <input type="button" value="Send" id="send" /><br /> <textarea id='messages' readonly="true" style="height: 200px; width: 200px;"></textarea> <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script> <script src="Scripts/jquery.signalR-0.5.1.min.js" type="text/javascript"></script> <script src="signalr/hubs" type="text/javascript"></script> <script type="text/javascript"> var chat = $.connection.simpleChat; chat.reciveMessage = function (msg) { $('#messages').val($('#messages').val() + "-" + msg + "\r\n"); }; $.connection.hub.start(); $('#send').click(function () { chat.sendMessage($('#msg').val()); }); </script>
<script src="signalr/hubs" type="text/javascript"></script>
به روز رسانی
در دورهای به نام SignalR در سایت، به روز شدهای این مباحث را میتوانید مطالعه کنید.
کدهای متورم (Bloaters)
- استفاده از متغیرهای اولیه بجای ساختارهای کوچک برای کارهای اولیه مانند Currency, DateTime, PhoneNumber
- استفاده از constantها برای کد کردن اطلاعات مانند USER_ADMIN_ROLE = 1
- استفاده از constantهای رشتهای به عنوان نام فیلدها در آرایههای داده
بد استفاده کنندگان از شیء گرایی (Object orientation abusers)
جلوگیری کنندگان از تغییر(Change preventers)
کدهای غیر ضروری (Dispensables)
کدهایی بیش از اندازه وابسته به هم (Couplers)
PM> Install-Package DNTFrameworkCore.Web
PM> Install-Package DNTFrameworkCore.Web.EntityFramework
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build() .MigrateDbContext<ProjectDbContext>() .Run(); } //... }
[Route("api/[controller]")] public class BlogsController : CrudController<IBlogService, int, BlogModel> { public BlogsController(IBlogService service) : base(service) { } protected override string CreatePermissionName => PermissionNames.Blogs_Create; protected override string EditPermissionName => PermissionNames.Blogs_Edit; protected override string ViewPermissionName => PermissionNames.Blogs_View; protected override string DeletePermissionName => PermissionNames.Blogs_Delete; }
var data = JSON.parse(responseBody) pm.environment.set("token", data.token);
حال برای ارسال درخواستهای HTTP به BlogsController به شکل زیر عمل کنید:
query={"page":1,"pageSize":100,"filter":{"logic":"and","filters":[{"field":"title","value":"Blog1","operator":"startswith"}]}}
{{endpoint}}/blogs/10
[Route("api/[controller]")] public class UsersController : CrudController<IUserService, long, UserReadModel, UserModel> { private readonly ILookupService _lookupService; public UsersController(IUserService service, ILookupService lookupService) : base(service) { _lookupService = lookupService ?? throw new ArgumentNullException(nameof(lookupService)); } protected override string CreatePermissionName => PermissionNames.Users_Create; protected override string EditPermissionName => PermissionNames.Users_Edit; protected override string ViewPermissionName => PermissionNames.Users_View; protected override string DeletePermissionName => PermissionNames.Users_Delete; [HttpGet("[action]")] [PermissionAuthorize(PermissionNames.Users_Create, PermissionNames.Users_Edit)] public async Task<IActionResult> RoleList() { var result = await _lookupService.ReadRolesAsync(); return Ok(result); } }
باتوجه به اینکه UserRole به عنوان یکی از وابستگیهای موجودیت User محسوب میشود، در پاسخ درخواست GET مرتبط با کاربری با شناسه 2، roles آن، لیستی از UserRoleModel هستند که به عنوان یک DetailModel طراحی شده است. به عنوان مثال برای حذف اتصال یک گروه کاربری باید درخواست PUT را به شکل زیر ارسال کنید:
اینبار اگر برای درخواست GET کاربر با شناسه 2 اقدام کنیم، به خروجی زیر خواهم رسید:
{ "userName": "rabbal", "displayName": "غلامرضا ربال", "password": null, "isActive": false, "roles": [], "permissions": [], "ignoredPermissions": [], "rowVersion": "AAAAAAACGxI=", "id": 2 }
برای بررسی بیشتر، پیشنهاد میکنم پروژه DNTFrameworkCore.TestAPI موجود در مخزن این زیرساخت را بازبینی کنید.
پس از فشردن دکمه Add کمی صبور باشید تا صفحه بارگذاری شود و تصویر زیر برای شما نمایش داده شود (دادههای نمایش داده شده آزمایشی و تصادفی هستند و با بازآوری صفحه تغییر میکنند):
همانطور که مشاهده میکنید دو دکمه در بالای این نمودار نمایش داده شده است (در قسمت تنظیمات web part هم میتوانید ارجاعهای لازم به این لینکها را بیابید ) :
Data & Appearance برای مدیریت منبع دادههای نمودار و نحوه نمایش دادهها که دو لینک اصلی در آن وجود دارد :
Advanced Propertes برای مدیریت قسمتهای دیگر از قبیل جزییات رنگ بندی و زمینه و ...
همانطور که در شکل زیر مشاهده میکنید میتوانید مشخص کنید که دادههای محورهای نمودار از کدام ستونها داده را بگیرند و در صورت نیاز به عملیات گروه بندی میتوانید آن را اعمال کنید :
در دیگر قسمتهای این فرم میتوانید تنظیمات دیگری را انجام دهید برای مثال در قسمت Other Fields میتوانید برای آیتمهای روی نمودار یک لینک یا Tooltip تعریف کنید .
پس از زدن دکمه Finish خروجی زیر را خواهید دید :
حال میتوانید از قسمت Customize Your Chart به ویرایش نحوه نمایش دادهها بپردازید
همانطور که مشاهده میکنید در این قسمت میتوانید نوع نمودار را بسته به نیاز خود انتخاب نمایید ، ویژکیهای نمایشی آن را تغییر داده و برای نمودار خود ویژکیهای 3 بعدی تنظیم کنید .
(برای نمایش بهتر خاصیت group by را از نمودار حذف کردم ) . نوع نمایش را مانند زیر تغییر میدهم :
در این قسمت Theme نمایشی نمودار و نوع نمایش ستونها و درصد transparency بودن ستون را بعلاوه طول و عرض اندازه نمودار و نوع خروجی نمایش داده شده در صفحه میتوانید تنظیم کنید . روی Next کلیک میکنم تا وارد دیگر تنظیمات شود از جمله عنوان نمودار و راهنمای آن :
در قسمت بالا تنظیمات عنوان برای نمودار قابل اجرا میباشد و در قسمت زیرین ، توضیحات و اختصارات راهنمای نمودار قابل تنظیم است . در این قسمت حتی میتوانید راهنما را داخل خود نمودار انداخته (Dock to chart Area ) و موقعیت آن را مشخص کنید . کار تقریبا تمام شد . روی Finish کلیک کنید .
حال با رجوع به قسمت Advanced Propertes میتوانید روی ظاهر این نمودار بیشتر کار کنید . این یک نمونه ساده از خروجی کار با این قسمت است :