Full Stack ASP.NET Core 2.0 MVC Forum Build
Topics Covered:
- Setting up a new ASP .NET Core 2.0 MVC web application with Identity user authentication in Visual Studio
- Separating Web, Services, and Data Access Layers in our solution
- Setting up tests with NUnit and .NET Core virtual in-memory database
- Debugging / Fixing bugs
- Implementing the MVC (Model-View-Controller) pattern
- Dependency Injection of Services into our Controllers
- Using input forms to pass data from our Views to our Controllers
- Azure file storage for Profile Image uploads
- Azure SQL database hosting
- SQL Database seeding for starting the application with a super-user
- Code-first database migrations
- Writing SQL queries to inspect data in our database
- Deploying the application to Azure.
با بالا رفتن تعداد اکشن متدهای یک پروژه، ممکن است استفاده از ValidateAntiForgeryToken فراموش شود. در ادامه مثالی را ملاحظه میکنید که یک پروژهی ASP.NET MVC را جهت یافتن اکشن متدهای Post ایی که فیلتر ValidateAntiForgeryToken ندارند، اسکن میکند:
using System; using System.Linq; using System.Reflection; // Add a ref. to \Program Files\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies\System.Web.Mvc.dll using System.Web.Mvc; // Add a ref. to System.Web using System.Web.UI; namespace FindOutputCaches { class Program { static void Main(string[] args) { var path = @"D:\path\bin\site.dll"; var asmTarget = Assembly.LoadFrom(path); checkCsrfTokens(asmTarget); Console.WriteLine("Press a key..."); Console.Read(); } private static void checkCsrfTokens(Assembly asmTarget) { // یافتن کلیه کنترلرها var controllers = asmTarget.GetTypes() .Where(type => typeof(IController).IsAssignableFrom(type) && !type.Name.StartsWith("T4MVC")) .ToList(); foreach (var controller in controllers) { // یافتن کلیه اکشن متدهای کنترلر جاری var actionMethods = controller.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(method => typeof(ActionResult).IsAssignableFrom(method.ReturnType)) .ToList(); foreach (var method in actionMethods) { var httpPostAttributes = method.GetCustomAttributes(typeof(HttpPostAttribute), true); if (httpPostAttributes == null || !httpPostAttributes.Any()) continue; var csrfTokens = method.GetCustomAttributes(typeof(ValidateAntiForgeryTokenAttribute), true); if (csrfTokens == null || !csrfTokens.Any()) { Console.WriteLine("Detected [HttpPost] without [ValidateAntiForgeryToken] in:\n {0}-->{1}", controller.FullName, method.Name); } } } } } }
سپس در این اسمبلی، کلیه نوعهای تعریف شده، یافت گردیده و آنهایی که پیاده سازی کننده IController هستند (یعنی کلاسهای کنترلر واقعی برنامه)، جدا خواهند شد.
در ادامه در این کنترلرها، متدهایی را بررسی خواهیم کرد که دارای خروجی از نوع ActionResult باشند (فقط اکشن متدها مدنظر هستند). اگر این اکشن متد یافت شده دارای ویژگی HttpPost بود و همچنین ValidateAntiForgeryToken نداشت، یعنی یک مشکل امنیتی که باید برطرف شود.
In this video Anders Hejlsberg spends some time discussing TypeScript. He starts with the reasons behind creating TypeScript (the so called elevator speech) and then moves on to some of the features coming in the next release. He mentions a number of features but spends the time discussing the null (and corresponding undefined) types and how TypeScript 2 makes handling them much easier.
برای رفع این نقیصه با استفاده از قطعه کد زیر میتوان کلیه کوئری استرینگهای صفحه را یافت و به شیءایی به نام urlParams به صورت خاصیت اضافه کرد:
var urlParams; (window.onpopstate = function () { var match, pl = /\+/g, // Regex for replacing addition symbol with a space search = /([^&=]+)=?([^&]*)/g, decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }, query = window.location.search.substring(1); urlParams = {}; while (match = search.exec(query)) urlParams[decode(match[1])] = decode(match[2]); })();
$.ajax({ type: "POST", url: "@sortUrl", data: JSON.stringify({ items: items, surveyId: surveyId }),
function jsonConcat(defaults, options) { /* merge defaults and options, without modifying defaults */ return $.extend({}, defaults, options); }
var ajaxData = { items: items, surveyId: surveyId }; $.ajax({ type: "POST", url: "@sortUrl", data: JSON.stringify(jsonConcat(ajaxData,urlParams)),
در طراحی مدل دامین، بیشتر مواقع از نوعهای اولیه مانند int , string,… استفاده میکنیم و به عبارتی میتوانیم بگوییم در استفاده از این نوع داده وسواس داریم. قطعه کد زیر را در نظر بگیرید:
public class UserFactory { public User CreateUser(string email) { return new User(email); } }
اگر به خاطر داشته باشید، در قسمتهای قبلی در مورد مفهومی به نام Honesty صحبت کردیم. به طور ساده باید بتوانیم از روی امضای تابع، کاری را که تابع انجام میدهد و خروجی آن را ببینیم. این تابع Honest نیست؛ شرایطی که string میتواند درست نباشد، خالی باشد، طول غیر مجاز داشته باشد و ... را نمیتوانیم از امضای تابع حدس بزنیم.
جواب خیلی سادهاست؛ شما نیاز دارید تا یک Type اختصاصی را ایجاد کنید. برای مثال بجای استفاده از نوع string برای یک ایمیل، میتوانید یک کلاس را به عنوان Email ایجاد کنید که مشخصهای به نام Value دارد. این کار به روشهای مختلفی قابل انجام است؛ اما پیشنهاد من استفاده از این روش هست:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace ValueOf { public class ValueOf<TValue, TThis> where TThis : ValueOf<TValue, TThis>, new() { private static readonly Func<TThis> Factory; /// <summary> /// WARNING - THIS FEATURE IS EXPERIMENTAL. I may change it to do /// validation in a different way. /// Right now, override this method, and throw any exceptions you need to. /// Access this.Value to check the value /// </summary> protected virtual void Validate() { } static ValueOf() { ConstructorInfo ctor = typeof(TThis) .GetTypeInfo() .DeclaredConstructors .First(); var argsExp = new Expression[0]; NewExpression newExp = Expression.New(ctor, argsExp); LambdaExpression lambda = Expression.Lambda(typeof(Func<TThis>), newExp); Factory = (Func<TThis>)lambda.Compile(); } public TValue Value { get; protected set; } public static TThis From(TValue item) { TThis x = Factory(); x.Value = item; x.Validate(); return x; } protected virtual bool Equals(ValueOf<TValue, TThis> other) { return EqualityComparer<TValue>.Default.Equals(Value, other.Value); } public override bool Equals(object obj) { if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; return obj.GetType() == GetType() && Equals((ValueOf<TValue, TThis>)obj); } public override int GetHashCode() { return EqualityComparer<TValue>.Default.GetHashCode(Value); } public static bool operator ==(ValueOf<TValue, TThis> a, ValueOf<TValue, TThis> b) { if (a is null && b is null) return true; if (a is null || b is null) return false; return a.Equals(b); } public static bool operator !=(ValueOf<TValue, TThis> a, ValueOf<TValue, TThis> b) { return !(a == b); } public override string ToString() { return Value.ToString(); } } }
public class EmailAddress : ValueOf<string, EmailAddress> { }
EmailAddress emailAddress = EmailAddress.From("foo@bar.com");
public class Address : ValueOf<(string firstLine, string secondLine, Postcode postcode), Address> { }
روش معرفی شدهی در این مقاله، صرفا جهت آشنایی بیشتر شما و داشتن کدی تمیزتر از طریق مفاهیم برنامه نویسی تابعی خواهد بود. در دنیای واقعی، احتمالا مسائلی را برای ذخیره سازی این آبجکتها و یا کار با کتابخانههایی مانند Entity Framework خواهید داشت که به سادگی قابل حل است.
در صورتیکه مشکلی در پیاده سازی داشتید، میتوانید مشکل خود را زیر همین مطلب و یا بر روی gist آن کامنت کنید.
Visual Studio 17.8 منتشر شد
The latest update for Visual Studio 2022 is officially out. Offering a comprehensive suite of enhancements that span productivity, programming languages, and enterprise management, this general release is a monumental step forward. Developed with extensive user feedback, this version is fully compatible with .NET 8, which is also generally available as of today.