2011-06-14 2 views
19

Je comprends MVC est tout au sujet de mettre les choses au bon endroit et la logique où il devrait être. Mes actions de contrôleur sont remplies de logique métier (non liée au stockage de données) et je pense que je devrais commencer à déplacer une partie de la logique vers un autre endroit.Où devrais-je mettre ma logique métier contrôleur dans MVC3

Y a-t-il une convention pour où je devrais placer cette logique? Par exemple, j'ai le contrôleur suivant qui est situé dans le fichier contrôleurs:

adminPowerController 

    public ActionResult Create(string test1) 
    // business logic 
    // business logic 
    // business logic 
    return View(); 
    } 
    public ActionResult Index(string test1) 
    // business logic 
    // business logic 
    // business logic 
    return View(); 
    } 
+0

Vérifiez cette question connexe: http://stackoverflow.com/q/3131798/64096 –

Répondre

26

L'endroit recommandé de mettre la logique métier est dans une couche de service. Vous pouvez donc définir une interface qui représentera l'opération commerciale:

public interface IMyService 
{ 
    DomainModel SomeOperation(string input); 
} 

puis d'implémenter ce service. Enfin le contrôleur l'utilisera:

public class MyController: Controller 
{ 
    private readonly IMyService _service; 
    public class MyController(IMyService service) 
    { 
     _service = service; 
    } 

    public ActionResult Create(string input) 
    { 
     var model = _service.SomeOperation(input); 
     var viewModel = Mapper.Map<DomainModel, ViewModel>(model); 
     return View(viewModel); 
    } 
} 

et de configurer votre infrastructure DI pour passer la bonne implémentation du service dans le contrôleur. Remarque: Dans l'exemple fourni, j'ai utilisé AutoMapper pour convertir un modèle de domaine en un modèle de vue transmis à la vue.

+2

ce code a dépendances AutoMapper et donc l'OP peut-être besoin de connaître à propos de cette référence – stack72

+1

@ stack72, bon point. J'ai mis à jour ma réponse pour fournir une référence. –

+0

Merci pour vos commentaires. Quelles sont les conventions de dénomination de fichier et de répertoire que vous utilisez pour votre couche de service? Puis-je supposer que vous conservez ces fichiers dans un répertoire appelé Interfaces? – Geraldo

5

Ce que je tends à faire dans mes projets MVC est de garder autant de la logique métier que possible en dehors de mes actions pour que je puisse les tester

Dans certains cas, je crée une couche de service et ensuite utiliser ce

public class QuizRunner : IQuizRunner 
{ 
    private readonly IServiceProxyclient _quizServiceProxy; 
    public QuizRunner(IServiceProxyclient quizServiceProxy) 
    { 
     _quizServiceProxy = quizServiceProxy; 
    } 

    public GameCategory GetPrizeGameCategory(int prizeId) 
    { 
     return _quizServiceProxy.GetGameCategoryForPrizeId(prizeId); 
    } 

} 

public interface IQuizRunner 
{ 
    GameCategory GetPrizeGameCategory(int prizeId); 
} 



private IQuizRunner_serviceClass; 

public AdminPowercontroller(IQuizRunner serviceClass) 
{ 
    _serviceClass = serviceClass; 
} 


public ActionResult Create(string test1) 
    var itemsFromLogic = _serviceClass.Method1(); 
    return View(); 
} 
public ActionResult Index(string test1) 
    var gameCategory = _serviceClass.GetPrizeGameCategory(test1); 
    var viewModel = Mapper.Map<GameCategory, GameCategoryViewModel>(gameCategory); 
    return View(viewModel); 
} 

cela permet mes actions à tester séparément de ma couche de service et sans dépendance

Hope this helps

Paul

+0

Merci pour vos commentaires. Quelles sont les conventions de dénomination de fichier et de répertoire que vous utilisez pour votre couche de service?Si cela ne vous dérange pas, pourriez-vous me montrer à quoi ressemblerait un fichier typique contenant une classe implémentant IServiceLayerClass? Juste la coquille du fichier et peut-être un argument qui se passe dedans ou dehors. Merci beaucoup. – Geraldo

+0

J'ai mis à jour ma réponse pour afficher un exemple de classe de couche de service - cette classe interagit avec un service Web mais démontre la preuve de concept – stack72

+0

@ stack72 - Comment le contrôleur est-il appelé avec la classe de service correcte? – Geraldo

1

La logique métier doit se trouver dans votre modèle de domaine séparé du framework MVC et d'autres éléments.

exemple du monde réel ...

Application (un de mes entités de domaine) Contrôleur:

[HttpPost] 
public ActionResult Withdraw(int applicationId){ 
    //find it from repository or whatever 
    var app=FindApplication(applicationId); 
    //force it do do stuff 
    a.Withdraw(); 
    //send back some response 
    return RedirectToAction("Application",new{applicationId}); 
} 

entité application elle-même:

public class Application{ 
public void Withdraw(){ 
    //check if current user is authorized to withdraw applications 
    Authorize<CanWithdrawApplications>(); 
    //check if application itself can be withdrawn 
    ThrowIf(!CanBeWithdrawn(),"Application can't be withdrawn."); 
    //apply state changes 
    IsWithdrawn=true; 
    //raise domain event 
    Raise(new Withdrawn(this)); 
} 
public bool CanBeWithdrawn(){ 
    return !IsWithdrawn && !Project.Contract.IsSigned; 
} 
} 

Pour en savoir plus sur ce Vous pouvez Découvrez ce qu'est domain driven design.

+0

@Amis - Donc, vous mettez normalement l'entité de l'application dans un genre de répertoire de service ? Comment FindApplication fonctionne-t-il? – Geraldo

+0

@Geraldo Mon entité d'application vit dans un assemblage séparé appelé 'Domain' (qui ne connaît que le framework .Net), dossier' Model'. FindApplication appelle simplement NHibernate directement. –

+0

mais si le dao est utilisé dans la couche logique, devrais-je injecter daoservice dans le modèle? –

Questions connexes