Как проверка сервиса передается обратно в контроллер? - PullRequest
1 голос
/ 27 февраля 2011

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

У меня есть сайт MVC 3, и у меня есть сервисный уровень, с которым общаются мои контроллеры, и хранилище, с которым общается мой сервисный уровень (все отделены с помощью контейнера IoC, но этоне имеет значения здесь).Моими моделями доменов являются объекты EF4, совместно используемые контроллером, службами и репозиториями.

У меня есть модель представления для регистрации, которая выглядит примерно так:

public class SignupViewModel
{
    [DisplayName("Email")]
    [Required, RegularExpression(@"^.+@.+\..+$")]
    public string Email { get; set; }

    [DisplayName("Password")]
    [Required]
    public string Password { get; set; }

    [DisplayName("Confirm password")]
    [Required, Compare("Password")]
    public string PasswordConfirmation { get; set; }
}

Модель моего домена пользователя выглядиткак-то так:

public class User
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string PasswordHash { get; set; }
    public string PasswordSalt { get; set; }
}

У меня есть сервисный метод, который используется для регистрации пользователя, который выглядит примерно так:

public void Register(User user, string planTextPassword)
{
    //Make sure the email address is not taken.
    bool emailIsTaken = IsEmailTaken(user.Email);

    if (emailIsTaken)
    {
        //What do I do here?
    }
    else
    {
        //Create the user.
    }
}

И, наконец, действие моего контроллера, чтобы связать все этовместе:

public ActionResult Signup(SignupViewModel signupViewModel)
{
    if (ModelState.IsValid)
    {
        _accountService.Register(Mapper.Map<SignupViewModel, User>(signupViewModel), signupViewModel.Password);
        _unitOfWork.Commit();
    }

    return View(signupViewModel);
}

Как вы можете видеть в комментарии в моем методе обслуживания, что мне делать, если проверка уровня обслуживания не проходит?Как обсуждалось в этом вопросе , я не должен бросать исключения.Но я не уверен, что следую тому, что предлагает Райан, или даже если это все еще применимо (т.е. есть ли лучшие способы справиться с этим сейчас с помощью MVC 3 или других инструментов, доступных сейчас, например, Fluent Validation).

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

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 27 февраля 2011

Я однажды попытался сделать то, о чем говорит Райан. В основном он говорит, что ваш сервис должен выглядеть примерно так:

public class TheService{
  ValidationResult Validate(YourType item);
  Save(YourType item);
}

Вначале вызывается Validate, и, если ValidationResult успешен, вы вызываете Save. Сохранение подтвердит сущность снова, чтобы убедиться, что вы не забыли проверить ее. Разница в том, что если при сохранении вызова происходит ошибка, возникает исключение.

Лично я сделал это один раз и больше не буду. Я думаю, что простое создание исключения делает все намного понятнее и дает меньше кода для обслуживания.

Чтобы вернуть информацию об ошибке в контроллер, вам нужно создать собственное исключение. Это может выглядеть так:

public class RulesException : Exception{
   public IEnumerable<ErrorInfo> Errors {get;set;}
}

public class ErrorInfo{
  public string PropertyName {get;set;}
  public string ErrorMessage {get;set;}
}

Что-то в этом роде - это начало. Для лучшей реализации смотрите исходный код xVal

ПРИМЕЧАНИЕ. Если вы используете исключения, постарайтесь не писать код, в котором вы выполняете попытку / перехват внутри цикла. Это самая важная вещь, которую следует избегать, когда речь идет об исключениях, поскольку они дороже, но по сравнению с вызовом базы данных, например, это дешево.

1 голос
/ 27 февраля 2011

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

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

При этом вместо того, чтобы Register имел возвращаемый тип void, вы могли бы возвращать экземпляр класса, который мог бы представлять как успех, так и сбой, а в случае сбоя иметь другое свойство, в котором перечислены ошибки.Это принципиальная вещь - она ​​довольно распространена в таких языках, как, например, Haskell.

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