MVC строго типизированный вид и настройки на стороне сервера перед отправкой на нижние уровни? - PullRequest
0 голосов
/ 12 сентября 2011

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

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

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; }
    }
}

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

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

[Редактировать] Поскольку 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 голосов
/ 13 сентября 2011

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

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

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

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

1 голос
/ 12 сентября 2011

Я бы порекомендовал поместить это в конструктор класса 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; }
    }
}
1 голос
/ 12 сентября 2011

Я бы использовал номер 1 и использовал system.componentmodel.dataannotations.metadatatype для проверки.

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

Это позволяет вам хранить вашу модель в другой библиотеке, проверять поля и показывать поля, как если бы вы использовали внутренние / частные классы с 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();
}
...