اشتراک‌ها
ساعت Bézier

طراحی یک ساعت با منحنی‌های Bézier 

ساعت Bézier
مطالب
قیود مسیریابی در ASP.NET Core
Route Constraints قابلیتی است در ASP.NET Core که با استفاده از آن میتوانید از رسیدن مقادیر نامعتبر به پارامترهای Action متد یک Controller جلوگیری کنید.
بعنوان مثال میتوانید محدودیتی قرار دهید که Routing فقط زمانی انجام شود که پارامتر وارد شده توسط کاربر، از جنس int باشد:
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    [HttpGet("{id:int}")]
    public IActionResult Get(int id)
    {
        return Ok(id);
    }
}
با قرار دادن یک Break-point در ابتدای اکشن متد، اگر سعی کنید این اکشن متد را با یک alpha string فراخوانی کنید، خواهید دید که به Break-point نرسیده و عمل Routing انجام نمیشود. اما اگر با یک عدد فراخوانی شود، Routing با موفقیت انجام شده و عدد ورودی در نتیجه، به شما بازگردانده میشود که نشان میدهد Constraint به درستی عمل کرده است.
  api/values/hi
✓    api/values/7
شاید بپرسید تفاوت این روش، با کد زیر چیست:
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        // id is 0 here if you pass string.
        return Ok(id);
    }
}  
در اینجا اگر بعنوان پارامتر ورودی، یک alpha string دهید، Routing انجام میشود، اما چون ورودی int نیست، مقدار id با 0 پر خواهد شد.
 api/values/hi
✓  api/values/7

2 روش برای اعمال Route Constraint‌ها بر روی URL Parameter‌ها وجود دارند که در ادامه به آن‌ها می‌پردازیم.


1- Inline Constraints

این نوع Constraint‌ها بعد از URL Parameter قرار گرفته و با استفاده از Colon از هم جدا میشوند:
app.UseMvc(routes =>
{
    routes.MapRoute("Values",
        "api/values/{id:int}",
        new { controller = "Values", action = "Get" });
});
همچنین میتوانید چندین Constraint را باهم ترکیب کنید و محدود به یک Constraint نیستید:
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    [HttpGet("{name:minlength(2):maxlength(10):alpha}")]
    public IActionResult Get(string name)
    {
        return Ok(name);
    }
}
✖  api/values/M
✖  api/values/1234
✖  api/values/abcdefghijk
✓  api/values/Moien

2- MapRoute's Constraints Argument

همه‌ی Constraint‌ها کلاسی هستند که اینترفیس IRouteConstraint را پیاده سازی کرده‌اند. داخل MapRoute میتوانید بطور مستقیم این کلاس‌ها را بعنوان Constraint معرفی کنید:
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "Values",
        template: "api/values/{name}",
        defaults: new { controller = "Values", action = "Get" },
        constraints: new
        {
            name = new CompositeRouteConstraint(new List<IRouteConstraint>
            {
                new AlphaRouteConstraint(),
                new MinLengthRouteConstraint(2),
                new MaxLengthRouteConstraint(10)
            })
        });
});
* این روش در Attribute Routing قابل پیاده سازی نیست.


ایجاد یک Constraint سفارشی

همانطور که قبل‌تر گفتیم، همه‌ی Constraint‌ها کلاسی هستند که اینترفیس IRouteConstraint را پیاده سازی کرده‌اند. بنابراین میتوانیم با پیاده سازی این اینترفیس، یک Constraint سفارشی را ایجاد کنیم.
در اینجا قصد داریم Constraint ای را ایجاد کنیم که یک string را به عنوان ورودی دریافت و متد StartsWith را بر روی آن انجام دهد و در صورت true بودن، Routing انجام شود:
public class StartsWithConstraint : IRouteConstraint
{
    public StartsWithConstraint(string startsWith)
    {
        if (string.IsNullOrWhiteSpace(startsWith))
            throw new ArgumentNullException(nameof(StartsWith));
        StartsWith = startsWith;
    }

    private string StartsWith { get; }

    public bool Match(HttpContext httpContext,
        IRouter route,
        string parameterName,
        RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        if (parameterName == null)
            throw new ArgumentNullException(nameof(parameterName));

        if (values == null)
            throw new ArgumentNullException(nameof(values));

        if (!values.TryGetValue(parameterName, out var value) || value == null) 
            return false;

        string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
        return valueString.StartsWith(StartsWith);
    }
}
همانطور که می‌بینید، به راحتی با پیاده سازی متد Match میتوانید شرط مورد نظر خود را اعمال کنید. بعد از ایجاد Constraint سفارشی خود، باید آن را داخل ConfigureServices برنامه Register کنید:
services.Configure<RouteOptions>(opt =>
opt.ConstraintMap.Add("startsWith", typeof(StartsWithConstraint)));
و در نهایت با نامی که هنگام Register کردن دادید ( در اینجا startsWith )، از آن استفاده کنید:
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    [HttpGet("{name:minlength(2):maxlength(10):alpha:startsWith(Mo)}")]
    public IActionResult Get(string name)
    {
        return Ok(name);
    }
}
api/values/Ali
api/values/Moien
✓ api/values/Morteza

در اینجا می‌توانید لیستی از Constraint‌های پیشفرض پیاده سازی شده در ASP.NET Core را مشاهده کنید.
نظرات مطالب
جایگزینی اسکریپت‌های WebResource.axd با فایل‌های استاتیک در ASP.NET Web forms
روزهای اولی که همه می‌رن سراغ وب فرم، دوست دارند همه چیز را داخل اسمبلی‌ها قرار دهند. فکر می‌کنند اینطوری بهتر است. بعد متوجه می‌شوند که به روز رسانی آن‌ها سخت می‌شود، WebResource.axd‌های طولانی مشکل‌زا درست می‌کند (مطلب جاری) و از همه مهم‌تر تعداد ارجاعاتی که در یک صفحه اضافه می‌شوند، زیاد هست و روی کارآیی سایت تاثیر منفی می‌گذارد (تعداد رفت و برگشت‌های زیادی را به سرور برای دریافت فایل‌های هر صفحه ایجاد می‌کند). بعد به این نتیجه می‌رسند که بد نیست این فایل‌ها را با هم یکی کنیم؟ (داخل یک اسمبلی گذاشتن به معنای یکی کردن فایل‌ها نیست) فشرده سازی خود فایل‌ها با حذف فواصل یا کوتاه کردن نام متغیرها چطور؟ اگر در این بین، سرور این‌ها را به صورت gzip ارائه دهد که خیلی خوب خواهد شد. اگر هدر کش کردن به مدت یکسال را هم در سمت کلاینت اضافه کنیم که عالی و به علاوه اگر فایلی در سمت سرور به روز شد، به صورت خودکار این کش دیگر قابل استفاده نباشد و به روز شود. اینجا است که سیستم bundling & minification دات نت متولد می‌شود. هم در MVC قابل استفاده است و هم در وب فرم‌ها. بنابراین طراحی سیستمی بهینه جهت ارائه اسکریپت‌ها و شیوه‌نامه‌ها، فراتر است از صرفا قرار دادن چند فایل در یک اسمبلی و ارائه خام آن‌ها.
نظرات مطالب
AngularJS #1
اغلب کارمندان یک سازمان یک عادت عمومی دارند، بر روی لینکشان کلیک راست می‌کنند و گزینه‌ی open in a new tab را می‌زنند و یا بدتر از کلید‌های back و forward مرورگر برای عقب جلو کردن صفحات پیمایش شده استفاده میکنند.
حالا هر چقدر که توی گوششان بخوانید، که فلان لینک را باید روش فقط کلیک کنی، باز هم به خرجشان نمی‌رود.
خیلی از کارمندان برای مثال لینک درج صورت حساب جدید را bookmark کرده اند تا به سرعت به آن دسترسی داشته باشند. همچنین autocomplete مرورگر هم در یافتن صفحات پیمایش شده به آن‌ها خیلی کمک می‌کند.
یادمه همین مشکل را توی یک برنامه‌ی نوشته شده با سیلورلایت دیدم و مشتری قبول نمی‌کرد که نمی‌تواند در یک tab جدید صفحه باز کند و ...
برنامه‌های شبیه دسکتاپ یعنی اینکه رفرش شدن صفحات را برای تغییر view از بین ببرد. هوز هم ماهیت وب است و باید همیشه این را در نظر داشت، تا بهترین تجربه‌ی رابط کاربری را فراهم کرد. نباید گفت که برنامه‌ی من فلان جور طراحی شده؛ همینی هست که هست، باید با رابط کاربری عموم وب اینترفیس‌ها هماهنگ باشد.