ASP MVC 2 Шаблон для реализации команд в стиле CanExecute - PullRequest
4 голосов
/ 08 августа 2011

Я пришел из фона WPF (MVVM) и пытаюсь перейти на MVC 2. Есть ли в MVC2 шаблон, в котором вы можете использовать кнопки командования / команды, такие как <input>, которые вы используете для отправки формы, чтобы вы могли скрыть/ отключить при попытке сделать вид.

В мире MVVM ваши команды могут реализовывать интерфейс ICommand, и у него есть метод CanExecute, который был весьма полезен.Мне было интересно, есть ли что-нибудь подобное в ASP MVC 2?

Единственный способ, о котором я могу подумать, - это сделать это в представлении, чтобы я мог проверить флаг в ViewModel (CanSave) и в зависимости от этого показать / скрыть тег <input>.

По сути, я хочу, чтобы работали 2 версии сайта, одна в режиме только для чтения, а другая в режиме редактирования.

Дайте мне знать, если вам нужны какие-либо разъяснения.

Ответы [ 4 ]

2 голосов
/ 21 августа 2011

ASP.NET MVC не имеет понятия «элементы управления», как это встречается в классических ASP.NET и WPF. Основополагающими блоками ASP.NET MVC являются элементы HTML, такие как <input>, <button> и так далее. Естественно, они не предлагают нужную вам функциональность (т. Е. Реализацию интерфейса ICommand).

Сценарий, на который вы смотрите (то есть два режима вашей формы), может (и, возможно, должен быть ) рассматриваться на уровне просмотра. Вы уже находитесь в правильном направлении: установите свойство CanSave на своей модели и используйте его в представлении, чтобы определить, что генерируется.

Пример:

<% if (Model.CanSave)
    { %>
        <p>First Name: <%= Html.TextBox("firstname", Model.firstname) %> </p>
<%  }
    else
    { %>
        <p>First Name: <%=Model.firstname %></p>
<%  } %>

Возможно, вы захотите проверить DisplayTemplates и EditorTemplates ..., которые очень удобны для этого сценария. Брэд Уилсон делает хорошую работу здесь .

Это поможет вам перейти к этому:

<%= (Model.CanSave) ? Html.EditorFor(x => x.firstname) : Html.DisplayFor(x => x.firstname) %>

... что делает ваш вид чистым и красивым.

1 голос
/ 19 августа 2011

Если вы не можете заставить MVC сделать это, то стоит написать что-то вроде этого псевдокода в стиле vb. Это включает в себя ...

Подклассы управления.

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

Interface BaseUIControl
    Property Enabled as Boolean
    Property Visible as Boolean
    Property Name as String
    Property EntireStateAsXML as string ' You can use this to do EVERYTHING!        

Interface UserActionItem
    Event Clicked(sender as UserActionItem ... don't pass anything from UI namespaces!)

Class MyButton (or link, etc.) Implement BaseUIControl, UserActionItem Inherits UI.Button

Как это помогает? Вы в основном заменили недостающую функциональность. Ваш контроллер (или даже прикладной уровень) может знать о компонентах пользовательского интерфейса только по интерфейсу, поэтому им не нужно будет видеть типы пользовательского интерфейса.

подробнее ...

Вы можете использовать эту философию для управления всем . Это сэкономило мне тысячи часов кода обезьяны.

Interface TextControl
    Property Value as text

Interface CheckControl 
    Property Checked as boolean 

Вышеупомянутые два довольно просты - вы наследуете MyCheckBox и MyTextBox от версий пользовательского интерфейса и реализуете соответствующие.

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

Interface ValidationBase
    Property Required as Boolean

Если у вас есть текстовая или числовая маска или ограничения, встроенные в 2 подкласса ...

Interface ValidationNumeric           
    Property MinVal, MaxVal as double 

Interface ValidationText
    Property MinLen, MaxLen as double 

Нет, он не пойдет в базу данных для вас. Но это подметает тонну грязи под ковром.

Вы даже можете установить эти значения свойств в конструкторе пользовательского интерфейса - да, если поместить BL в кровать с пользовательским интерфейсом, НО, если у вас только один пользовательский интерфейс для BL, на самом деле работает очень хорошо.

Теперь изобразите пользовательский интерфейс со множеством вещей, таких как список / мультиселект, элементы управления выбора двойного списка, флажок списка, групповой блок кнопок / флажков ...

Interface Selector
    property Items as list (of string) 
    property SelectedItems as list (of string)

Используйте то, что работает в пользовательском интерфейсе - ваши общие процедуры могут не заботиться о том, как они выглядят !! Подклассы UI просто реализуют их, чтобы установить / получить правильные значения.

Кроме того ... мы добавили 'validationEquation', ActivatesEquation (серый / ungray), SetValueTriggerEquation (если true, установите значение SetValueEquation, в противном случае оставьте в покое), что позволило элементам управления устанавливать простые значения из других элементов ( в основном, получая значения из связанных объектов, как будто используя отражение) через Expression Evaluator Паскаля Гаяне (он читает .net types!)

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

Это невероятно насколько это упрощает сложное приложение. У нас есть одна с 1200+ панелями ввода данных (... страницы ... у нас это приложение для толстых клиентов), которые заполняют 250 различных бумажных форм по 250K LOC. Определения формы содержат «имя» каждого элемента управления, и оно извлекается из XML, созданного на экранах. Мы, вероятно, сохранили 500K LOC, так как на многих экранах нет кода или только тривиальный код; вся привязка данных, проверка и т. д. обрабатываются общими процедурами, которые ссылаются на интерфейсы.

Как я уже сказал, это работает только для большого приложения. Потратьте хотя бы 2-3 недели на разработку 90% функциональности; вероятно, еще один месяц в течение 2 лет созревания. Я предполагаю, что ваши приложения большие, если вы заботитесь об ICommand и его удобствах. Я бы поставил окупаемость на 15-20 умеренно сложных страницах.

1 голос
/ 20 августа 2011

Если я правильно понимаю вопрос, вы можете написать ControllerCommand класс для инкапсуляции этого.Примерно так:

public class ControllerCommand
{
    public string Action { get; set; }
    public string Controller { get; set; }
    public object RouteValues { get; set; }
    public bool IsEnabled { get; set; }
}

Модель представления Your Details может использовать его следующим образом:

public class DetailsModel
{
    public guid Id { get; set;}
    // some other viewmodel properties
    public ControllerCommand Edit { get; set; }
}

Вы можете написать методы расширения на HtmlHelper для замены встроенных:

public MvcHtmlString CommandLink(this HtmlHelper html, string linkText, ControllerCommand command, object htmlAttributes)
{
    if (command.IsEnabled)
    {
        return html.ActionLink(linkText, command.Action, command.Controller, command.RouteValues, htmlAttributes);
    }
    else
    {
        return MvcHtmlString.Create(linkText);
        // perhaps return <span class="disabled-command">linkText</span>
    }
}
0 голосов
/ 16 августа 2011

Один из найденных мною способов - использовать атрибуты Filter, которые вы можете добавить в свои действия, но которые обрабатывают только CanExecute на стороне сервера.

Для стороны с графическим интерфейсом невозможно найти лучший способ, чем установка операторов If для проверки того, имеет ли пользователь полномочия на выполнение определенного действия (например, кнопки «Изменить / Удалить»)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...