MVC строго типизированный вид и настройки на стороне сервера перед отправкой на нижние уровни?

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

Команда выглядит так:

public class RegisterUserCommand : CommandBase
{
    public string UserName { get; set; }
    public string Email{ get; set; }
    public DateTime RegistrationDate { get; set; }
    public string ApiKey {get; set;} // edit
}

В этом классе нет логики, только данные.

Я хочу, чтобы пользователи вводили свое имя пользователя, адрес электронной почты, и я хочу, чтобы система использовала текущую дату для создания команды.

Что лучше между:

  1. создать строго типизированное представление на основе RegisterUserCommand, а затем ввести дату и ключ APi непосредственно перед отправкой на бизнес-уровень?

  2. создать класс RegisterUserViewModel, создать представление с этим классом и создать объект команды на основе ввода представления?

Я написал следующий код (для решения № 2):

public class RegisterController : Controller
{
    //
    // GET: /Register/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(RegisterUserViewModel registrationData)
    {

        var service = NcqrsEnvironment.Get<ICommandService>();
        service.Execute(
            new RegisterUserCommand
            {
                RegistrationDate = DateTime.UtcNow,
                Email= registrationData.Email,
                UserName= registrationData.Name,
                ApiKey = "KeyFromConfigSpecificToCaller" // edit
            }
            );

        return View();
    }


    public class RegisterUserViewModel
    {
        [Required]
        [StringLength(16)]
        public string Name { get; set; }
        [Required]
        [StringLength(64)]
        public string Email{ get; set; }
    }
}

Этот код работает... но мне интересно, если я выберу правильный путь...

спасибо за советы

[Edit] Поскольку Datetime, похоже, вызывает недоразумение, я добавил еще одно свойство "ApiKey", которое также должно быть установлено на стороне сервера, из веб-слоя (не из командного уровня)

[Правка 2] попробуйте предложение Эрика и реализуйте первое решение, которое я себе представил:

[HttpPost]
public ActionResult Index(RegisterUserCommand registrationCommand)
{

    var service = NcqrsEnvironment.Get<ICommandService>();
    registrationCommand.RegistrationDate = DateTime.UtcNow;
    registrationCommand.ApiKey = "KeyFromConfigSpecificToCaller";
    service.Execute(
        registrationCommand
        );

    return View();
}

... это приемлемо?

3 ответа

Решение

Я думаю, что вам будет лучше с вариантом № 2, где у вас будет отдельная ViewModel и команда. Хотя это может показаться избыточным (в некоторой степени), ваши команды на самом деле являются сообщениями от вашего веб-сервера вашему обработчику команд. Эти сообщения не могут быть отформатированы так же, как ваша ViewModel, и не должны. И если вы используете NCQRS как есть, вам придется сопоставить свои команды с вашими методами и конструкторами AR.

Хотя это может сэкономить вам немного времени, я думаю, что вы будете готовы к моделированию своего домена после моделей ViewModels, и это не должно иметь место. Ваши ViewModels должны быть отражением того, что ваш пользователь испытывает и видит; Ваш домен должен отражать ваши бизнес-правила и знания и не всегда отражаться в вашем представлении.

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

Надеюсь, это поможет. Удачи!

Я бы использовал номер 1 и использовал http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute.aspx для проверки.

Я создал пример (ответ) для еще одного вопроса здесь.

Это позволяет вам хранить вашу модель в другой библиотеке, проверять поля и показывать поля, как если бы вы использовали внутренние / частные классы с DataAnnotations. Я не большой поклонник создания совершенно отдельного класса для представления, которое не имеет дополнительной ценности при необходимости возвращать данные в другой класс. (Если бы у вас были дополнительные значения, такие как значения выпадающего списка или значения по умолчанию, я думаю, что это имело бы смысл).

Вместо

[HttpPost]
public ActionResult Index(RegisterUserViewModel registrationData)
{

    var service = NcqrsEnvironment.Get<ICommandService>();
    service.Execute(
        new RegisterUserCommand
        {
            RegistrationDate = DateTime.UtcNow,
            Email= registrationData.Email,
            UserName= registrationData.Name,
            ApiKey = "KeyFromConfigSpecificToCaller" // edit
        }
        );

    return View();
}

Вы можете иметь

[HttpPost]
public ActionResult Index(RegisterUserCommand registrationData)
{

    var service = NcqrsEnvironment.Get<ICommandService>();

    registrationData.ApiKey = "KeyFromConfigSpecificToCaller";

    service.Execute(registrationData);

    return View();
}

Я бы порекомендовал поместить это в конструктор класса RegisterUserCommand. Таким образом, по умолчанию всегда устанавливается значение DateTime.UtcNow, и, если вам нужно явно установить что-либо, вы можете просто добавить его в инициализатор объекта. Это также поможет в тех случаях, когда вы используете этот класс в других частях вашего проекта, и вы забыли явно указать RegistrationDate.

public class RegisterUserCommand : CommandBase
{
    public string UserName { get; set; }
    public string Email{ get; set; }
    public DateTime RegistrationDate { get; set; }

    public RegisterUserCommand()
    {
        RegistrationDate = DateTime.UtcNow;
    }
}

И контроллер

public class RegisterController : Controller
{
    //
    // GET: /Register/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(RegisterUserViewModel registrationData)
    {

        var service = NcqrsEnvironment.Get<ICommandService>();
        service.Execute(
            new RegisterUserCommand
            {
                Email= registrationData.Email,
                OpenIdIdentifier = registrationData.OpenIdIdentifier
            }
            );

        return View();
    }


    public class RegisterUserViewModel
    {
        [Required]
        [StringLength(16)]
        public string Name { get; set; }
        [Required]
        [StringLength(64)]
        public string Email{ get; set; }
    }
}
Другие вопросы по тегам