اشتراکها
اشتراکها
Json.NET 6.0 Release 1 منتشر شد
نظرات مطالب
طراحی پایگاه داده چند زبانه
استفاده از یک فیلد language در هر تیبل باعث میشود شما برای یک موجودیت کالا مثلا در سه زبان مختلف 3 رکورد درج کنید که در ارتباط این کالا با دیگر جداول دچار مشکل خواهید شد
مطالب
SQL Instance
ممکن است کاربر بر روی سیستم خود نسخههای مختلفی از SQL Server را نصب کرده باشد. برای مثال SQL Express, SQL 2005, SQL 2008. و یا نسخه ای خاص (مثلا 2012) را چند بار روی سیستم خود نصب کرده باشد. SQL برای تفکیک این نسخهها و نصبها از مفهومی با عنوان Instance استفاده میکند. یعنی به هر نسخه نصب شده نامی یکتا میدهد تا بتوان به تفکیک به آنها دسترسی داشت.
برای اتصال به این نسخهها باید در بخش آدرس سرور، از ترکیب نام سیستم و نام Instance به این شکل استفاده کرد: SystemName\Instance
بعضی مواقع لازم است که لیست Instanceهای نصب شده روی سیستم کاربر را به دست آوریم. ADO.NET کلاسی به همین منظور تعبیه کرده که شبکه را جستجو کرده و SQL Instanceهای مختلف را که قابل دسترسی هستند را برای شما لیست میکند. استفاده از این کلاس بسیار ساده است:
البته با توجه به اینکه شبکه را جستجو میکند در نرم افزار شما وقفه خواهد انداخت. خوب اگه بخواهیم Instanceهای نصب شده روی سیستم کاربر را پیدا کنیم چی؟ سادهترین و سریعترین راه استفاده از رجیستری سیستم است. نام Instanceها در رجیستری ویندوز در آدرس زیر قابل دسترسی است:
برای استفاده از این کلید در c# میتوان از کد زیر کمک بگیرید:
فقط دو نکته قابل توجه است. برنامه باید در Any CPU کامپایل شود تا در سیستمهای 64 بیتی بتوانید به محل درست رجیستری دسترسی پیدا کنید. چون نرم افزارهای 32 بیت در ویندوز 64 بیت در سیستم wow64 اجرا میشود که دسترسی به رجیستری آن در آدرس wow64 هر قسمت رجیستری است. بنابراین کد فوق در حالت Any CPU و غیر فعال بودن Prefer 32-bit قسمت Build در Properties برنامه به درستی اجرا میشود.
نکته: Default Instance در SQL مقدار MSSQLSERVER میباشد.
برای اتصال به این نسخهها باید در بخش آدرس سرور، از ترکیب نام سیستم و نام Instance به این شکل استفاده کرد: SystemName\Instance
بعضی مواقع لازم است که لیست Instanceهای نصب شده روی سیستم کاربر را به دست آوریم. ADO.NET کلاسی به همین منظور تعبیه کرده که شبکه را جستجو کرده و SQL Instanceهای مختلف را که قابل دسترسی هستند را برای شما لیست میکند. استفاده از این کلاس بسیار ساده است:
using System.Data.Sql; class Program { static void Main() { // Retrieve the enumerator instance and then the data. SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance; System.Data.DataTable table = instance.GetDataSources(); // Display the contents of the table. DisplayData(table); Console.WriteLine("Press any key to continue."); Console.ReadKey(); } private static void DisplayData(System.Data.DataTable table) { foreach (System.Data.DataRow row in table.Rows) { foreach (System.Data.DataColumn col in table.Columns) { Console.WriteLine("{0} = {1}", col.ColumnName, row[col]); } Console.WriteLine("============================"); } } }
البته با توجه به اینکه شبکه را جستجو میکند در نرم افزار شما وقفه خواهد انداخت. خوب اگه بخواهیم Instanceهای نصب شده روی سیستم کاربر را پیدا کنیم چی؟ سادهترین و سریعترین راه استفاده از رجیستری سیستم است. نام Instanceها در رجیستری ویندوز در آدرس زیر قابل دسترسی است:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names
برای استفاده از این کلید در c# میتوان از کد زیر کمک بگیرید:
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names"); foreach (string sk in key.GetSubKeyNames()) { var rkey = key.OpenSubKey(sk); foreach (string s in rkey.GetValueNames()) { MessageBox.Show("Sql instance name:" + s); } }
نکته: Default Instance در SQL مقدار MSSQLSERVER میباشد.
نظرات اشتراکها
قلم (فونت) فارسی صمیم
اعداد انگلیسی، خوب، انگلیسی نمایش داده میشوند. برای نمایش فارسی اعداد، خودتان باید این تغییر را دستی اعمال کنید:
public static string ToPersianNumbers(this string data) { if (string.IsNullOrWhiteSpace(data)) return string.Empty; return data.Replace("0", "۰") .Replace("1", "۱") .Replace("2", "۲") .Replace("3", "۳") .Replace("4", "۴") .Replace("5", "۵") .Replace("6", "۶") .Replace("7", "۷") .Replace("8", "۸") .Replace("9", "۹") .Replace(".", ","); }
در قسمتهای قبلی (^ و ^ و ^) با Text Template در Visual Studio آشنا شدید. این قسمت برای تکمیل بحث در مورد ابزاری که Microsoft از آن در برنامههای خود از جمله Visual Studio جهت تولید کدهای اتوماتیک استفاده مینماید، صحبت خواهیم کرد.
قبل از آن بد نیست که بدانید چرا این ابزار T4 نام گرفته !
T4 مخفف Text Template Transformation Toolkit میباشد (TTTT). شکل زیر مراحل اجرای یک کد Text Template را توسط T4 نشان میدهد:
برای آزمایش، یک فایل متنی کنار فایل TextTransform.exe با نام Text2.tt ایجاد نمایید و کد زیر را در داخل آن بنویسید:
این مثال بعد از اجرا، لیست تمام Process های جاری سیستم را به همراه Id آنها، چاپ مینماید.
برای تولید فایل خروجی، دستور زیر را در cmd.exe اجرا کنید :
نکته: اگر User شما به این پوشه دسترسی ندارد و کاربر Admin نیستید احتمالا به مشکل بر میخورد. میتوانید فایل TextTransform.exe را در مکان دیگری قرار دهید و دستور را از آن محل اجرا کنید و یا برای پوشهی مذکور دسترسی ایجاد نمایید.
اگر میخواهید بیشتر در مورد معماری T4 بدانید بهتر است مقاله زیر را مطالعه کنید:
قبل از آن بد نیست که بدانید چرا این ابزار T4 نام گرفته !
T4 مخفف Text Template Transformation Toolkit میباشد (TTTT). شکل زیر مراحل اجرای یک کد Text Template را توسط T4 نشان میدهد:
Program Files (x86)\Common Files\microsoft shared\TextTemplating\10.0
برای اطلاع از نحوه کار با TextTransform.exe خارج از محیط Visual Studio بهتر است دستور زیر را در cmd.exe اجرا کنید تا راهنمای استفاده و پارامترهای اختیاری آن را مشاهده نمایید:
TextTransform.exe –h
برای آزمایش، یک فایل متنی کنار فایل TextTransform.exe با نام Text2.tt ایجاد نمایید و کد زیر را در داخل آن بنویسید:
<#@ template debug="true" hostspecific="false" language="C#" #> <#@ output extension=".txt" #> <#@ import namespace="System.Diagnostics" #> Report In : <#= DateTime.Now #> <# Process[] Procs = Process.GetProcesses(); for (int i = 0; i < Procs.Length; i++) { string Pstr = Procs[i].ProcessName + " -|- " + Procs[i].Id + Environment.NewLine ; #><#= Pstr #><# } #>
برای تولید فایل خروجی، دستور زیر را در cmd.exe اجرا کنید :
TextTransform.exe -out Report1.txt Text2.tt
توجه کنید که فایل Text2.tt را کنار فایل TextTransform.exe قرار دهید و بعد از اجرای دستور بالا، باید خروجی در فایل Text2.tt در همان مسیر ایجاد گردد.نکته: اگر User شما به این پوشه دسترسی ندارد و کاربر Admin نیستید احتمالا به مشکل بر میخورد. میتوانید فایل TextTransform.exe را در مکان دیگری قرار دهید و دستور را از آن محل اجرا کنید و یا برای پوشهی مذکور دسترسی ایجاد نمایید.
اگر میخواهید بیشتر در مورد معماری T4 بدانید بهتر است مقاله زیر را مطالعه کنید:
http://www.olegsych.com/2008/05/t4-architecture/
نکته دیگر این که برای Visual Studio، ابزارهایی جهت بهبود کار با Text Templateها وجود دارند که با جستجوی T4 Editor، نمونههایی از آنها را خواهید یافت. tangible T4 Editor نمونه ای از این Pluginها میباشد که به Visual Studio افزوده میگردد و یا یک پروژه Open Source هم برای آشنایی بسیار بیشتر با T4 در t4toolbox.codeplex.com وجود دارد که میتوانید مشاهده کنید.سال نو مبارک! به امید روزهایی شاد، سلامت و پر برکت.
پیرو مطلب قلمهایی حاوی آیکون که خصوصا در برنامههای مترو بیشتر مرسوم شدهاند، شاید بد نباشد کار برنامه Character Map ویندوز را با WPF شبیه سازی کنیم.
ابتدا Model و ViewModel این برنامه را درنظر بگیرید:
توضیحات:
یک سری قابلیت جالب در WPF برای استخراج اطلاعات قلمها وجود دارند که در فضای نام System.Windows.Media اسمبلی PresentationCore.dll قرار گرفتهاند. برای نمونه پس از وهله سازی FontFamily بر اساس یک قلم مدفون شده در برنامه، امکان استخراج تعداد گلیفهای موجود در این قلم وجود دارد که نحوه انجام آنرا در متد fillDataSource ملاحظه میکنید.
این اطلاعات استخراج شده و لیست Symbols برنامه را تشکیل میدهند. در نهایت برای نمایش این اطلاعات، از ترکیب ItemsControl و UniformGrid استفاده خواهیم کرد:
دریافت مثال این مطلب
CrMap.zip
پیرو مطلب قلمهایی حاوی آیکون که خصوصا در برنامههای مترو بیشتر مرسوم شدهاند، شاید بد نباشد کار برنامه Character Map ویندوز را با WPF شبیه سازی کنیم.
ابتدا Model و ViewModel این برنامه را درنظر بگیرید:
namespace CrMap.Models { public class Symbol { public char Character { set; get; } public string CharacterCode { set; get; } } }
using System; using System.Collections.Generic; using System.Windows.Media; using CrMap.Models; namespace CrMap.ViewModels { public class CrMapViewModel { public IList<Symbol> Symbols { set; get; } public int GridRows { set; get; } public int GridCols { set; get; } public CrMapViewModel() { fillDataSource(); } private void fillDataSource() { Symbols = new List<Symbol>(); GridCols = 15; var fontFamily = new FontFamily(new Uri("pack://application:,,,/"), "/Fonts/#whhglyphs"); GlyphTypeface glyph = null; foreach (var typeface in fontFamily.GetTypefaces()) { if (typeface.TryGetGlyphTypeface(out glyph) && (glyph != null)) break; } if (glyph == null) throw new InvalidOperationException("Couldn't find a GlyphTypeface."); GridRows = (glyph.CharacterToGlyphMap.Count / GridCols) + 1; foreach (var item in glyph.CharacterToGlyphMap) { var index = item.Key; Symbols.Add(new Symbol { Character = Convert.ToChar(index), CharacterCode = string.Format("&#x{0:X}", index) }); } } } }
یک سری قابلیت جالب در WPF برای استخراج اطلاعات قلمها وجود دارند که در فضای نام System.Windows.Media اسمبلی PresentationCore.dll قرار گرفتهاند. برای نمونه پس از وهله سازی FontFamily بر اساس یک قلم مدفون شده در برنامه، امکان استخراج تعداد گلیفهای موجود در این قلم وجود دارد که نحوه انجام آنرا در متد fillDataSource ملاحظه میکنید.
این اطلاعات استخراج شده و لیست Symbols برنامه را تشکیل میدهند. در نهایت برای نمایش این اطلاعات، از ترکیب ItemsControl و UniformGrid استفاده خواهیم کرد:
<Window x:Class="CrMap.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:CrMap.ViewModels" Title="MainWindow" WindowStartupLocation="CenterScreen" WindowState="Maximized" Height="350" Width="525"> <Window.Resources> <vm:CrMapViewModel x:Key="vmCrMapViewModel" /> </Window.Resources> <ScrollViewer VerticalScrollBarVisibility="Visible"> <ItemsControl DataContext="{StaticResource vmCrMapViewModel}" ItemsSource="{Binding Symbols}" Name="MainItemsControl" VerticalAlignment="Top" HorizontalAlignment="Center" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="4"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <UniformGrid HorizontalAlignment="Center" VerticalAlignment="Center" Columns="{Binding GridCols}" Rows="{Binding GridRows}"> </UniformGrid> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <ContentControl> <Border BorderBrush="SlateGray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="1" CornerRadius="3" Margin="3"> <StackPanel Margin="3" Orientation="Vertical"> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Fonts/#whhglyphs" Foreground="DarkRed" FontSize="17" Text="{Binding Character}" /> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding CharacterCode}" /> </StackPanel> </Border> </ContentControl> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </ScrollViewer> </Window>
دریافت مثال این مطلب
CrMap.zip
قبل شروع این قسمت بد نیست با یک سری از وبلاگهای اعضای تیم Oslo آشنا شویم:
در ادامهی مثال قسمت قبل، اکنون میخواهیم entity جدیدی به نام Project را به مدل اضافه کنیم:
//mschema to define a Project type
type Project
{
ProjectID : Integer64 = AutoNumber();
ProjectName : Text#25;
ConectionStringSource : Text;
ConectionStringDestination : Text;
DateCompared: DateTime;
Comment: Text?;
ProjectOwner: ApplicationUser;
} where identity ProjectID;
//this will define a SQL foreign key relationship
ProjectCollection : Project* where item.ProjectOwner in ApplicationUserCollection;
set xact_abort on;
go
begin transaction;
go
set ansi_nulls on;
go
create schema [Test1];
go
create table [Test1].[ApplicationUserCollection]
(
[UserID] bigint not null identity,
[FirstName] nvarchar(max) null,
[LastName] nvarchar(25) not null,
[Password] nvarchar(10) not null,
constraint [PK_ApplicationUserCollection] primary key clustered ([UserID])
);
go
create table [Test1].[ProjectCollection]
(
[ProjectID] bigint not null identity,
[Comment] nvarchar(max) null,
[ConectionStringDestination] nvarchar(max) not null,
[ConectionStringSource] nvarchar(max) not null,
[DateCompared] datetime2 not null,
[ProjectName] nvarchar(25) not null,
[ProjectOwner] bigint not null,
constraint [PK_ProjectCollection] primary key clustered ([ProjectID]),
constraint [FK_ProjectCollection_ProjectOwner_Test1_ApplicationUserCollection] foreign key ([ProjectOwner]) references [Test1].[ApplicationUserCollection] ([UserID])
);
go
insert into [Test1].[ApplicationUserCollection] ([FirstName], [LastName], [Password])
values (N'user1', N'name1', N'1@34')
;
insert into [Test1].[ApplicationUserCollection] ([FirstName], [LastName], [Password])
values (N'user2', N'name2', N'123@4')
;
insert into [Test1].[ApplicationUserCollection] ([FirstName], [LastName], [Password])
values (N'user3', N'name3', N'56#2')
;
insert into [Test1].[ApplicationUserCollection] ([FirstName], [LastName], [Password])
values (N'user4', N'name4', N'789@5')
;
go
commit transaction;
Go
نکته:
جهت آشنایی با انواع دادههای مجاز در زبان M میتوان به مستندات رسمی آن مراجعه نمود:
The "Oslo" Modeling Language Specification
اکنون قصد داریم همانند مثال قسمت قبل، تعدادی رکورد آزمایشی را برای این جدول تعریف کنیم:
ProjectCollection
{
Project1{
ProjectName = "My Project 1",
ConectionStringSource = "Data Source=.;Initial Catalog=MyDB1;Integrated Security=True;",
ConectionStringDestination = "Data Source=.;Initial Catalog=MyDB2;Integrated Security=True;",
Comment="Project Comment",
DateCompared=2009-01-01T00:00:00,
ProjectOwner=ApplicationUserCollection.User1 //direct ref to User1 (FK)
},
Project2{
ProjectName = "My Project 2",
ConectionStringSource = "Data Source=.;Initial Catalog=MyDB1;Integrated Security=True;",
ConectionStringDestination = "Data Source=.;Initial Catalog=MyDB2;Integrated Security=True;",
Comment="Project Comment",
DateCompared=2009-01-01T00:00:00,
ProjectOwner=ApplicationUserCollection.User2 //direct ref to User2 (FK)
}
}
ادامه دارد ...
مطالب دورهها
مثال - نمایش بلادرنگ میزان مصرف CPU و حافظه سرور بر روی کلیه کلاینتهای متصل توسط SignalR
یکی از کاربردهای جالب SignalR میتواند به روز رسانی مداوم صفحه نمایش کاربران، توسط اطلاعات ارسالی از طرف سرور باشد. در ادامه قصد داریم به عنوان منبع داده، آمار کارآیی سرور را به کلاینتها ارسال کنیم و سپس به تصویری همانند شکل ذیل برسیم:
در اینجا از Smoothie Charts برای ترسیم نمودارهای بلادرنگ سازگار با Canvas مخصوص HTML5 استفاده شده است.
پیشنیازها
پیشنیازهای این مطلب با مطلب «مثال - نمایش درصد پیشرفت عملیات توسط SignalR» یکی است. برای مثال، نحوه دریافت وابستگیها، تنظیمات فایل global.asax و افزودن اسکریپتها، تفاوتی با مثال قبلی ندارند.
تهیه منبع داده اطلاعات نمایشی
کلاس PerformanceCounterProvider، سه مؤلفه کارآیی سرور را بررسی کرده و هربار توسط متد GetResults، آنها را بازگشت میدهد. از این منبع داده، در هاب برنامه استفاده خواهیم کرد.
تهیه هاب ارسال دادهها به کلاینتها
در این هاب، یک thread timer ایجاد شده است که هر دو ثانیه یکبار، اطلاعات را از PerformanceCounterProvider دریافت و سپس با فراخوانی this.Clients.All.newCounters، آنها را به کلیه کلاینتهای متصل ارسال میکند.
این هاب به صورت خودکار با اولین بار وهله سازی، پس از فراخوانی متد connection.hub.start در سمت کلاینت، شروع به کار میکند.
کدهای سمت کلاینت نمایش نمودارها
- در ابتدا سه canvas بر روی صفحه قرار گرفتهاند که معرف سه PerformanceCounter دریافتی از سرور هستند.
- id هر canavs به Name اطلاعات دریافتی از سرور تنظیم شده است تا نمودارها در جای صحیحی ترسیم شوند.
- سپس نحوه کپسوله سازی SmoothieChart را مشاهده میکنید؛ چطور میتوان از آن یک شیء جاوا اسکریپتی ایجاد کرد و چطور اطلاعات را به آن اضافه نمود.
- نهایتا کار هاب را آغاز میکنیم. Callback ایی به نام performanceCounterHub.client.newCounters دقیقا متصل است به فراخوانی this.Clients.All.newCounters سمت سرور. در اینجا updatedCounters دریافتی، یک آرایه جاوا اسکریپتی است که هر عضو آن دارای Name و Value است. بر این اساس، تنها کافی است این مقادیر را که هر دو ثانیه یکبار به روز میشوند، به SmoothieChart برای ترسیم ارسال کنیم.
کدهای کامل این مثال را از اینجا نیز میتوانید دریافت کنید:
SignalR04.zip
در اینجا از Smoothie Charts برای ترسیم نمودارهای بلادرنگ سازگار با Canvas مخصوص HTML5 استفاده شده است.
پیشنیازها
پیشنیازهای این مطلب با مطلب «مثال - نمایش درصد پیشرفت عملیات توسط SignalR» یکی است. برای مثال، نحوه دریافت وابستگیها، تنظیمات فایل global.asax و افزودن اسکریپتها، تفاوتی با مثال قبلی ندارند.
تهیه منبع داده اطلاعات نمایشی
using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace SignalR04.Common { public class Counter { public string Name { set; get; } public float Value { set; get; } } public class PerformanceCounterProvider { private readonly List<PerformanceCounter> _counters = new List<PerformanceCounter>(); public PerformanceCounterProvider() { _counters.Add(new PerformanceCounter("Processor", "% Processor Time", "_Total", readOnly: true)); _counters.Add(new PerformanceCounter("Memory", "Pages/sec", readOnly: true)); _counters.Add(new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total", readOnly: true)); } public IList<Counter> GetResults() { return _counters.Select(c => new Counter { Name = c.CategoryName, Value = c.NextValue() }).ToList(); } } }
تهیه هاب ارسال دادهها به کلاینتها
using System.Threading; using Microsoft.AspNet.SignalR; using ThreadTimer = System.Threading.Timer; namespace SignalR04.Common { public class PerformanceCounterHub : Hub { private ThreadTimer _threadTimer; //keep it alive private readonly PerformanceCounterProvider _perfService = new PerformanceCounterProvider(); public PerformanceCounterHub() { _threadTimer = new ThreadTimer(timerCallback, null, Timeout.Infinite, 1000); _threadTimer.Change(dueTime: 1000, period: 2000); } private void timerCallback(object state) { var results = _perfService.GetResults(); this.Clients.All.newCounters(results); } } }
این هاب به صورت خودکار با اولین بار وهله سازی، پس از فراخوانی متد connection.hub.start در سمت کلاینت، شروع به کار میکند.
کدهای سمت کلاینت نمایش نمودارها
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script> <script src="Scripts/jquery.signalR-1.1.3.min.js" type="text/javascript"></script> <script type="text/javascript" src='<%= ResolveClientUrl("~/signalr/hubs") %>'></script> <script src="Scripts/smoothie.js" type="text/javascript"></script> </head> <body> <form id="form1" runat="server"> <div> <div> <h2>Processor</h2> <canvas id="Processor" width="800" height="100"></canvas> </div> <div> <h2>Memory</h2> <canvas id="Memory" width="800" height="100"></canvas> </div> <div> <h2>PhysicalDisk</h2> <canvas id="PhysicalDisk" width="800" height="100"></canvas> </div> </div> </form> <script type="text/javascript"> var ChartEntry = function (name) { var self = this; self.name = name; self.chart = new SmoothieChart({ millisPerPixel: 50, labels: { fontSize: 15} }); self.timeSeries = new TimeSeries(); self.chart.addTimeSeries(self.timeSeries, { lineWidth: 3, strokeStyle: "#00ff00" }); }; ChartEntry.prototype = { addValue: function (value) { var self = this; self.timeSeries.append(new Date().getTime(), value); }, start: function () { var self = this; self.canvas = document.getElementById(self.name); self.chart.streamTo(self.canvas); } }; $(function () { $.connection.hub.logging = true; var performanceCounterHub = $.connection.performanceCounterHub; var charts = []; performanceCounterHub.client.newCounters = function (updatedCounters) { $.each(updatedCounters, function (index, updateCounter) { var entry; $.each(charts, function (idx, chart) { if (chart.name == updateCounter.Name) { entry = chart; return; } }); if (!entry) { entry = new ChartEntry(updateCounter.Name); charts.push(entry); entry.start(); } entry.addValue(updateCounter.Value); }); }; $.connection.hub.start(); }); </script> </body> </html>
- id هر canavs به Name اطلاعات دریافتی از سرور تنظیم شده است تا نمودارها در جای صحیحی ترسیم شوند.
- سپس نحوه کپسوله سازی SmoothieChart را مشاهده میکنید؛ چطور میتوان از آن یک شیء جاوا اسکریپتی ایجاد کرد و چطور اطلاعات را به آن اضافه نمود.
- نهایتا کار هاب را آغاز میکنیم. Callback ایی به نام performanceCounterHub.client.newCounters دقیقا متصل است به فراخوانی this.Clients.All.newCounters سمت سرور. در اینجا updatedCounters دریافتی، یک آرایه جاوا اسکریپتی است که هر عضو آن دارای Name و Value است. بر این اساس، تنها کافی است این مقادیر را که هر دو ثانیه یکبار به روز میشوند، به SmoothieChart برای ترسیم ارسال کنیم.
کدهای کامل این مثال را از اینجا نیز میتوانید دریافت کنید:
SignalR04.zip
هر ساله لیستی از پرکاربردترین کلمات عبور کاربران در دنیا، منتشر میشود که یک نمونه از آنرا در اینجا میتوان مشاهده کرد:
«Splashdata، توسعه دهنده نرم افزارهای امنیتی، فهرست سالانه خود را از رایجترین رمزهای عبور منتشر کرده است.»
میشود از این لیست برای بهبود پروسه ثبت نام در یک سایت استفاده کرد و همان زمان که کاربر کلمه عبور ضعیفی را وارد کرده است، به او پیغام داد که «کلمه عبور وارد شده را راحت میتوان حدس زد!»
متد الحاقی IsSafePasword فوق بررسی میکند که آیا کلمه عبور انتخابی:
- خالی نیست.
- بیشتر از 5 کاراکتر طول دارد.
- تمام حروف بکارگرفته شده در آن یکسان نیستند.
و در ASP.NET MVC با استفاده از قابلیت Remote validation آن استفاده از این متد به نحو زیر خواهد بود:
ابتدا یک اکشن متد به کنترلر ثبت نام در سایت به نحو فوق اضافه خواهد شد.
سپس قسمتی از ViewModel متناظر با صفحه ثبت نام سایت، به شکل زیر اضافه و تعریف میگردد:
«Splashdata، توسعه دهنده نرم افزارهای امنیتی، فهرست سالانه خود را از رایجترین رمزهای عبور منتشر کرده است.»
میشود از این لیست برای بهبود پروسه ثبت نام در یک سایت استفاده کرد و همان زمان که کاربر کلمه عبور ضعیفی را وارد کرده است، به او پیغام داد که «کلمه عبور وارد شده را راحت میتوان حدس زد!»
using System.Linq; namespace SecurityModule { public static class SafePassword { public static ISet<string> BadPasswords = new HashSet<string> { "password", "password1", "123456", "12345678", "1234", "qwerty", "12345", "dragon", "******", "baseball", "football", "letmein", "monkey", "696969", "abc123", "mustang", "michael", "shadow", "master", "jennifer", "111111", "2000", "jordan", "superman", "harley", "1234567", "iloveyou", "trustno1", "sunshine", "123123", "welcome" }; public static bool IsSafePasword(this string data) { if (string.IsNullOrWhiteSpace(data)) return false; if (data.Length < 5) return false; if (BadPasswords.Contains(data.ToLowerInvariant())) return false; if (data.AreAllCharsEuqal()) return false; return true; } public static bool AreAllCharsEuqal(this string data) { if (string.IsNullOrWhiteSpace(data)) return false; data = data.ToLowerInvariant(); var firstElement = data.ElementAt(0); var euqalCharsLen = data.ToCharArray().Count(x => x == firstElement); if (euqalCharsLen == data.Length) return true; return false; } } }
- خالی نیست.
- بیشتر از 5 کاراکتر طول دارد.
- تمام حروف بکارگرفته شده در آن یکسان نیستند.
و در ASP.NET MVC با استفاده از قابلیت Remote validation آن استفاده از این متد به نحو زیر خواهد بود:
public partial class RegisterController : Controller { //... [HttpPost] [OutputCache(Location = OutputCacheLocation.None, NoStore = true)] public virtual ActionResult CheckPassword(string password1) { return Json(password1.IsSafePasword()); } }
سپس قسمتی از ViewModel متناظر با صفحه ثبت نام سایت، به شکل زیر اضافه و تعریف میگردد:
using System.ComponentModel.DataAnnotations; using System.Web.Mvc; namespace MyBlog.Models { public class RegisterViewModel { //... [Display(Name = "کلمه عبور")] [Required(ErrorMessage = "لطفا کلمه عبور خود را وارد نمائید")] [DataType(DataType.Password)] [StringLength(50, MinimumLength = 5, ErrorMessage = "حداقل طول کلمه عبور 5 حرف است")] [Remote(action: "CheckPassword", controller: "Register", HttpMethod = "POST", ErrorMessage = "کلمه عبور وارد شده را راحت میتوان حدس زد!")] public string Password1 { get; set; } } }