کار با فایلها در MVC 5 و EF 6
7.Visual Studio 2017 15.9 منتشر شد
These are the customer-reported issues addressed in 15.9.7:
- Crashes when expanding variables!.
- /DEBUG:FASTLINK + C7 + PCH crashes debugger.
- Native C++ application crashes because of stack corruption with VS 2017 15.9.2.
- Incorrect Release Mode code.
- Xamarin Unobserved Task Exception WebRequest.
- Link /SOURCELINK option seems to do nothing. This fixes Source Link for Managed C++ Debugging.
- Fixed an issue with corruption of AVX/MPX/AVX512 registers while Debugging.
- Update of Microsoft.VCLibs.140.00.UWPDestkop framework packages for C++ UWP DesktopBridge applications adding support for ARM64.
- Corrected incorrect version of VCToolsRedistVersion in Microsoft.VCToolsVersion.default.props.
- Corrected unsigned embedded dll for VC Redist installers.
- SSDT/Web Tools: We fixed an issue where SQL LocalDB was not installed on Polish, Turkish, and Czech locales.
- SSDT: We fixed an issue affecting SQL Server Analysis Services (Method not found exception when clicking on UI).
- SSDT: We fixed an accessibility issue which was causing the contents of a table not to be visible in the result window when using High-Contrast mode.
Security Advisory Notices
معرفی DNTBreadCrumb
routes.MapRoute( "category_route", // Route name "MyControllerName/{category}/{productname}", // URL with parameters new { controller = "MyControllerName", action = "MyActionName", category = UrlParameter.Optional, productname = UrlParameter.Optional, area = "" } );
Some months ago a feature landed in Xamarin.Forms that seemed to truly polarize the Xamarin.Forms community: support for styling applications using CSS. Some argued that it was an unnecessary introduction to "Web" technology to the native development experience, and others that it simply isn't the right solution to the problem. While I sympathize with the latter opinion and think there's plenty of room for some good debate on the right path forward, I count myself as part of a third camp: I think that CSS is a powerful (and frequently maligned) solution to the problem of styling native mobile applications.
وبلاگها و سایتهای ایرانی
امنیت
Visual Studio
ASP. Net
طراحی وب
PHP
- Aptana PHP 1.0 منتشر شد (اگر قبلا این IDE بسیار قابل توجه را دریافت کرده بودید فقط کافی است به منوی aptana و گزینه my aptana مراجعه کرده و از قسمت plugins ، این پلاگین 18 مگابایتی را دریافت کنید.)
اسکیوال سرور
سی شارپ
عمومی دات نت
ویندوز
متفرقه
- مزایای مهاجرت از ویژوال سورس سیف مایکرسافت به SVN
- افزونهای برای فایرفاکس جهت GUI prototyping (خیلی کار جالبی کرده ولی چرا به صورت یک افزونه؟)
در این قسمت قصد داریم از امکانات جدید اعتبار سنجی تعریف شده در فضای نام استاندارد System.ComponentModel.DataAnnotations استفاده نمائیم. از سیلورلایت سه به بعد امکان استفاده از این فضای نام به سادگی در برنامههای سیلورلایت میسر است (همچنین در برنامههای ASP.Net MVC)؛ اما برای کار با آن در WPF نیاز به تعدادی متد کمکی میباشد...
فهرست مطالب:
فصل 5- تعیین اعتبار ورودی کاربر و الگوی MVVM
- مقدمه
- معرفی برنامه فصل
- مدل برنامهی فصل
- ViewModel برنامه فصل
- View برنامه فصل
دریافت قسمت پنجم
دریافت مثال قسمت پنجم
تعدادی از منابع و مآخذ مورد استفاده در این سری:
2. Model View ViewModel
3. DataModel-View-ViewModel pattern
4. 5 Minute Overview of MVVM in Silverlight
5. A Field Guide to WPF Presentation Patterns
6. An attempt at simple MVVM with WPF
7. WPF: If Heineken did MVVM Frameworks Part 1 of n
8. Modal dialogs with MVVM and Silverlight 4
9. How do I do… With the Model-View-ViewModel pattern
10. Intro to WPF MVVM
11. Introduction to MVVM pattern in WPF
12. Learning WPF M-V-VM
13. Binding Combo Boxes in WPF with MVVM
14. Model-View-ViewModel Pattern
15. Unit Testable WCF Web Services in MVVM and Silverlight 4
16. MVVM Part 1: Overview
17. Which came first, the View or the Model?
18. Stackoverflow's questions tagged with MVVM
19. WPF: MVVM (Model View View-Model) Simplified
20. WPF and MVVM tutorial 01, Introduction
21. WPF patterns : MVC, MVP or MVVM or…?
22. Silverlight, MVVM and Validation Part III
23. DotNetKicks.com - Stories recently tagged with 'MVVM'
24. DotNetShoutout - Stories tagged with MVVM
25. MVVM Light Toolkit
26. MVVM screen casts
27. What’s new in MVVM Light V3
28. Using RelayCommands in Silverlight 3 and WPF
29. WPF Apps With The Model-View-ViewModel Design Pattern
30. WPF MVVM and Showing Dialogs
نکته : فقط در Vs.Net با نسخههای Ultimate و Premium میتونید از Code UI Test استفاده کنید که البته به دلیل اینکه در ایران پیدا کردن نسخههای دیگر Vs.Net به غیر از Ultimate سختتر است به طور قطع این محدودیت برای برنامه نویسان ما وجود نخواهد داشت. برای اینکه از نسخه Vs.Net خود اطمینان حاصل کنید از منوی Help گزینه About Microsoft Visual Studio رو انتخاب کنید. پنجره ای به شکل زیر مشاهده خواهید کرد که در آن مشخصات کامل Vs.Net ذکر شده است.
در این مرحله قصد داریم برای فرم زیر Unit Test طراحی کنیم. پروژه به صورت زیر است:
کاملا واضح است که در این فرم دو عدد به عنوان ورودی دریافت میشود و بعد از کلیک بر روی CalculateSum نتیجه در textbox سوم نمایش داده میشود. برای تست عملکرد صحیح فرم بالا ایتدا به Solution مورد نظر از منوی test Project یک Coded UI Test Project اضافه میکنیم. به دلیل اینکه این قبلا در این Solution پروژه تست از نوع Coded UI Test نبود بلافاصله یک پنجره نمایش داده میشود. مطمئن شوید گزینه اول انتخاب شده و بعد بر روی Ok کلیک کنید.(گزینه اول به معنی است که قصد داریم عملیات مورد نظر بر روی UI را رکورد کنیم و گزینه دوم به معنی است که قصد داریم از عملیات رکورد شده قبلی استفاده کنیم). یک کلاس به نام CodeUITest1 به همراه یک متد تست به نام CodedUITestMethod1 ساخته میشود. اولین چیزی که جلب توجه میکند این است که این کلاس به جای TestClassAttribute دارای نشان CodeUITestAttrbiute است. در گوشه سمت راست Vs.Net خود یک پنجره کوچک به نام UI Map Test Builder مانند شکل زیر خواهید دید.دکمه قرمز رنگ به نام Record Button است و عملیات تست را رکورد خواهد کرد. دکمه دایره ای به رنگ مشکی برای تعیین Assertion به کار میرود. و در نهایت گزینه آخر کدهای مورد نظر مراحل قبل را به صورت خودکار تولید خواهد کرد.
#روش کار
روش کار به این صورت است که ابتدا شما مراحل تست خود را شبیه سازی خواهید کرد و بعد از آن Test Builder مراحل تست شما را به صورت کامل به صورت کدهای قابل فهم تولید خواهد کرد. (دقیقا شبیه به ایجاد UnitTest به روش Arrange/Act/Assert است با این تفاوت که این مراحل توسط UI Map رکورد شده و نیازی به کد نویسی ندارد). در پایان باید یک Data Driven Coded UI Test طراحی کنید تا بتوانید از این مراحل رکورد استفاده نمایید.
#چگونگی شبیه سازی :
پروژه را اجرا نمایید. زمانی که فرم مورد نظر ظاهر شد بر روی گزینه Record در TestBuilder کلیک کنید. عملیات ذخیره سازی شروع شده است. در نتیجه به فرم مربوطه رفته و در Textbox اول مقدار 10 و در textbox دوم مقدار 5 را وارد نمایید. با کلیک بر روی دکمه CalculateSum مقدار 15 نمایش داده خواهد شد. از برنامه خارج شوید و بعد بر روی گزینه Generate Code در TestBuilder کلیک کنید با از کلیدهای ترکیبی Alt + G استفاده نمایید.(اگر در این مرحله، از برنامه خارج نشده باشید با خطا مواجه خواهید شد.) در پنجره نمایش داده شده یک نام به متد اختصاص دهید. عملیات تولید کد شروع خواهد شد. بعد کدی مشابه زیر را در متد مربوطه مشاهده خواهید کرد.
[TestMethod] public void CodedUITestMethod1() { this.UIMap.CalculateSum(); this.UIMap.txtSecondValueMustBe10(); }
public void CodedUITestMethod1 ()
{
#region Variable Declarations
WinEdit uITxtFirstNumberEdit = this.UIدوعددصحیحواردنماییدWindow.UITxtFirstNumberWindow.UITxtFirstNumberEdit;
WinEdit uITxtSecondNumberEdit = this.UIدوعددصحیحواردنماییدWindow.UITxtSecondNumberWindow.UITxtSecondNumberEdit;
WinButton uICalculateSumButton = this.UIدوعددصحیحواردنماییدWindow.UICalculateSumWindow.UICalculateSumButton;
#endregion
// Type '10' in 'txtFirstNumber' text box
uITxtFirstNumberEdit.Text = this.CalculateSumParams.UITxtFirstNumberEditText;
// Type '{Tab}' in 'txtFirstNumber' text box
Keyboard.SendKeys(uITxtFirstNumberEdit, this.CalculateSumParams.UITxtFirstNumberEditSendKeys, ModifierKeys.None);
// Type '10' in 'txtSecondNumber' text box
uITxtSecondNumberEdit.Text = this.CalculateSumParams.UITxtSecondNumberEditText;
// Click 'Calculate Sum' button
Mouse.Click(uICalculateSumButton, new Point(83, 12));
// Type '10' in 'txtFirstNumber' text box
uITxtFirstNumberEdit.Text = this.CalculateSumParams.UITxtFirstNumberEditText1;
// Type '{Tab}' in 'txtFirstNumber' text box
Keyboard.SendKeys(uITxtFirstNumberEdit, this.CalculateSumParams.UITxtFirstNumberEditSendKeys1, ModifierKeys.None);
// Type '10' in 'txtSecondNumber' text box
uITxtSecondNumberEdit.Text = this.CalculateSumParams.UITxtSecondNumberEditText1;
// Type '{Tab}' in 'txtSecondNumber' text box
Keyboard.SendKeys(uITxtSecondNumberEdit, this.CalculateSumParams.UITxtSecondNumberEditSendKeys, ModifierKeys.None);
// Click 'Calculate Sum' button
Mouse.Click(uICalculateSumButton, new Point(49, 11));
// Type '10' in 'txtFirstNumber' text box
uITxtFirstNumberEdit.Text = this.CalculateSumParams.UITxtFirstNumberEditText2;
// Type '{Tab}' in 'txtFirstNumber' text box
Keyboard.SendKeys(uITxtFirstNumberEdit, this.CalculateSumParams.UITxtFirstNumberEditSendKeys2, ModifierKeys.None);
// Type '5' in 'txtSecondNumber' text box
uITxtSecondNumberEdit.Text = this.CalculateSumParams.UITxtSecondNumberEditText2;
// Type '{Tab}' in 'txtSecondNumber' text box
Keyboard.SendKeys(uITxtSecondNumberEdit, this.CalculateSumParams.UITxtSecondNumberEditSendKeys1, ModifierKeys.None);
// Click 'Calculate Sum' button
Mouse.Click(uICalculateSumButton, new Point(74, 16));
}
چگونگی ایجاد Assertion
اگر به کد متد تست CodedUITestMethod1 در بالا دقت کنید یک متد به صورت this.UIMap.txtSecondValueMustBe10 فراخوانی شده است. این در واقع یک Assertion است که در هنگام عملیات رکورد ایجاد کردم و به این معنی است که مقدار TextBox دوم حتما باید 10 باشد. حال روش تولید Assertionها را بررسی خواهیم کرد.
بعد از شروع شدن مرحله رکورد اگر قصد دارید برای یک کنترل خاص Assert بنویسید، دکمه assertion (به رنگ مشکی و به صورت دایره است) را بر روی کنترل مورد نظر drag&drop کنید. یک border آبی برای کنترل مورد نظر ایجاد خواهد شد:
به محض اتمام عملیات drag&drop منوی زیر ظاهر خواهد شد:
از گزینه Add Assertion استفاده کنید و برای کنترل مورد نظر یک assert بنویسید. در شکل زیر یک assert برای textbox دوم نوشتم به صورتی که مقدار آن باید با 5 برابر باشد.از گزینه آخر برای نمایش پیغام مورد نظر خودتون در هنگامی که aseert با شکست مواجه میشود استفاده کنید.
کد تولید شده زیر برای عملیات assert بالا است:
public void txtSecondValueMustBe10() { #region Variable Declarations WinEdit uITxtSecondNumberEdit = this.UIدوعددصحیحواردنماییدWindow.UITxtSecondNumberWindow.UITxtSecondNumberEdit; #endregion // Verify that the 'ControlType' property of 'txtSecondNumber' text box equals '10' Assert.AreEqual(this.txtSecondValueMustBe10ExpectedValues.UITxtSecondNumberEditControlType, uITxtSecondNumberEdit.ControlType.ToString()); }
مرحله اول انجام شد. برای تست این مراحل باید یک Data DrivenTest بسازید که در پست بعدی به صورت کامل شرح داده خواهد شد.
نگاهی به SignalR Hubs
Hubs به نوعی یک فریم ورک سطح بالای RPC نیز محسوب میشوند (Remote Procedure Calls) و آنرا برای انتقال انواع و اقسام دادهها بین سرور و کلاینت و یا فراخوانی متدی در سمت کلاینت یا سرور، بسیار مناسب میسازد. برای مثال اگر قرار باشد با persistent connection به صورت مستقیم کار کنیم، نیاز است تا بسیاری از مسایل serialization و deserialization اطلاعات را خودمان پیاده سازی و اعمال نمائیم.
قرار دادهای پیش فرض Hubs
- متدهای public کلاسهای Hubs از طریق دنیای خارج قابل فراخوانی هستند.
- ارسال اطلاعات به کلاینتها از طریق فراخوانی متدهای سمت کلاینت انجام خواهد شد. (نحوه تعریف این متدها در سمت سرور بر اساس قابلیتهای dynamic اضافه شده به دات نت 4 است که در ادامه در مورد آن بیشتر بحث خواهد شد)
مراحل اولیه نوشتن یک Hub
الف) یک کلاس Hub را تهیه کنید. این کلاس، از کلاس پایه Hub تعریف شده در فضای نام Microsoft.AspNet.SignalR باید مشتق شود. همچنین این کلاس میتواند توسط ویژگی خاصی به نام HubName نیز مزین گردد تا در حین برپایی اولیه سرویس، از طریق زیرساختهای SignalR به نامی دیگر (یک alias یا نام مستعار خاص) قابل شناسایی باشد. متدهای یک هاب میتوانند نوعهای ساده یا پیچیدهای را بازگشت دهند و همه چیز در اینجا نهایتا به فرمت JSON رد و بدل خواهد شد (فرمت پیش فرض که در پشت صحنه از کتابخانه معروف JSON.NET استفاده میکند؛ این کتابخانه سورس باز به دلیل کیفیت بالای آن، از زمان ارائه MVC4 به عنوان جزئی از مجموعه کارهای مایکروسافت قرار گرفته است).
ب) مسیریابی و Routing را تعریف و اصلاح نمائید.
و ... از نتیجه استفاده کنید.
تهیه اولین برنامه با SignalR
ابتدا یک پروژه خالی ASP.NET را آغاز کنید (مهم نیست MVC باشد یا WebForms). برای سادگی بیشتر، در اینجا یک ASP.NET Empty Web application درنظر گرفته شده است. در ادامه قصد داریم یک برنامه Chat را تهیه کنیم؛ از این جهت که توسط یک برنامه Chat بسیاری از مفاهیم مرتبط با SignalR را میتوان در عمل توضیح داد.
اگر از VS 2012 استفاده میکنید، گزینه SignalR Hub class جزئی از آیتمهای جدید قابل افزودن به پروژه است (منوی پروژه، گزینه new item آن) و پس از انتخاب این قالب خاص، تمامی ارجاعات لازم نیز به صورت خودکار به پروژه جاری اضافه خواهند شد.
و اگر از VS 2010 استفاده میکنید، نیاز است از طریق NuGet ارجاعات لازم را به پروژه خود اضافه نمائید:
PM> Install-Package Microsoft.AspNet.SignalR
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; namespace SignalR02 { [HubName("chat")] public class ChatHub : Hub { public void SendMessage(string message) { Clients.All.hello(message); } } }
کلاس پایه Hub یک سری متد و خاصیت را در اختیار کلاسهای مشتق شده از آن قرار میدهد. سادهترین راه برای آشنایی با این متدها و خواص مهیا، کلیک راست بر روی نام کلاس پایه Hub و انتخاب گزینه Go to definition است.
برای نمونه در کلاس ChatHub فوق، از خاصیت Clients برای دسترسی به تمامی آنها و سپس فراخوانی متد dynamic ایی به نام hello که هنوز وجود خارجی ندارد، استفاده شده است.
اهمیتی ندارد که این کلاس در اسمبلی اصلی برنامه وب قرار گیرد یا مثلا در یک class library به نام Services. همینقدر که از کلاس Hub مشتق شود به صورت خودکار در ابتدای برنامه اسکن گردیده و یافت خواهد شد.
مرحله بعد، افزودن فایل global.asax به برنامه است. زیرا برای کار با SignalR نیاز است تنظیمات Routing و مسیریابی خاص آنرا اضافه نمائیم. پس از افرودن فایل global.asax، به فایل Global.asax.cs مراجعه کرده و در متد Application_Start آن تغییرات ذیل را اعمال نمائید:
using System; using System.Web; using System.Web.Routing; namespace SignalR02 { public class Global : HttpApplication { protected void Application_Start(object sender, EventArgs e) { // Register the default hubs route: ~/signalr RouteTable.Routes.MapHubs(); } } }
یک نکته مهم
اگر از ASP.NET MVC استفاده میکنید، این تنظیم مسیریابی باید پیش از تعاریف پیش فرض موجود قرار گیرد. در غیراینصورت مسیریابیهای SignalR کار نخواهند کرد.
اکنون برای آزمایش برنامه، برنامه را اجرا کرده و مسیر ذیل را فراخوانی کنید:
http://localhost/signalr/hubs
proxies.chat = this.createHubProxy('chat');
تا اینجا ما موفق شدیم اولین Hub خود را تشکیل دهیم.
بررسی پروتکل Hub
اکنون که اولین Hub خود را ایجاد کردهایم، بد نیست اندکی با زیر ساخت آن نیز آشنا شویم.
مطابق مسیریابی تعریف شده در Application_Start، مسیر ابتدایی دسترسی به SignalR با افزودن اسلش SignalR به انتهای مسیر ریشه سایت بدست میآید و اگر به این آدرس یک اسلش hubs را نیز اضافه کنیم، فایل js metadata مرتبط را نیز میتوان دریافت و مشاهده کرد.
زمانیکه یک کلاینت قصد اتصال به یک Hub را دارد، دو مرحله رخ خواهد داد:
الف) negotiate: در این حالت امکانات قابل پشتیبانی از طرف سرور مورد پرسش قرار میگیرند و سپس بهترین حالت انتقال، انتخاب میگردد. این انتخابها به ترتیب از چپ به راست خواهند بود:
Web socket -> SSE -> Forever frame -> long polling
به این معنا که اگر برای مثال امکانات Web sockets مهیا بود، در همینجا کار انتخاب نحوه انتقال اطلاعات خاتمه یافته و Web sockets انتخاب میشود.
تمام این مراحل نیز خودکار است و نیازی نیست تا برای تنظیمات آن کار خاصی صورت گیرد. البته در سمت کلاینت، امکان انتخاب یکی از موارد یاد شده به صورت صریح نیز وجود دارد.
ب) connect: اتصالی ماندگار برقرار میگردد.
در پروتکل Hub تمام اطلاعات JSON encoded هستند و یک سری مخففهایی را در این بین نیز ممکن است مشاهده نمائید که معنای آنها به شرح زیر است:
C: cursor M: Messages H: Hub name M: Method name A: Method args T: Time out D: Disconnect
روشهای مختلف ارسال اطلاعات به کلاینتها
به چندین روش میتوان اطلاعاتی را به کلاینتها ارسال کرد:
1) استفاده از خاصیت Clients موجود در کلاس Hub
2) استفاده از خواص و متدهای dynamic
در این حالت اطلاعات متد dynamic و پارامترهای آن به صورت JSON encoded به کلاینت ارسال میشوند (به همین جهت اهمیتی ندارند که در سرور وجود خارجی دارند یا خیر و به صورت dynamic تعریف شدهاند).
using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; namespace SignalR02 { [HubName("chat")] public class ChatHub : Hub { public void SendMessage(string message) { var msg = string.Format("{0}:{1}", Context.ConnectionId, message); Clients.All.hello(msg); } } }
حالت Clients.All به معنای ارسال پیامی به تمام کلاینتهای متصل به هاب ما هستند.
3) روشهای دیگر، استفاده از خاصیت dynamic دیگری به نام Caller است که میتوان بر روی آن متد دلخواهی را تعریف و فراخوانی کرد.
//این دو عبارت هر دو یکی هستند Clients.Caller.hello(msg); Clients.Client(Context.ConnectionId).hello(msg);
در اینجا پیامی صرفا به فراخوان جاری سرویس ارسال میگردد.
4) استفاده از خاصیت dynamic ایی به نام Clients.Others
Clients.Others.hello(msg);
5) استفاده از متد Clients.AllExcept
این متد میتواند آرایهای از ConnectionIdهایی را بپذیرد که قرار نیست پیام ارسالی ما را دریافت کنند.
6) ارسال اطلاعات به گروهها
تعداد مشخصی از ConnectionIdها یک گروه را تشکیل میدهند؛ مثلا اعضای یک chat room.
public void JoinRoom(string room) { this.Groups.Add(Context.ConnectionId, room); } public void SendMessageToRoom(string room, string msg) { this.Clients.Group(room).hello(msg); }
خاصیت Group در کلاس پایه Hub تعریف شده است.
نکته مهمی را که در اینجا باید درنظر داشت این است که اطلاعات گروهها به صورت دائمی در سرور ذخیره نمیشوند. برای مثال اگر سرور ری استارت شود، این اطلاعات از دست خواهند رفت.
آشنایی با مراحل طول عمر یک Hub
اگر به تعاریف کلاس پایه Hub دقت کنیم:
public abstract class Hub : IHub, IDisposable { protected Hub(); public HubConnectionContext Clients { get; set; } public HubCallerContext Context { get; set; } public IGroupManager Groups { get; set; } public void Dispose(); protected virtual void Dispose(bool disposing); public virtual Task OnConnected(); public virtual Task OnDisconnected(); public virtual Task OnReconnected(); }
تعدادی از این متدها را میتوان جهت مقاصد logging برنامه مورد استفاده قرار داد و یا در متد OnDisconnected اگر اطلاعاتی را در بانک اطلاعاتی ذخیره کردهایم، بر این اساس میتوان وضعیت نهایی را تغییر داد.
ارسال اطلاعات از یک Hub به Hub دیگر در برنامه
فرض کنید یک Hub دوم را به نام MinitorHub به برنامه اضافه کردهاید. اکنون قصد داریم از داخل ChatHub فوق، اطلاعاتی را به آن ارسال کنیم. روش کار به نحو زیر است:
public override System.Threading.Tasks.Task OnDisconnected() { sendMonitorData("OnDisconnected", Context.ConnectionId); return base.OnDisconnected(); } private void sendMonitorData(string type, string connection) { var ctx = GlobalHost.ConnectionManager.GetHubContext<MonitorHub>(); ctx.Clients.All.newEvenet(type, connection); }
مورد استفاده دیگر این روش، ارسال اطلاعات به کلاینتها از طریق کدهای یک برنامه تحت وب است (که در همان پروژه هاب واقع شده است). برای مثال در یک اکشن متد یا یک روال رویدادگردان کلیک نیز میتوان از GlobalHost.ConnectionManager استفاده کرد.