استفاده از reCAPTCHA در ASP.NET
NiftyDotNet!
لینک گوگل کد مشکلی نداره فقط ما رو فیلتر کردند.
همانطور که در قسمت اول گفته شد، React برای اینکه بتواند تگها را در زمان اجرا و به صورت پویا به روز کند، وضعیت فعلی تگها را دنبال میکند و در صورت وقوع تغییرات، تگها را به روز میکند. به این حالت Stateful گفته میشود. تگهای ساخته شده توسط React دو وضعیت را دارند. یکی وضعیت اولیه که به مرورگر ارسال شده، در حال نمایش است و ثابت، و دیگری در پشت زمینه در فایل جاوااسکریپت، در انتظار وقوع تغییری. React این دو وضعیت را با هم مقایسه میکند و اگر بین آنها تفاوتی وجود داشت، تغییرات را اعمال میکند.
در React.createClass به همراه متدهای داخلی React میتوانیم برای یک کامپوننت، وضعیتی اولیه را مشخص کنیم، تغییرات را دنبال کنیم و وضعیت فعلی را تغییر دهیم. برای روشن شدن نحوه کار، مثال قسمت قبل را که یک منو از نوشیدنیها بود، اینطور تغییر میدهیم که کاربر بتواند با inputها و یک دکمه، به لیست نوشیدنیها، مورد تازهای را اضافه کند:
var hotDrinks = [ { item: "Tea", price: "7000" }, { item: "Espresso", price: "10000" }, { item: "Hot Chocolate", price: "12000" } ]; var MenuItem = React.createClass({ render: function () { return ( <li className="list-group-item"> <span className="badge">{this.props.price}</span> <p>{this.props.item}</p> </li> ) } }); var Menu = React.createClass({ getInitialState: function () { return { menuList: this.props.data }; }, componentDidMount: function () { var component = this; $("#btnAddNewItem").click(function () { component.state.menuList.push( { item: $("#textInputItemName").val(), price: $("#textInputItemPrice").val() }); component.setState({ menuList: component.state.menuList }); }); }, render: function () { return ( <div className="row"> <div className="col-md-4"> <ul className="list-group"> {this.state.menuList.map(item => <MenuItem {...item} />)} </ul> </div> </div> ) } }); ReactDOM.render( <Menu data={hotDrinks} />, document.getElementById("reactTestContainer") );
توضیح کامپوننت Menu
getInitialState، componentDidMount، setState، state و render همگی از کتابخانه React هستند. اگر intelisense و code snippets مخصوص React را در VSCode نصب کرده باشید، دسترسی به سایر متدها و خاصیتهای کتابخانه سادهتر است.
شیء state، وضعیت کنونی کامپوننت است. وقتی دادهای را به state اختصاص میدهیم، آن را به عنوان وضعیت اولیه در نظر میگیرد. با تغییر داده، React وضعیت کامپوننت را تغییر یافته حساب میکند و به صورت خودکار تگها را دوباره با دادههای تازه میسازد. دادههای state همان دادههایی هستند که تگها با آنها ساخته میشوند؛ در بخش render.
getInitialState مثل یک سازنده عمل میکند؛ مقدار ورودی کامپوننت را به یک شیء اختصاص میدهد و آن را برمیگرداند. به کجا؟ به state. یعنی menuList عضوی از شیء state میشود. در مثال بالا و در این متد، لیست نوشیدنیها به menuList اعمال میشود.
componentDidMount باید حتما قبل render تعریف شود، به این دلیل که زمان اجرایش باید حتما بعد از اولین render باشد. این متد وظیفه دارد تغییرات مورد نظر ما را در سطح کد یا رابط کاربری دنبال کند. اگر تغییر دلخواهی به وجود آمد، وضعیت کامپوننت را به روز میکند که بعد از آن React به صورت خودکار تگها را دوباره میسازد. در مثال بالا متد به رویداد کلیک یک دکمه گوش میدهد. اگر کلیک زده شد، نام نوشیدنی جدید و قیمت آن را از inputها میخواند و به عنوان یک آیتم جدید به menuList در state اضافه میکند. اما هنوز یک قدم مانده و بدون آن React، شیء state را تغییر یافته به حساب نمیآورد. در بخش setState وضعیت جاری کامپوننت را با تغییرات اعمال شده، جایگزین میکنیم. در این نقطه React به صورت خودکار به سراغ render میرود و ادامه داستان!
همانطور که قبلا گفته شد، React.createClass و React.Component فقط در Syntax با هم تفاوت دارند. در نتیجه این مثال را میشود در حالت React.Component هم اجرا کرد.
در قسمت بعد موضوع دیگری را به نام Composability شرح میدهیم. مبحثی ساده با مثال که نشان میدهد چطور کامپوننتها را مستقل از هم بسازیم و در عین حال با هم استفاده کنیم.
ASP.NET MVC #18
- MVC5 فقط یک افزونه است برای MVC4 و MVC4 هم یک افزونه است برای MVC3. در MVC5 افزونهای به نام ASP.NET Identity نیز ارائه شدهاست.
- پروژهی سورس باز دیگری نیز در سایت به نام Iris membership برای پوشش مسایل بحث جاری تهیه شدهاست.
نحوه ایجاد یک اسلایدشو به صورت داینامیک
CoffeeScript #13
بخشهای بد
در ادامهی قسمت قبل، به مواردی که توسط CoffeeScript اصلاح شدهاند، میپردازیم.
Reserved words
کلمات کلیدی خاصی در جاوااسکریپت وجود دارد مانند class، enum و const که برای نسخههای بعدی جاوااسکریپت در آینده رزرو شدهاند. استفاده از این کلمات در برنامههای جاوااسکریپت میتواند نتایج غیرقابل پیش بینی داشته باشد. برخی از مرورگرهای به خوبی از عهدهی این کار برمیآیند و بعضی دیگر به طور کامل جلوی استفاده از اینها را گرفتهاند. CoffeeScript بعد از تشخیص استفاده از یک کلمهی کلیدی، با یک راه کار خاص، از این موضوع میگریزد.
به عنوان مثال، فرض کنید میخواهیم از کلمه کلیدی class به عنوان یک خصوصیت در یک شیء استفاده کنیم:
myObj = { delete: "I am a keyword!" } myObj.class = ->
var myObj; myObj = { "delete": "I am a keyword!" }; myObj["class"] = function() {};
Equality comparisons
مقایسه برابری ضعف دیگری است که در جاوااسکریپت باعث ایجاد رفتاری گیج کننده و اغلب باعث ایجاد اشکالاتی در کد نوشته شده میشود. به مثال زیر توجه کنید:
"" == "0"// false 0 == ""// true 0 == "0"// true false == "false"// false false == "0"// true false == undefined// false false == null// false null == undefined// true " \t\r\n" == 0// true
راه حل این کار استفاده از عملگر برابری سختگیرانه است، که از 3 مساوی تشکیل شده است: === عملگر برابر سخت گیرانه دقیقا مانند عملگر برابری عادی عمل میکند و تنها نوع دادهها را بررسی میکند که با هم برابر باشند.
توصیه میشود که همیشه از عملگر برابری سختگیرانه استفاده کنید و هرجا لازم بود قبل مقایسه عمل تبدیل نوع دادهها را انجام دهید.
CoffeeScript این مشکل را به صورت کامل حل کرده است؛ یعنی هر جایی که عمل مقایسه == انجام شود به === تبدیل میشود. شما باید به صورت صریح نوع دادهها را قبل از مقایسه تبدیل کرده باشید.
نکته: در مقایسهها رشته خالی ""، null ،undefined و عدد 0 همگی false برمی گردانند.
alert "Empty Array" unless [].length alert "Empty String" unless "" alert "Number 0" unless 0
if (![].length) { alert("Empty Array"); } if (!"") { alert("Empty String"); } if (!0) { alert("Number 0"); }
alert "This is not called" unless ""?
if ("" == null) { alert("This is not called"); }
Function definition
خیلی جالب است که در جاوااسکریپت میتوانید تابعی را بعد از اینکه فراخوانی کردید، تعریف کنید. به عنوان مثال، کد زیر به صورت کامل اجرا میشود:
wem(); function wem() {alert("hi");}
if (true) { function declaration() { return "first"; } } else { function declaration() { return "second"; } } declaration();
، تابع ()declaration مقدار "first" را برگشت خواهد داد و در دیگر مرورگرها مانند Chrome، مقدار "second" برگشت داده خواهد شد. در حالیکه به نظر میرسد که قسمت else هیچگاه اجرا نخواهد شد.در صورتیکه علاقمند به کسب اطلاعات بیشتری دربارهی نحوه تعریف توابع، هستید باید راهنمای آقای Juriy Zaytsev را مطالعه کنید. به صورت خلاصه، رفتار نسبتا مبهم مرورگرها میتواند منجر به ایجاد مشکلاتی در مسیر نوشتن یک پروژه شوند.
همه چیز در CoffeeScript در نظر گرفته شده است و بهترین روش برای حل این مشکل، حذف کلمه function و به جای آن استفاده از عبارت (expression) تابع است.
Number property lookups
نقصی که در پارسر جاوااسکریپت در مواجه با نماد نقطه (dot notation) بر روی اعداد وجود دارد، تفسیر آن به ممیز شناور، بجای مراجعه به ویژگیهای آن است. برای مثال کد جاوااسکریپت زیر باعث ایجاد خطای نحوی میشود:5.toString();
(5).toString(); 5..toString();
انتقال SVN به یک سیستم جدید
1 - اساس کار متداول SVN بر اساس فولدر سازی به ازای هر تغییر نیست. به ازای هر تغییر شما میتونید موارد اصلاحی را commit کنید. بعد میشود بر اساس comment نوشته شده برای این commit گزارش گرفت و نگارش جاری را مثلا با 5 نگارش قبل مقایسه کرد. با همین ابزار diff ایی که معرفی کردم. ضمنا امکان export کامل پروژه به ازای هر نگارش commit شده وجود دارد.
البته مباحث انعشابات و غیره هم وجود دارد که در فصلی جداگانه به آن پرداخته شده.
میشود برچسب یا tag ایجاد کرد و کل پروژه را تا یک نگارش خاص در آن قرار داد. عموما برای ارائه نگارشهای عمومی این روش توصیه میشود.
یا میشود یک انعشاب درست کرد و جدا از خط اصلی کاری یا همان trunk کار کرد (مثلا آزمایش یک قابلیت جدید) و سپس این انعشاب تکمیل شده را با trunk و خط اصلی کاری یکی کرد.
هر کدام از این موارد (برچسب یا انشعاب) هم بر اساس پوشهها هستند البته در مخزن کد.
2 - افزونه Visual SVN این مورد را سادهتر کرده. خودش گزینهی ایجاد خودکار مخزن و افزودن به آنرا دارد و از این لحاظ در وقت صرفه جویی میشود.
ایجاد ویژگیهای اعتبارسنجی سفارشی در ASP.NET Core 3.1 به همراه اعتبارسنجی سمت کلاینت آنها
public class NationalCodeClientValidator : ClientValidatorBase { #region Fields private NationalCodeValidator NationalCodeValidator => (NationalCodeValidator)Validator; #endregion Fields #region Methods #region Constructors public NationalCodeClientValidator(PropertyRule rule, IPropertyValidator validator) : base(rule, validator) { } #endregion Constructors #region Override public override void AddValidation(ClientModelValidationContext context) { MergeAttribute(context.Attributes, "data-val", "true"); MergeAttribute(context.Attributes, "data-val-nationalcode", GetErrorMessage()); } #endregion Override #region Utility private string GetErrorMessage() { var formatter = ValidatorOptions.MessageFormatterFactory().AppendPropertyName(Rule.GetDisplayName()); string messageTemplate; try { messageTemplate = Validator.Options.ErrorMessageSource.GetString(null); } catch (FluentValidationMessageFormatException) { messageTemplate = ValidatorOptions.LanguageManager.GetStringForValidator<NotEmptyValidator>(); } var message = formatter.BuildMessage(messageTemplate); return message; } #endregion Utility #endregion Methods }
سپس کلاسی دیگر تعریف کرده و از PropertyValidator ارث بری میکنید:
public class NationalCodeValidator : PropertyValidator { #region Methods #region Constructors public NationalCodeValidator() : base(new LanguageStringSource(nameof(NationalCodeValidator))) { } #endregion Constructors #region Override protected override bool IsValid(PropertyValidatorContext context) { return true; } #endregion Override #endregion Methods }
سپس باید کلاسهای تعریف شده رو به FluentValidation معرفی کرد:
.AddFluentValidation(option => { option.RegisterValidatorsFromAssemblyContaining<CreateBankValidation>(); option.ConfigureClientsideValidation(AddFluentValidationClientModelValidatorProvider()); })
private static Action<FluentValidationClientModelValidatorProvider> AddFluentValidationClientModelValidatorProvider() { return clientSideValidation => { clientSideValidation.Add(typeof(NationalCodeValidator), (context, rule, validator) => new NationalCodeClientValidator(rule, validator)); }; }
حال فقط مانده استفاده ساختار Validation در سمت کلاینت:
// بررسی تایید کد ملی function setCustomValidator() { $.validator.unobtrusive.adapters.add('nationalcode', [], function (options) { options.rules['nationalcode'] = {}; options.messages['nationalcode'] = options.message; }); $.validator.addMethod('nationalcode', function (value, element, parameters) { if (isValidIranianNationalCode(value)) return true; return false; }); }
بهروزرسانی فایلهای Resource در زمان اجرا
یکی از ویژگیهای مهمی که در پیاده سازی محصول با استفاده از فایلهای Resource باید به آن توجه داشت، امکان بروز رسانی محتوای این فایلها در زمان اجراست. از آنجاکه احتمال اینکه کاربران سیستم خواهان تغییر این مقادیر باشند بسیار زیاد است، بنابراین درنظر گرفتن چنین ویژگیای برای محصول نهایی میتواند بسیار تعیین کننده باشد. متاسفانه پیاده سازی چنین امکانی درباره فایلهای Resource چندان آسان نیست. زیرا این فایلها همانطور که در قسمت قبل توضیح داده شد پس از کامپایل به صورت اسمبلیهای ستلایت (Satellite Assembly) درآمده و دیگر امکان تغییر محتوای آنها بصورت مستقیم و به آسانی وجود ندارد.private void TestResXResourceReader() { using (var reader = new ResXResourceReader("Resource1.fa.resx")) { foreach (var item in reader) { var resource = (DictionaryEntry)item; Console.WriteLine("{0}: {1}", resource.Key, resource.Value); } } }
public class ResXResourceEntry { public string Key { get; set; } public string Value { get; set; } public ResXResourceEntry() { } public ResXResourceEntry(object key, object value) { Key = key.ToString(); Value = value.ToString(); } public ResXResourceEntry(DictionaryEntry dictionaryEntry) { Key = dictionaryEntry.Key.ToString(); Value = dictionaryEntry.Value != null ? dictionaryEntry.Value.ToString() : string.Empty; } public DictionaryEntry ToDictionaryEntry() { return new DictionaryEntry(Key, Value); } }
private static List<ResXResourceEntry> Read(string filePath) { using (var reader = new ResXResourceReader(filePath)) { return reader.Cast<object>().Cast<DictionaryEntry>().Select(de => new ResXResourceEntry(de)).ToList(); } }
private static void Write(IEnumerable<ResXResourceEntry> resources, string filePath) { using (var writer = new ResXResourceWriter(filePath)) { foreach (var resource in resources) { writer.AddResource(resource.Key, resource.Value); } } }
private static void AddOrUpdate(ResXResourceEntry resource, string filePath) { var list = Read(filePath); var entry = list.SingleOrDefault(l => l.Key == resource.Key); if (entry == null) { list.Add(resource); } else { entry.Value = resource.Value; } Write(list, filePath); }
private static void Remove(string key, string filePath) { var list = Read(filePath); list.RemoveAll(l => l.Key == key); Write(list, filePath); }
public class ResXResourceManager { private static readonly object Lock = new object(); public string ResourcesPath { get; private set; } public ResXResourceManager(string resourcesPath) { ResourcesPath = resourcesPath; } public IEnumerable<ResXResourceEntry> GetAllResources(string resourceCategory) { var resourceFilePath = GetResourceFilePath(resourceCategory); return Read(resourceFilePath); } public void AddOrUpdateResource(ResXResourceEntry resource, string resourceCategory) { var resourceFilePath = GetResourceFilePath(resourceCategory); AddOrUpdate(resource, resourceFilePath); } public void DeleteResource(string key, string resourceCategory) { var resourceFilePath = GetResourceFilePath(resourceCategory); Remove(key, resourceFilePath); } private string GetResourceFilePath(string resourceCategory) { var extension = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName == "en" ? ".resx" : ".fa.resx"; var resourceFilePath = Path.Combine(ResourcesPath, resourceCategory.Replace(".", "\\") + extension); return resourceFilePath; } private static void AddOrUpdate(ResXResourceEntry resource, string filePath) { var list = Read(filePath); var entry = list.SingleOrDefault(l => l.Key == resource.Key); if (entry == null) { list.Add(resource); } else { entry.Value = resource.Value; } Write(list, filePath); } private static void Remove(string key, string filePath) { var list = Read(filePath); list.RemoveAll(l => l.Key == key); Write(list, filePath); } private static List<ResXResourceEntry> Read(string filePath) { lock (Lock) { using (var reader = new ResXResourceReader(filePath)) { var list = reader.Cast<object>().Cast<DictionaryEntry>().ToList(); return list.Select(l => new ResXResourceEntry(l)).ToList(); } } } private static void Write(IEnumerable<ResXResourceEntry> resources, string filePath) { lock (Lock) { using (var writer = new ResXResourceWriter(filePath)) { foreach (var resource in resources) { writer.AddResource(resource.Key, resource.Value); } } } } }
public class BuildManager { public string ProjectPath { get; private set; } public BuildManager(string projectPath) { ProjectPath = projectPath; } public void Build() { var regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0"); if (regKey == null) return; var msBuildExeFilePath = Path.Combine(regKey.GetValue("MSBuildToolsPath").ToString(), "MSBuild.exe"); var startInfo = new ProcessStartInfo { FileName = msBuildExeFilePath, Arguments = ProjectPath, WindowStyle = ProcessWindowStyle.Hidden }; var process = Process.Start(startInfo); process.WaitForExit(); } }
public class ResXResourceFileManager { public static readonly string BinPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase.Replace("file:///", "")); public static readonly string ResourcesPath = Path.Combine(BinPath, @"..\App_Data\Resources"); public static readonly string ResourceProjectPath = Path.Combine(ResourcesPath, "Resources.csproj"); public static readonly string DefaultsPath = Path.Combine(ResourcesPath, "Defaults"); public static void CopyDlls() { File.Copy(Path.Combine(ResourcesPath, @"bin\debug\Resources.dll"), Path.Combine(BinPath, "Resources.dll"), true); File.Copy(Path.Combine(ResourcesPath, @"bin\debug\fa\Resources.resources.dll"), Path.Combine(BinPath, @"fa\Resources.resources.dll"), true); Directory.Delete(Path.Combine(ResourcesPath, "bin"), true); Directory.Delete(Path.Combine(ResourcesPath, "obj"), true); } public static void RestoreAll() { RestoreDlls(); RestoreResourceFiles(); } public static void RestoreDlls() { File.Copy(Path.Combine(DefaultsPath, @"bin\Resources.dll"), Path.Combine(BinPath, "Resources.dll"), true); File.Copy(Path.Combine(DefaultsPath, @"bin\fa\Resources.resources.dll"), Path.Combine(BinPath, @"fa\Resources.resources.dll"), true); } public static void RestoreResourceFiles(string resourceCategory) { RestoreFile(resourceCategory.Replace(".", "\\")); } public static void RestoreResourceFiles() { RestoreFile(@"Global\Configs"); RestoreFile(@"Global\Exceptions"); RestoreFile(@"Global\Paths"); RestoreFile(@"Global\Texts"); RestoreFile(@"ViewModels\Employees"); RestoreFile(@"ViewModels\LogOn"); RestoreFile(@"ViewModels\Settings"); RestoreFile(@"Views\Employees"); RestoreFile(@"Views\LogOn"); RestoreFile(@"Views\Settings"); } private static void RestoreFile(string subPath) { File.Copy(Path.Combine(DefaultsPath, subPath + ".resx"), Path.Combine(ResourcesPath, subPath + ".resx"), true); File.Copy(Path.Combine(DefaultsPath, subPath + ".fa.resx"), Path.Combine(ResourcesPath, subPath + ".fa.resx"), true); } }
window.location.reload();