بازیابی وضعیت View Model

یکشنبه 5 اردیبهشت 1395

در این مقاله الگویی را که در وب سایت های MVC کلاسیک بکاربرده می شد بررسی خواهیم کرد که مشکل پر شدن ویژگیهای View Model را که از طریق درخواست های http ارسال نخواهند شد را حل میکند.

بازیابی  وضعیت View Model

در این مقاله الگویی را که در وب سایت های MVC کلاسیک بکاربرده می شد بررسی خواهیم کرد که مشکل پر شدن ویژگیهای   View Model را که از طریق درخواست های  http ارسال نخواهند شد را حل میکند.

بیشتر ویژگی های مدل به دو دسته تقسیم می شوند :

    . Domain Properties که مدل را مشخص و توصیف میکند.

    . Additional Properties که ویژگیهای دامنه یا همان  Domain Properties را توصیف میکند.

public class Account
{
    // Domain property
    public int CountryId { get; set; }

    // Additional property
    public IEnumerable<KeyValuePair<int, string>> Countries { get; set; }

Domain Properties به منطق اضافی نیاز ندارد و با پاسخ http می آید و آن را با استفاده از درخواست  http  ارسال میکینم.  Additional Peroperties باعث بروز مشکل می شود زیرا نمیتوان آنها را همراه با ویژگی های دامنه ارسال کرد. ویژگیهای اضافی یا Additional Properties بخشی از مدل دامنه نیستند و می توانند بزرگتر باشند. این ویژگیها نمی توانند توسط درخواست به برنامه بیایند بنابراین خالی هستند. در نتیجه نمی توانیم ویژگیهای دامنه را با استفاده از ویژگیهای اضافی اعتبارسنجی کنیم (مثلا کشور انتخاب شده یکی از کشورهای موجود باشد). زمانی که مدل ویژگیهای اضافی دارد باید در طول پردازش فرم درخواست پر شوند.

پس هر دفعه که یک مدل ایجاد میکنیم به پر کردن ویژگیهای اضافی آن نیاز داریم. یک راه حل ساده برای آن، قرار دادن منطق پر کردن در کنترلر است. اما با انجام این کار ، کد تکراری در یافت میکنیم. منطق پر کردن را هم در جایی داریم که View  نمایش داده می شود و هم در action که فرم درخواست ها را رسیدگی میکند. یک کلاس جداگانه برای منطق پر کردن در نظر میگیریم که مسئولیت پر کردن ویژگی های اضافی را دارد.

public class AccountFiller : IViewModelFiller<Account>
{
    public void Fill(Account model) {
        model.Countries = Countries.GetAvailable();
    }
}

همانطور که قبلا گفته شد قصد داریم مدل را در دو محل پر کنیم. در کنترلر هنگامی که مدل را ایجاد میکنیم، و در model binder  هنگامی که مقادیر فرم را به مدل متصل میکنیم. در Model binder مدل را قبل از اعتبار سنجی پر میکنیم. پس می توانیم از ویژگیهای اضافی هنگام اعتبار  سنجی استفاده کنیم(با استفاده از  FluentValidation). 

// ...somewhere in controller
public  ActionResult Account() {
    var account = new Account { CountryId = 1 };

    _accountFiller.Fill(account);

    return View(account);
}

public class AccountModelBinder : DefaultModelBinder
{
    private readonly IViewModelFiller<Account> _filler;

    public AccountModelBinder(IViewModelFiller<Account> filler) {
        _filler = filler;
    }

    protected override void OnModelUpdated(ControllerContext controllerContext, 
        ModelBindingContext bindingContext) {
        var model = (Account)bindingContext.Model;

        _filler.Fill(model);
       
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

این الگو هنگامی که DI و  FluentValidation استفاده می شوند بهتر کار میکند. تکراری بودن کدها را کاهش می دهد به کم شدن کدها کمک میکند و معماری قابل تست آن به آسانی گسترش پیدا میکند.

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید