开发者

Where should I put my controller business logic in MVC3

开发者 https://www.devze.com 2023-03-12 13:49 出处:网络
I understand MVC is all about putting things in the correct place and the logic where it should be. My controller actions are getting filled up with business logic (not related to data storage) and I

I understand MVC is all about putting things in the correct place and the logic where it should be. My controller actions are getting filled up with business logic (not related to data storage) and I feel that I should start moving some of the logic to a different place.

Is there a convention for where I should place this logic? For example I have the foll开发者_JS百科owing controller that's located in the controllers file:

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


The recommended place to put business logic is into a service layer. So you could define an interface which will represent the business operation:

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

and then have an implementation of this service. Finally the controller will use it:

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

and configure your DI framework to pass the proper implementation of the service into the controller.

Remark: In the example I provided I used AutoMapper to convert between a domain model into a view model which is passed to the view.


What i tend to do in my MVC projects is to keep as much of the business logic as possible outside of my actions so that I can test them

In some cases I create a service layer and then use that

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

this allows my actions to be tested separately from my service layer and without dependency

Hope this helps

Paul


Business logic should live in your domain model separated from MVC framework and other stuff.

Real world example...

Application (one of my domain entities) controller:

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

Application entity itself:

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

For more about this You might want to check out what domain driven design is about.

0

精彩评论

暂无评论...
验证码 换一张
取 消