اشتراک‌ها
استفاده از MVVM در ASP.NET Core

Open source MVVM framework for ASP.NET Core and OWIN 

View

@viewModel DotvvmDemo.CalculatorViewModel, Dotvvm
    
<p>
    Enter the first number: 
    <dot:TextBox Text="{value: Number1}" />
</p>
<p>
    Enter the second number: 
    <dot:TextBox Text="{value: Number2}" />
</p>
<p>
    <dot:Button Text="Calculate" Click="{command: Calculate()}" />
</p>
<p>
    The result is: {{value: Result}}
</p>

ViewModel

using System;
    
namespace DotvvmDemo 
{
    public class CalculatorViewModel 
    {
            
        public int Number1 { get; set; }
            
        public int Number2 { get; set; }
            
        public int Result { get; set; }
            
        public void Calculate() 
        {
            Result = Number1 + Number2;
        }
    }
}


استفاده از MVVM در ASP.NET Core
مطالب
قیود مسیریابی در 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 را مشاهده کنید.
اشتراک‌ها
ایجاد منوی پویا با استفاده از EF Code First و jQuery در MVC
در این مقاله یک منوی تک سطحی ساده ایجاد می‌شود که قادر به گروهبندی منوهای فرزند است که می‌توان نام منو و برچسب و اکشن مربوط به آن را در زمان اجرا، تعیین کرد. 
ایجاد منوی پویا با استفاده از EF Code First و jQuery در  MVC
نظرات مطالب
آشنایی با SplitQuery در EF Core 5x
اما به نظر بنده استفاده از SplitQuery زمانی میتونه مفیده باشه اگه تعداد رکوردهای جدول فرزند زیاد باشه و گرنه در غیر این صورت استفاده کردن از همون SingleQuery میتونه بهتر باشه
نظرات مطالب
کتابخانه GMap.Net
در ویرایش جدید کلاس Rect را که فرزند کلاس Gmap.net.Overlays.Rectangle است قرار دادیم تا مشکل و تصادمی با کلاس System.Drawing.Rectangle نداشته باشد.
مطالب
امکان تعریف ویژگی‌ها بر روی توابع محلی در C# 9.0

یکی از ویژگی‌های جدید اضافه شده به سی شارپ 9، Attributes on local functions نام دارد و این توانایی را به ما می‌دهد تا بر روی متد‌های محلی که درون متدها تعریف می‌شوند، Attributes قرار دهیم. قابلیت local functions در نسخه 7 سی شارپ اضافه شده‌است و با استفاده از این قابلیت می‌توانیم درون یک متد، تابع دیگری را تعریف کنیم و در همان متد، از آن تابع درونی استفاده کنیم. در واقع تابع درونی، لوکال متد بیرونی است و در خارج از متد بیرونی، قابل دسترسی نیست. مانند مثال زیر:

    // Main method 
    public static void Main()
    {
        // Local Function 
        void AddValue(int a, int b)
        {
            Console.WriteLine("Value of a is: " + a);
            Console.WriteLine("Value of b is: " + b);
            Console.WriteLine("Sum of a and b is: {0}", a + b);
            Console.WriteLine();
        }

        // Calling Local function 
        AddValue(20, 40);
        AddValue(40, 60);
    }

برای بررسی این ویژگی جدید سی شارپ 9.0، از یک مثال استفاده می‌کنیم. فرض کنید یک برنامه‌ی کنسول را داریم و می‌خواهیم یک قطعه کد فقط در حالتی در خروجی نوشته شود که برنامه در حالت دیباگ اجرا شده باشد و اگر در حالت ریلیز باشد، در خروجی مشاهده نشود. قبل از نسخه‌ی 9.0 سی شارپ، مجبور هستیم از directive های کامپایلر زبان استفاده کنیم و از طریق آن به کامپایلر بفهمانیم که چه زمانی این قطعه کد را کامپایل کند. مانند مثال زیر:

        static void Main(string[] args)
        {
            static void DoAction()
            {
                // DoAction

                Console.WriteLine("DoAction...");
            }

#if DEBUG
            DoAction();
#endif
        }

اما با استفاده قابلیت اضافه شده‌ی در این نسخه از سی شارپ، می‌توان روی متدهای محلی هم Attributes اضافه کرد. پس می‌توانیم از ConditionalAttribute استفاده کنیم و آن را در بالای متد محلی قرار دهیم و از کامپایلر بخواهیم در حالت دیباگ اجرا شود. مانند کد زیر

        static void Main(string[] args)
        {
            [Conditional("DEBUG")]
            static void DoAction()
            {
                // Do Action Here

                Console.WriteLine("Do Action...");
            }

            DoAction();
        }

اگر بر روی متدهای محلی C# 8.0 از Attribute استفاده کنیم، با خطای زیر روبرو می‌شویم:

ErrorCS8400Feature 'local function attributes' is not available in C# 8.0. Please use language version 9.0 or greater.
پاسخ به بازخورد‌های پروژه‌ها
SettingService
این مقالتون رو هم خوندم عالی بود .

منظورم این بود وقتی با الگوی UnitOfWork ترکیبش کردید .یکسری توابع مثل 

        public Task<T> LoadSetting<T>() where T : ISettings, new()
        {
            throw new NotImplementedException();
        }
استفاده کردید . که مثل اینکه جوابگوی این مدل تنظیمات برای ذخیره سازی نیست .
میشه روش استفاده یا حتی پیاده سازی یکی از این توابع رو بگید 
نظرات مطالب
PersianDateTime جایگزینی برای System.DateTime
این تمام کد برنامه است :
using System;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //  این قسمت برای ورود اطلاعات به بانک است و با کمک کتابخانه پرژن دات نت  تاریخ شمسی را به میلادی تبدیل و ذخیره میکنم
            using(var db = new h7Entities())
            {
                var t = new test
                {
                    ResponseDate = PersianDateTime.Parse(textBox1.Text).ToDateTime()
                };
                db.test.Add(t);
                db.SaveChanges();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // این قسمت هم فقط اطلاعات واکشی شده را در گرید نمایش میدهد . بدون هیچ شرطی ، یک سلکت ساده . . فقط از پرژن دانت نت برای تبدیل میلادی به شمسی کمک میگیرم
            using (var db = new h7Entities())
            {
                dataGridView1.DataSource =(from t in db.test
                                              select  new
                                              { 
                                                  Id= t.Id,
                                                  time = new PersianDateTime(DateTime.Parse(t.ResponseDate.ToString())).ToString(PersianDateTimeFormat.DateShortTime)
                                              }).ToList();                
            }

        }
    }
}

کتابخانه PersianDateTime  را از نیوگت دریافت کردم .
ولی چیزی در گرید نمایش نمیدهد .

مدل برنامه هم :

 public partial class test
    {
        public int Id { get; set; }
        public Nullable<System.DateTime> ResponseDate { get; set; }
    }


سوال دیگه اینکه وقتی تبدیلی انجام نمی‌شود ، خروجی زیر را دارم :


حالا چطور از فیلدی که تاریخ را نمایش میدهد فقط آن را تبدیل به شمسی و نمایش دهد ؟ شبیه این  1365/02/02    ؟
تشکر