среда, 23 июля 2014 г.

Глобальная view model для представлений asp.net mvc

Прежде чем рассказывать о реализации глобальной view model в представлениях, поясню, зачем это нужно. При использовании технологии asp.net mvc для создания web-приложений существует возможность представлению (содержащему привычную для нас html – разметку) передать класс - модели, который генерируется в контроллере, и тогда это представление будет называться строготипизированным. Однако бывают случаи, когда в представление необходимо передать несколько моделей, что опять же, является тривиальной задачей (см. ViewData или PartialView). Но иногда бывают случаи, когда необходимо сделать одну общую модель для нескольких представлений, при этом они не должны перестать быть строготипизированными. Приведу пример из реального проекта, где это понадобилось. Итак, необходимо организовать проведение баллистических расчетов для различных космических аппаратов, которые находятся на обслуживании и выполняют различные задачи (рис.1).

При этом, нужно обеспечить как можно более простое добавление нового аппарата на обслуживание, и максимально увеличить число повторно используемых модуле (т.е. нужно писать код только в том случае, когда какие-либо характеристики аппарата являются действительно уникальными).

     Немного опишу конечную реализацию. После того, как оператор  выбирает конкретный аппарат, для которого он будет производить баллистические расчеты, необходимо отобразить действия, которые можно совершать с этим аппаратом (рис.2). Затем при выборе конкретного расчета загружается его представление, в котором необходимо задать необходимые настройки вычислительной операции.

     Так как необходимо выполнить требование по максимизации повторного использования модулей, упростить постановку нового КА на обслуживание, да и просто исключить дублирование кода, у различных космических аппаратов есть общие характеристики, применительно к баллистическим расчетам. Исходя из этих соображений было написано два базовых класса: BaseController – в нем собраны инструменты для работы с базой данных, логгер, и различные мапперы, которые будут использованы в классах – наследниках, и его наследник SpacecraftBaseController – в нем собраны типовые баллистические расчеты, которые характерны для всех типов космических аппаратов. Кроме этого было сделано layout представление для этих операций. Тут встала задача прописать в layout линки в зависимости от конкретного аппарата, т.е. добавить к action name, который не меняется, необходимый controller name аппарата с которым в данный момент работает оператор. Эту задачу можно решать по-разному, но я, наверно из-за своего опыта работы с wpf, решил сделать глобальный view model для layout представления, который, в дальнейшем, можно использовать и в локальных представлениях для операций.
     Начнем с MainSpacecraftViewModel, тут все просто:
public class MainSpacecraftLayoutViewModel
    {
        public string CotrollerName  { get; set; }
        public int Id { get; set; }
    }
Теперь SpacecraftBaseController, я покажу только то, что относится к статье:

public abstract class SpacecraftBaseController : BaseController
    {
        public MainSpacecraftLayoutViewModel MainSpacecraftLayoutViewModel { get; set; }  
        // Инициализирует MainSpacecraftLayoutViewModel с конкретными свойствами
               internal abstract void InitializeViewModel();
       }

Тут я думаю тоже все понятно, класс-наследник должен проинициализировать свойство MainSpacecraftLayoutViewModel:

public class ISSController : SpacecraftBaseController
    {
        internal override sealed void InitializeViewModel()
        {
            MainSpacecraftLayoutViewModel = new MainSpacecraftLayoutViewModel
            {
                CotrollerName = "ISS",
                Id = 1
            };
            ViewData["MainSpacecraftLayoutViewModel"] = MainSpacecraftLayoutViewModel;
        }
}

Затем его уже можно использовать в представлении layout:
@{
    Layout = null;
    var viewModel = (MainSpacecraftLayoutViewModel) ViewData["MainSpacecraftLayoutViewModel"];
    ...
}
    ...
<li><a href="@Url.Action("Predict", @viewModel.CotrollerName)">Прогноз</a></li>

Комментариев нет:

Отправить комментарий