<?xml version="1.0" encoding="utf-8"?> <Log xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Type>Verify</Type> <Gateway>Mellat</Gateway> <OrderNumber>636696338698017740</OrderNumber> <Amount>50000</Amount> <ReferenceId>63610A4322A08FDD</ReferenceId> <TransactionId>139032371054</TransactionId> <Status>Success</Status> <Message>تراکنش با موفقیت انجام شد</Message> <CreatedOn>2018-08-12T01:25:31.1869631+04:30</CreatedOn> </Log>
- در مورد سوئیچ startup-project در مطلب « شروع به کار با EF Core 1.0 - قسمت 3 - انتقال مهاجرتها به یک اسمبلی دیگر» بحث شدهاست.
- این پروژه از فایل _01-add_migrations.cmd برای افزودن مهاجرتها استفاده میکند و از فایل _02-update_db.cmd برای به روز رسانی ساختار بانک اطلاعاتی.
- Context تعریف شدهی این پروژه دارای یک سازندهی با چندین پارامتر است. نباید سازندهی دارای پارامتر دیگری را برای آن تعریف کنید (علت خطای دریافت شده). نیازی هم به اینکار نیست. چون اینترفیس تزریقی IOptions آن دسترسی کاملی را به اطلاعات فایل config برنامه در اختیار شما قرار میدهد و کاملا قابل سفارشی سازی است (قسمت «امکان نگاشت تنظیمات برنامه به کلاسهای متناظر»).
بررسی روش ارتقاء به NET Core 1.1.
من حداقل چنین مشکلی را ندارم:
فایل Properties\PublishProfiles\Test.pubxml مورد استفاده هم چنین محتوایی را دارد:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <WebPublishMethod>FileSystem</WebPublishMethod> <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration> <LastUsedPlatform>Any CPU</LastUsedPlatform> <SiteUrlToLaunchAfterPublish /> <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish> <ExcludeApp_Data>False</ExcludeApp_Data> <PublishFramework>netcoreapp1.1</PublishFramework> <UsePowerShell>True</UsePowerShell> <publishUrl>.\bin\Release\PublishOutput</publishUrl> <DeleteExistingFiles>False</DeleteExistingFiles> </PropertyGroup> </Project>
حالت پیش فرض خروجی ASP.NET Core 1.0 RTM دقیقا همان camel case است. اگر میخواهید آنرا به Pascal Case تغییر دهید، میتوانید به صورت زیر عمل کنید:
services.AddMvc().AddJsonOptions(opt => { var resolver = opt.SerializerSettings.ContractResolver; if (resolver != null) { var res = resolver as DefaultContractResolver; res.NamingStrategy = null; // this is what removes the camelcasing } });
public partial class App { public App() { this.DispatcherUnhandledException += appDispatcherUnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; }
<?xml version="1.0"?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>
محاسبه عرض یک box در اینترنت اکسپلورر 6 به صورت زیر است:
این در حالی است که روش استاندارد محاسبه عرض یک box به صورت زیر است:
برای رفع این مشکل چندین روش وجود دارد. اما به نظر من بهترین روش قرار دادن تگ زیر در ابتدای صفحه است:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
از زمانیکه دات نت فریم ورک ارائه شده (حدودا 8 سال یا بیشتر اگر بتای آنرا هم به حساب بیاوریم به سال 2000 بر میگردد)، نگارشهای متفاوتی تا به امروز در اختیار عموم قرار گرفته اند.
جدول زیر این موارد را تا این تاریخ لیست کرده و شماره نگارش دقیق آنها را نیز بر میشمارد:
.NET version | Actual version |
3.5 SP1 | 3.5.30729.1 |
3.5 | 3.5.21022.8 |
3.0 SP2 | 3.0.4506.2152 |
3.0 SP1 | 3.0.4506.648 |
3.0 | 3.0.4506.30 |
2.0 SP2 | 2.0.50727.3053 |
2.0 SP1 | 2.0.50727.1433 |
2.0 | 2.0.50727.42 |
1.1 SP1 | 1.1.4322.2032 |
1.1 SP1 (in 32 bit version of Windows 2003) | 1.1.4322.2300 |
1.1 | 1.1.4322.573 |
1.0 SP3 | 1.0.3705.6018 |
1.0 SP2 | 1.0.3705.288 |
1.0 SP1 | 1.0.3705.209 |
1.0 | 1.0.3705.0 |
برای بدست آوردن شماره نگارشهای نصب شده بر روی یک کامپیوتر متاسفانه راه سادهای وجود ندارد. امکاناتی هم که خود دات نت فریم ورک به صورت ذاتی ارائه میدهد به صورت زیر است:
class NetVersion
{
public static string Version
{
get
{
return Environment.Version + "\n" +
Environment.OSVersion;
}
}
}
که خروجی آن فقط آخرین نگارش CLR را شامل میشود.
برای مثال روی ویندوز اکس پی سرویس پک 3 با دات نت فریم ورک سه و نیم، سرویس پک یک خواهیم داشت:
2.0.50727.3053
Microsoft Windows NT 5.1.2600 Service Pack 3
خوبی این روش هم این است که اگر در یک هاست اینترنتی قصد داشتید شماره نگارش دات نت فریم ورک سرور را بررسی کنید، بدون مشکل پاسخ خواهد داد. برای مثال اگر به دات نت فریم ورک 2 سرویس پک 2 رسیدید، یعنی دات نت فریم ورک سه و نیم، سرویس پک یک حتما روی سرور نصب است، چون این دو با هم ارائه شدهاند و به صورت مجزا ارائه نشدهاند.
برای بدست آوردن لیست دات نت فریم ورکهای مختلف باید به رجیستری ویندوز مراجعه کرد. مسیرهای:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform
این روش یا حتی لیست کردن فولدرهای نصب شد در مسیر C:\WINDOWS\Microsoft.NET\Framework نیز شماره نگارش کامل را ارائه نمیدهند. تنها راه باقیمانده مراجعه به فایل mscorlib.dll هر پوشه و بررسی نگارش آن است:
اینکار را با برنامه نویسی به صورت زیر میتوان انجام داد:
public static string MscorlibVersion
{
get
{
//using System.Diagnostics;
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(
Environment.GetEnvironmentVariable("windir") +
@"\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll");
return myFileVersionInfo.ProductVersion;
}
}
Strong Name
System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35
برای استفاده از این تکنولوژی ابتدا نیاز است تا یک جفتکلید عمومی/خصوصی (توسط ادمین، منبع گواهینامهها، یک بانک یا یک ابزار خاص) فراهم شود تا از آن برای اینکریپشن استفاده شود. سپس دادههای موردنظر (هر داده کلی که قصد ارسال و توزیع آن را داریم مثل یک اسمبلی) با استفاده از یک الگوریتم هشکردن (مثل MD5، SHA یا ترکیبی از آنها، هرچند MD5 توصیه نمیشود) پردازش شده و یک هشکد مخصوص تولید میشود. این هشکد با استفاده از کلید خصوصی دردسترس اینکریپت میشود و به عنوان یک امضای دیجیتال به همراه داده موردنظر ارسال یا توزیع میشود. در سمت مصرف کننده که با استفاده از یک روش خاص و امن به کلید عمومی دسترسی پیدا کرده است عملیات دیکریپت کردن این امضای دیجیتال با استفاده از کلید عمومی انجام شده و هشکد مربوطه بدست میآید. همچنین عملیات تولید هشکد با استفاده از دادهها در سمت مصرف کننده انجام شده و هشکد دادهها نیز دوباره با استفاده از همان الگوریتم استفاده شده در سمت توزیعکننده تولید میشود. سپس این دو مقدار محاسبه شده در سمت مصرفکننده با یکدیگر مقایسه شده و درصورت برابر بودن میتوان اطمینان حاصل کرد همان دادهای که توزیع کننده در اصل ارسال کرده بدون تغییر به دست مصرف کننده رسیده است. درواقع ویژگی اینکریپت/دیکریپت کردن دادهها توسط جفتکلید این است که بهصورت یکطرفه بوده و دادههای اینکریپت شده با استفاده از یک کلید خصوصی را تنها با استفاده از کلید عمومی همان کلید خصوصی میتوان بدرستی دیکریپت کرد.
1. تولید و مدیریت جفتکلیدهای قوی- نامگذاریشده (Strongly Named Key Pairs)
همانطور که در قسمت قبل اشاره شد برای نامگذاری قوی یک اسمبلی به یک کلید عمومی (public key) و یک کلید خصوصی (private key) که در مجموع به آن یک جفت کلید (key pair) میگویند، نیاز است.برای اینکار میتوان با استفاده از برنامه sn.exe (عنوان کامل آن Microsoft .Net Framework Strong Name Utility است) یک جفت کلید تولید کرده و آن را در یک فایل و یا در CSP (یا همان cryptographic service provider) ذخیره کرد. همچنین اینکار را میتوان توسط ویژوال استودیو نیز انجام داد. امکان موردنظر در فرم پراپرتی یک پروژه و در تب Signing آن وجود دارد.
نکته: یک CSP عنصری از API کریپتوگرافی ویندوز (Win32 CryptoAPI) است که سرویسهایی چون اینکریپشن، دیکریپشن، و تولید امضای دیجیتال را فراهم میکند. این پرووایدرها همچنین تسهیلاتی برای مخازن کلیدها فراهم میکنند که از اینکریپشنهای قوی و ساختار امنیتی سیستم عامل (سیستم امنیتی و دسترسی کاربران ویندوز) برای محافظت از تمام کلیدهای کریپتوگرافی ذخیره شده در مخزن استفاده میکند. بهطور خلاصه و مفید میشود اشاره کرد که میتوان کلیدهای کریپتوگرافی را درون یک مخزن کلید CSP ذخیره کرد و تقریبا مطمئن بود که تا زمانیکه هیچکس کلمه عبور سیستم عامل را نداند، این کلیدها امن خواهند ماند. برای کسب اطلاعات بیشتر به دادههای CryptoAPI در اسناد SDK سیستم عامل خود مراجعه کنید.
برنامه sn به همراه SDKهای ویندوز نصب میشود. البته با نصب ویژوال استودیو تمام SDKهای موردنیاز مطابق با نسخههای موجود، نصب خواهد شد. مسیر نسخه 4 و 32 بیتی این برنامه در سیستم عامل Windows 7 بهصورت زیر است:
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sn.exe
با استفاده از آرگومان k همانند دستور زیر یک جفتکلید جدید تولید شده و در فایل MyKeys.snk در ریشه درایو d: ذخیره میشود:
sn –k d:\MyKeys.snk
نکته: به بزرگی و کوچکی حروف سوییچهای دستورات برنامه sn دقت کنید!
این کار یک جفت کلید کریپتوگرافی 1024 بیتی بهصورت تصادفی تولید میکند. این دستور را باید در خط فرمانی (Command Prompt) اجرا نمود که مسیر فایل sn.exe را بداند. برای راحتی کار میتوان از خط فرمان ویژوال استودیو (Visual Studio Command Prompt) استفاده کرد.
نکته: اجرای عملیات فوق در یک شرکت یا قسمت توسعه یک شرکت، تنها یک بار نیاز است زیرا تمام اسمبلیهای تولیدی تا زمانیکه عناوین ساده متمایزی دارند میتوانند از یک جفت کلید مشترک استفاده کنند.
نکته: هرچند که میتوان از پسوندهای دیگری نیز برای نام فایل حاوی جفت کلید استفاده کرد، اما توصیه میشود از همین پسوند snk. استفاده شود.
فایل تولید شده حاوی هر دو کلید «عمومی» و «خصوصی» است. میتوان با استفاده از دستور زیر کلید عمومی موجود در فایل mykeys.snk را استخراج کرده و در فایل mypublickey.snk ذخیره کرد:
sn –p d:\mykeys.snk d:\mypublickey.snk
sn -tp MyPublicKey.snk
sn -i MyKeys.snk MyStrongNameKeys
sn –m n
sn –m y
sn -d MyStrongNameKeys
نکته: برای استفاده از این ویژگی در ویژوال استودیو، باید در تب Signing در تنظیمات پروژه گزینه Sign the Assembly را انتخاب کرد. سپس میتوان فایل حاوی جفت کلیدهای تولیدشده را انتخاب یا فایل جدیدی تولید کرد. البته ویژوال استودیو تا نسخه 2010 امکانی جهت استفاده از مخازن CSP را ندارد.
[assembly:AssemblyKeyFileAttribute("MyKeys.snk")]
sn –vf MyAsm.exe
Microsoft (R) .NET Framework Strong Name Utility Version 2.0.50727.42 Copyright (C) Microsoft Corporation. All rights reserved. Failed to verify assembly -- Strong name validation failed for assembly MyAsm.exe'.
sn –p d:\MyKeys.snk d:\MyPublicKey.snk sn –pc MyKeysContainer d:\MyPublicKey.snk
csc.exe /delaysign /keyfile:d:\MyPublicKey.snk /out:d:\MyAsm.exe d:\Class1.cs
al /out:<assembly name> <module name> /keyfile:<file name>
sn –Vr d:\MyAsm.exe
sn –R d:\MyAsm.exe MyKeys.snk sn –R d:\MyAsm.exe MyKeysContainer
sn –D assembly1 assembly2
sn –Vu d:\MyAsm.exe
sn –Vx
sn –Vl
C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe
gacutil /i c:\MyAsm.dll
gacutil /u MyAsm
gacutil /u MyAsm,Version=1.3.0.5
gacutil /l
gacutil /l MyAsm
قبل از شروع به طراحی UI باید کمی با واحدهای اندازه گیری در اندروید آشنا شویم. بدانید و آگاه باشید که استفاده از واحد Pixel برای تعیین اندازه در اندروید کار بسیار اشتباهی است. طراح همیشه باید Density یا تراکم صفحهی نمایش را در نظر بگیرد. تراکم صفحهی نمایش به معنای تعداد پیکسل موجود در یک اینچ میباشد. اندازهی 100 پیکسل در دستگاههای مختلف با (dpi(Dot Per Inchهای متفاوت به یک اندازه نیست.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/MyButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/Hello" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:background="#fff" android:id="@+id/NameListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); List<string> namesList = new List<string> { "Mohammad","Fatemeh","Ali","Hasan","Husein","Mohsen","Mahdi", }; var namesAdapter = new ArrayAdapter<string> (this, Android.Resource.Layout.SimpleListItem1, namesList); var listview = FindViewById<ListView>(Resource.Id.NameListView); listview.Adapter = namesAdapter; }
ListView کنترل بسیار منعطفی میباشد. برخی ویژگیها آن را در زیر میتوانید مشاهده بفرمایید:
- android:dividerHeight // ارتفاع جداکنندهی سطرها
- android:divider // رنگ جداکنندهی سطرها
- android:layoutAnimation // انیمیشن برای layoutها
- android:background // رنگ ضمینه را مشخص میکند. البته میتوانید یک style را به ان نسبت دهید
خوب؛ حالا بیایید یک ListView را با ظاهر و Adapter سفارشی بسازیم.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="14dp"> <TextView android:text="" android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/idTextView" /> <TextView android:text="" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/nameTextView" android:layout_marginLeft="14dp" /> </LinearLayout>
namespace DotSystem.ir.App1.Model { public class Person { public int Id { get; set; } public string PersonName { get; set; } }
namespace DotSystem.ir.App1.Adapters { public class PersonAdapter : BaseAdapter<Model.Person> { public override Person this[int position] { get { throw new NotImplementedException(); } } public override int Count { get { throw new NotImplementedException(); } } public override long GetItemId(int position) { throw new NotImplementedException(); } public override View GetView(int position, View convertView, ViewGroup parent) { throw new NotImplementedException(); } } }
در اینجا ما به چند فیلد داخل کلاس احتیاج داریم.
- لیست اطلاعات مورد نظر.
- Activity جاری که Adapter را استفاده میکند.
namespace DotSystem.ir.App1.Adapters { public class PersonAdapter : BaseAdapter<Person> { protected Activity _activity = null; protected List<Person> _list = null; public PersonAdapter(Activity activity, List<Person> list) { _activity = activity; _list = list; } public override Person this[int position] { get { return _list[position]; } } public override int Count { get { return _list.Count; } } public override long GetItemId(int position) { return _list[position].Id; } public override View GetView(int position, View convertView, ViewGroup parent) { throw new NotImplementedException(); } } }
public override View GetView(int position, View convertView, ViewGroup parent) { if (convertView == null) convertView = _activity.LayoutInflater .Inflate(Resource.Layout.PersonListViewItemLayout, parent, false); var idTextView = convertView.FindViewById<TextView>(Resource.Id.idTextView); var nameTextView = convertView.FindViewById<TextView>(Resource.Id.NameListView); var persion = _list[position]; idTextView.Text = persion.Id.ToString(); nameTextView.Text = persion.PersonName; return convertView; }
protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); List<Model.Person> personList = new List<Model.Person> { new Model.Person() {Id = 1, PersonName = "Mohammad", }, new Model.Person() {Id = 2, PersonName = "Ali", }, new Model.Person() {Id = 3, PersonName = "Fatemeh", }, new Model.Person() {Id = 4, PersonName = "hasan", }, new Model.Person() {Id = 5, PersonName = "Husein", }, new Model.Person() {Id = 6, PersonName = "Mohsen", }, new Model.Person() {Id = 14, PersonName = "Mahdi", }, }; var personAdapter = new Adapters.PersonAdapter(this, personList); var listview = FindViewById<ListView>(Resource.Id.NameListView); listview.Adapter = personAdapter; }