How to implement a "slim" controller

Asked

Viewed 331 times

9

I am working on a prototype of an ASP.NET MVC application, where I want to leave my controller lean (with the least amount of code possible), for such, not making business logic in it, but rather in the business layer.

I have the business layer, where I have my class Usuario, and in this layer I have interfaces that should be implemented by other layers. I will be using dependency injection.

My question is how to notify my controller on what worked or not, to notify or redirect the user, for example, when my controller calls Usuario.Cadastrar(), there may be an error in filling in the data, the password may not meet the security requirements, the email may already be registered or there may be error in sending the confirmation email.

What the Register method should return to Controller? An enumerator like (ErroEnviarEmail, SenhaFraca, EmailCadastrado), one Exception for every possible path? A string etc..

public class Usuario
{
    public Usuario()
    {

    }

    public Usuario(IUsuarioRepositorio repositorio, ISeguranca seguranca, IEnviaEmail email)
    {
        this.repositorio = repositorio;
        this.seguranca = seguranca;
        this.email = email;
    }

    private IUsuarioRepositorio repositorio;
    private ISeguranca seguranca;
    private IEnviaEmail email;

    public int Codigo { get; set; }
    public string Email { get; set; }
    public string Senha { get; set; }


    public bool Cadastrar()
    {
        if (this.ValidarPreenchimento())
        {
            if (this.seguranca.ValidarSegurancaSenha(this.Senha))
            {
                if (!this.repositorio.EmailCadastrado(this.Email))
                {
                    this.Senha = seguranca.Criptografar(this.Senha);
                    this.repositorio.Inserir(this);
                    this.email.EnviarEmailCadastro(this);
                    return true;
                }
            }
        }       
        return false;
    }

    private bool ValidarPreenchimento()
    {
        if (string.IsNullOrEmpty(this.Email))
            return false;

        if (string.IsNullOrEmpty(this.Senha))
            return false;

        return true;
    }

}
  • Why you have a "business layer"?

  • Several reasons. You can call this layer a domain, a service, or even a model, because it’s still a model. It’s about separation of responsibilities, and reuse. Today is ASP.NET MVC, but soon I can create a Web API, taking advantage of a lot, having to rewrite only the controllers of the API

  • This will not be necessary in ASP.NET 5, not least because the Controller MVC6 for Web API and MVC should be the same. Your separation is only pertinent until the MVC5. Still I would like one more answer?

  • Interesting. I think that’s it for now. Before my controller had a little more code, and this concept anti "fat controller" left me a little confused on the question of the answers he needs. But the material passed by @bigown gave a direction.But I’m still studying.

2 answers

8


I imagine you’ll have a hard time doing anything that can be called "thin" when you talk in so many layers. Lasagna does not go with thinness :). Take away the business rule from the controller It’s not making him thin, it’s fixing a mistake that had been made.

The controller does not have to be notified of anything. It invokes the model, that it must perform everything it needs and informs the controller through the return.

He’ll probably call the Usario.Cadastrar() existing in the model and the boolean return of this method should be its notification whether it has worked or not. At least this seems to be his intention.

Rich error information

Okay, you want to return other possible problems. There are alternatives.

I would probably return an enumeration or an object that gives more information that can be used in view and possibly some member of her controller. This object could look like an exception even though it is not one. Read more on link above.

There are those who say I should use exception, but I would not go this way to indicate business logic problem. Mainly to use in the way demonstrated in the other answer. In addition to not solving your problem causes others.

Depending on the context could even use the exception, or other solution not described here, but without understanding the problem as a whole is difficult to state, I can only list alternatives.

But as a general rule do not use exceptions to treat business rules, and therefore not exceptional. And validation is business rule.

  • 1

    very good these alternatives. now gave me a light to help decide.I liked ta quote of lasagna.

  • Based on your answer and suggested reading, I found the correct search terms and found a question in the community that helped me a lot http://codereview.stackexchange.com/questions/63049/returning-status-codes-from-business-layer

1

I’d do it this way:

  • Using annotation validation even you solve all the problems of information coming wrong from view.
  • Using Try catch you handle all unexpected errors, being able to create exceptions for something more specific.

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit(VMObjeto obj)
        {
            if (ModelState.IsValid)
            {
           
              try{
                
                ... 
                //chamada do seu negocio
                ....
                
              catch (Exception ex)
               {
               
                 ... 
                 //seu tratamento de erro, usando a arquitetura que você quiser
                 
               }
              
             }
          
          }

  • Thanks! I imagined that Exception was an alternative, controversial, but it is an alternative. Yes I will do validation by annotation, but I must have validation in the business layer because I intend to create a web api too.

  • @Murilo, although you don’t like the alternative I’ll give you, you can check if the call is AJAX and return a Json(retorno) instead of View(model)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.