DDD - communication between the presentation and domain layer - c#

I am having trouble connecting the dots from many posts I have read (and coming to realize I probably need to buy Eric Evans book instead of relying on loads of internet material) I am trying to adhere to domain driven design, but I am having trouble on the best method to communication from the presentation layer to my domain before saving my data back to the database. To keep it simple, right now I have a user class that can have a list of jobs. When a user opens the application their active directory information is queried and this class is populated with their data as long as they have the app open. Then, the user can edit an existing job if they own it or create a new one. I started creating a service class that uses my UnitOfWork class thinking this would act as my communication, but that is where I am stuck.
Current Setup:
DAL - EF 6 generated POCOs and DbContext, Repository, Unit of Work
Domain - Entities, Repository & Unit of Work interface, domain interface services I refer to in this post?
Presentation - MVC (intranet), concrete service?
Questions:
Is the service class the best class to implement for this type of communication (and for creating new instances of my domain classes (e.g. a method to create a new job)? I realize I could use a factory pattern, but I did not want to get too complicated yet)? Would the service reside in the domain layer or do I create a separate project for an application layer? Then would the interface go in the domain layer and the concrete implementation go into the application layer? I feel like that could be over complicating the app. Also, is the service WCF or can I just create my own classes?
How do I map the ViewModel in my MVC layer back to the domain using this service (if that is the best way) without the presentation layer leaking in to the service? I've read up on DTOs, but then is that overkill in the service layer? Or is it okay to expose my domain entities as the ViewModel? I must be thinking about this incorrectly. I cannot picture how this interaction would look in a controller without some leakage. Sorry for all the questions, and thanks.
public class User
{
public int Id{ get; set; }
public string WindowsId{ get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
public string Email { get; set; }
public string WorkPhone { get; set; }
public List<Job> Jobs { get; private set; }
public void AddJob(Job job)
{
if(job == null)
throw new Exception("Job is null");
var newJob = new Job(this) //tell the job that this user is creating the job
{
Description = job.Description,
DueDate = job.DueDate,
Name = job.Name,
Reason = job.Reason
};
Jobs.Add(newJob);
}
}
UPDATE: My Solution
I ended up taking a little bit from everybody's answers.
#granadaCoder - I used my EF POCOs as the classes to pass around as DTOs because most of the time that is the data I was displaying to the user in my ViewModel. So it allowed me to use the DTOs as the ViewModels
#ChrisPratt - you are correct. Doing this prevented a lot of extra work. All I did was create a service that had all the queries I needed. And if I ever had to change the EF it would still not bother my other layers. All I would have to do is create the repository and UOW
#MilivojMilani - I did have repeating logic in the controller so the service layer kept me aligned with the DRY principal
#Yorro - I used your points and references to reinforce the design since I was still unsure about the service layer setup. Since this is a smaller project, I setup another folder with my service and interface that I created, no WCF

Stay away from the Repository/Unit of Work pattern if you're using Entity Framework. EF is itself an implementation of this pattern. If you want to abstract Entity Framework, then implement a service pattern that returns fully-baked data exactly how you need it. It's best illustrated with an example:
With EF/Repository
IQueryable<Post> posts = db.Posts.Where(m => m.BlogId == blog.Id && m.Status == PostStatuses.Published && m.PublishDate <= DateTime.Now).OrderBy(m => m.PublishDate);
With Service
List<Post> posts = service.GetPublishedPostsForBlog(blog);
The two key differences here are:
You're returning data already pulled from the database with the service; a repository/EF will return a queryable that may or may not have been executed against the database yet.
All your logic goes into the service method with a service. Whereas, with a repository/EF you build your query in place.
That said, don't get so hung up on the layers of your application. It's not about how many layers you have and what you call them, but rather about abstracting logic away from pieces of your application that shouldn't need to know how to construct that logic. A controller action to return a list of published blog posts, for example, shouldn't need to know what qualifies a post as being "published". That's domain logic that should go somewhere else (like the service method that returns this dataset). The idea is simply to follow the single-responsibility principle: a class/method/etc. should do one thing and do it well. Your controller action should only concern itself with returning the view (and doing the bare minimal amount of work to fetch what that view needs).
As far as mapping goes, the term explains exactly what you do, so I'm not sure of the confusion here. If you want to map Post to PostViewModel for example:
var model = new PostViewModel
{
Title = post.Title,
Content = post.Content,
...
}
Or with a list of objects, you can employ LINQ:
var model = posts.Select(m => new PostViewModel
{
Title = m.Title,
Content = m.Content,
...
}
If you question is simply: how do I do this easier? Then, you can look into a third-party mapping library like AutoMapper.

The Service Layer
The service layer serves as the application's boundery, it encapsulates your domain entities, in other words, it protects your domain. All communication to the domain must go through the service layer. But the Domain Model (at its purest form) should not have any reference to the Service Layer or any other infrastructure layers (DAL/Presentation).
http://martinfowler.com/eaaCatalog/serviceLayer.html
Would the service reside in the domain layer or do I create a separate project for an application layer? Then would the interface go in the domain layer and the concrete implementation go into the application layer?
If you are already segregating your layers into their own projects, then the service layer should have its own project.
Is the service WCF or can I just create my own classes?
The simplest service is just a class, see an example of a service layer straight from Microsoft Tutorials:
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
Here is another example on how to refactor an MVC using a service layer
http://www.arrangeactassert.com/asp-net-mvc-controller-best-practices-%E2%80%93-skinny-controllers/
How do I map the ViewModel in my MVC layer back to the domain using this service (if that is the best way) without the presentation layer leaking in to the service? I've read up on DTOs, but then is that overkill in the service layer? Or is it okay to expose my domain entities as the ViewModel? I must be thinking about this incorrectly. I cannot picture how this interaction would look in a controller without some leakage.
This question is another topic altogether. DTO is a good way for the service layer to communicate with outside layers.
Your questions are very good, and in fact it is the most frequently asked.
Is it overkill to use DTO in the Service Layer?
Is it okay to expose the guts(domain) of my application to outside layers?
How would the service layer interact with outside layers without leakages?
Where should the DTO reside?
I've answered the same questions here: https://stackoverflow.com/a/21569720/1027250
This image provides overhead view on how a service layer fits into a multi-layer architecture. Note that this is not absolute or perfect for every project, you should approach a pattern depending on the need of the project. Additional layers adds complexity, it is a long term investment on a long term project with a large team.

1.If you're using MVC you may or may not have a service layer. Ask yourself a following question - do you use this functionality on more than one place? If the answer is yes - use the application service (not domain service). If no, put it in the MVC controller itself.
Don't put any hydration logic in the domain layer. Domain layer in DDD shouldn't know anything about persistence. Controller/Application service should fetch the data using repository interfaces and save the data using same interfaces. In your case, you should be fetching and saving only the User class, while Job should be below it as aggregate root child. Using UnitOfWork and Repository is perfectly fine. Here is a good article on it =>
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
2.It is perfectly normal to, in some cases, use domain object as ViewModel class. In other more complex cases, you will have to map properties manually. Mapping is usually best done as extension method on ViewModel class. Some use AutoMapper though I'm against using it when mapping presentation classes to domain. All this mapping work should NOT be done in domain layer. You might have a lot of viewmodel classes and it would bloat the domain layer with presentation layer logic.
Hope it helped.

Related

How to persist aggregates with repositories?

I am trying to learn some concepts about DDD and the part of persisting Aggregates is confusing me a bit. I have read various answers on the topic on SO but none of them seem to answer my question.
Let's say I have an Aggregate root of Product. Now I do not want to inject the ProductRepository that will persist this aggregate root in the constructor of the Product class itself. Imagine me writting code like
var prod = new Product(Factory.CreateProductRepository(), name, costprice);
in the UI layer. If I do not want to inject my repository via dependency injection in the Aggregate Root, then the question is where should this code go? Should I create a class only for persisting this AR? Can anyone suggest what is the correct & recommended approach to solve this issue?
My concern is not which ORM to use or how to make this AR ORM friendly or easy to persist, my question is around the right use of repositories or any persistence class.
Application Services
You are right, the domain layer should know nothing about persistence. So injecting the repository into Product is indeed a bad idea.
The DDD concept you are looking for is called Application Service. An application service is not part of the domain layer, but lives in the service layer (sometimes called application layer). Application services represent a use case (as opposed to a domain concept) and have the following responsibilities:
Perform input validation
Enforce access control
Perform transaction control
The last point means that an application service will query a repository for an aggregate of a specific type (e.g. by ID), modify it by using one of its methods, and then pass it back to the repository for updating the DB.
Repository Ganularity
Concerning your second question
Should I create a class only for persisting this AR?
Yes, creating one repository per aggregate is a common approach. Often, standard repository operations like getById(), update(), delete(), etc. are extracted into a reusable class (either a base class or by aggregation).
You can also create additional repositories for non-domain information, e.g. statistical data. In these cases, make sure that you don't accidentally miss a domain concept, however.

DAL, Model Layer, EF code-first and business logic, how do they fit together?

Bit per bit, I am undestanding and becoming more proficient with ASP.NET MVC4. However I'm still failing to be clear in my mind concerning this very important point. Let us say that I have a model :
public class WorkPaper
{
public int WorkPaperID { get; set; }
public string name { get; set; }
public string description {get ; set; }
public bool verified {get; set;}
public DateTime dateAdded {get; set;}
}
I use this model with Entity Framework code first approach and I have the following DB Context :
public class NicodemeContext : DbContext
{
public DbSet<WorkPaper> Workpapers { get; set; }
}
What I don't understand is : what is the Model Layer and what is the Data Access Layer. To me the WorkPaper class tends to be part of the DAL since I designed it and choosed my properties names and types (navigations property etc...) to fit the EF pattern. But the problem is that if i'm right, I really don't see where I should put the business logic.
In that specific case, if I want to add a rule saying that a Workpaper cannot be sent if it hasn't been verified and an other rule saying that if it's been added more than 2 weeks ago it can't be submitted (strange rules but that's just an example). Where should I add them ? Do I have to create an other class, but then where should I put it and what should it contain ? Isn't it going to be very redundant with the class I already have ? But in the other hand, since that class is "database oriented", wouldn't it be messy to add business rules there ?
My point is really in understanding where I have to put my business logic and to understand the difference between the DAL and the model. I have difficulties to identify the DAL and the Model Layer since their look very similar to me. I would like to do things the correct way.
(Basically, I don't know where to code "my program" with MVC ! I'm not comfortable as soon as I want to code the functionality I'm actually interested in. I feel like i'm not doing the things right)
There is no single "right" way to do this. There are probably a number of "wrong" ways, but as with most things much of it is "it depends".
You will find a lot of opinions on this. And much of that depends on how you are approaching it. For instance, #Tarzan suggests using your model for both business logic and data layer entities. Others, suggest creating separate Entity objects, business objects, and view model objects.
If you're making a relatively simple, CRUD type application then you can probably do as #Tarzan suggests and have few problems. However, in more complex applications you start to run into problems doing it this way. For instance, what happens when your business logic is different from your data logic? If you combine them into a single set of entities, then you are forced to make the logic the same everywhere, or spend a lot of time retrofitting.
The most flexible approach is to keep your Presentation, Business, and Data layers completely separate. In this way, the requirements of (for example) the UI don't need to match the other layers. (Here's a simple example, imagine that for some kinds of objects, a particular field is allowed to be null, but not for others. Your data layer would only know that the field is nullable, while your business layer would know that certain objects can't be null).
However, that approach can have a lot of overhead, and require what seems like duplicate code in each layer... creating a lot of extra effort, which is often times not worth it for small or simple applications.
One key thing to remember is that MVC is a Presentation pattern. That means it ONLY concerns itself with the user interface. The "model" is typically considered to be a "view model", which is the model the view uses. This model is customized for the views requirements. For instance, by using Data Attributes that you would not put on a data model.
If you consider MVC to be strictly presentational, then MVC doesn't care what kind of data access you're using, nor does it care what kind of business layer you're using. It could be a service layer, or a repository, or a business objects library (such as CSLA).
A common pattern in MVC applications is to use a service layer of some type, or a repository if you're simply doing CRUD operations. There is typically some kind of mapping system between each layer, using technologies like AutoMapper or custom build mapping classes.
The point here is simply this. MVC doesn't concern itself with business and data, so don't get yourself all worked up over how these fit into an MVC application. They don't, or at least they don't other than with very basic interfacing.
Your application is a collection of objects, in what can be considered an architecture. This architecture is made up of different layers. MVC, Service, Data, etc.. MVC may be the primary user interface, but that doesn't mean everything else is also MVC.
You can put the NicodemeContext class in the DAL and the WorkPaper class in the Model Layer.
The Model Layer is where you define your business domain. This is where your business logic goes.
The Data Access Layer is where you read and write to the database and populate the objects from your Model Layer.
A useful technique is to use partial classes in the Model. In one partial class keep everything that might be written by a code generator and everything handwritten in the other partial class. For example, if you use a tool to generate a partial WorkPaper class it will usually contain all of the properties and associations. In the handwritten partial class you can place your business logic. If something changes with your domain, this allows you to run the class generator again and again without fear of losing your business logic. I know that you said you are using code-first but still, partial classes can be useful.
Models are where you put business logic, and communicate with the Data Access Layer which saves & retrieves data. Your views are for presenting the user interface. The controllers are for passing information between views and models. It takes awhile to get the feel of MVC, but you are asking the right questions and are on the right track.
Hope this helps. Cheers.

Where should I place business logic when using RavenDB

I am planning on building a single page application(SPA) using RavenDB as my data store.
I would like to start with the ASP.NET Hot Towel template for the SPA piece.
I will remove the EntityFramework/WebApi/Breeze components and replace with RavenDB for storage and ServiceStack for building the backend API.
Most current opinions seems to frown upon using any sort of repository or additional abstraction on top of RavenDB and call for using the RavenDB API directly inside of controllers(in an MVC app)
I am assuming I should follow the same wisdom when using Raven with ServiceStack and make calls against IDocumentSession directly inside of my service implementations.
My concern lies with the fact that it seems my service implementation will become rather bloated by following this path. It also seems that I will often need to write the same code multiple times, for example, if I need to update a User document within several different web service endpoints.
It also seems likely that I will need to access Raven from other (future) pieces of my application. For example, I may need to add a console application that processes jobs from a queue in the future, and this piece of the app may need to access data within Raven...but from the start, my only path to Raven will be through the web service API. Would I just plan to call the web api from this theoretical console app? Seem inefficient if they are potentially running on the same hardware.
Can anyone offer any advice on how to utilize Raven effectively within my webservices and elsewhere while still following best practices when using this document store? It would seem practical to create a middle business logic tier that handles calls against raven directly...allowing my webservices to call methods within this tier. Does this make sense?
EDIT
Can anyone provide any recent samples of similar architecture?
FWIW, we're currently working on an app using ServiceStack and RavenDB. We're using a DDD approach and have our business logic in a rich Domain Layer. The architecture is:
Web App. Hosts the web client code (SPA) and the service layer.
Service Layer. Web services using ServiceStack with clean/fairly flat DTOs that are completely decoupled from the Domain objects. The Web Services are responsible for managing transactions and all RavenDB interaction. Most 'Command-ish' service operations consist of: a) Load domain object(s) (document(s)) identified by request, b) Invoke business logic, c) Transform results to response DTOs. We've augmented ServiceStack so that many Command-ish operations use an automatic handler that does all the above without any code required. The 'Query-ish' service operations generally consist of: a) Executing query(ies) against RavenDB, b) Transforming the query results to response DTOs (in practice this is often done as part of a), using RavenDB during query processing/indices/transformers). Business logic is always pushed down to the Domain Layer.
Domain Layer. Documents, which correspond to 'root aggregates' in DDD-speak, are completely database agnostic. They know nothing of how they are loaded/saved etc. Domain objects expose public GETTERs only and private SETTERs. The only way to modify state on domain objects is by calling methods. Domain objects expose public methods that are intended to be utilised by the Service Layer, or protected/internal methods for use within the domain layer. The domain layer references the Messages assembly, primarily to allow methods on our domain objects to accept complex request objects and avoid methods with painfully long parameter lists.
Messages assembly. Standalone assembly to support other native .Net clients such as unit-tests and integration tests.
As for other clients, we have two options. We can reference ServiceStack.Common and the Messages assembly and call the web services. Alternatively, if the need is substantially different and we wish to bypass the web services, we could create a new client app, reference the Domain Layer assembly and the Raven client and work directly that way.
In my view the repository pattern is an unnecessary and leaky abstraction. We're still developing but the above seems to be working well so far.
EDIT
A greatly simplified domain object might look something like this.
public class Order
{
public string Id { get; private set; }
public DateTime Raised { get; private set; }
public Money TotalValue { get; private set; }
public Money TotalTax { get; private set; }
public List<OrderItem> Items { get; private set; }
// Available to the service layer.
public Order(Messages.CreateOrder request, IOrderNumberGenerator numberGenerator, ITaxCalculator taxCalculator)
{
Raised = DateTime.UtcNow;
Id = numberGenerator.Generate();
Items = new List<OrderItem>();
foreach(var item in request.InitialItems)
AddOrderItem(item);
UpdateTotals(taxCalculator);
}
private void AddOrderItemCore(Messages.AddOrderItem request)
{
Items.Add(new OrderItem(this, request));
}
// Available to the service layer.
public void AddOrderItem(Messages.AddOrderItem request, ITaxCalculator taxCalculator)
{
AddOrderItemCore(request);
UpdateTotals(taxCalculator);
}
private void UpdateTotals(ITaxCalculator taxCalculator)
{
TotalTax = Items.Sum(x => taxCalculator.Calculate(this, x));
TotalValue = Items.Sum(x => x.Value);
}
}
There's two main parts to consider here.
Firstly, as you have already noted, if you go by the word of the more fanatical RavenDB fans it is some mythical beast which is exempt from the otherwise commonly accepted laws of good application design and should be allowed to permeate throughout your application at will.
It depends on the situation of course but to put it simply, if you would structure your application a certain way with something like SQL Server, do the same with RavenDB. If you would have a DAL layer, ORM, repository pattern or whatever with a SQL Server back-end, do the same with RavenDB. If you don't mind leaky abstractions, or the project is small enough to not warrant abstracting your data access at all, code accordingly.
The main difference with RavenDB is that you're getting a few things like unit of work and the ORM for 'free', but the overall solution architecture shouldn't be that different.
Second, connecting other clients. Why would a console app - or any other client for that matter - access your RavenDB server instance any differently to your web site? Even if you run the server embedded mode in your ASP.NET application, you can still connect other clients to it with the same RavenDB.Client code. You shouldn't need to touch the web service API directly.

anemic domain model and domain services

If domain entities aren't anemic, so they embed specific-usage behavior inside themselfes, is there a need/point to use/build specific domain services? How about validation should it go inside an entity?
What way is more flexible for unit testing?
Thanks!
Typically when an anemic model is not being used, you'll still have needs that require domain specific services. That's because the non-anemic models (or just, models, if you will) should contain code that allows themselves to be manipulated, but should refrain from taking dependencies on other models, especially models that are not directly related through a parent/child relationship.
Separate domain services will allow you to maintain that separation and still provide rich functionality, since they domain services can potentially be aware of a larger view of the entire domain model.
As for validation, it is not uncommon for these models to provide their own validation, just remember that sometimes the valid state of a model depends on a larger context that the model may not be aware of, so external validation is probably still going to exist.
Lastly, unit-testing flexibility is going to depend quite a bit on your application, and the underlying technology (such as language choice). I haven't seen many cases where either approach has enough influence on unit testing by itself.
Domain Services are necessary when you have a Domain Model because there is functionality that's not a part of your entities.
Think for example about a Repository or a Factory. The interface for a Repository will probably be in your Domain Layer but the implementation in your Infrastructure Layer. With a Factory, both the implementation and interface will be in your Domain Layer.
These Domain Services are used from your Application Layer. The goal of an application layer is to make sure that everything is in place so the Domain Model can do his work. This could mean loading specific entities from Repositories and then calling domain specific functions on them.
Validation should go inside an Entity. For example, lets suppose you have a Money class.
public class Money
{
public Money(string currency, int amount)
{
Currency = currency;
Amount = amount;
}
public int Amount { get; set; }
public string Currency { get; set; }
}
If the Money class is not allowed to have a negative amount, where would you validate this?
The best place to do this is inside the class. An entity is responsible for its own state.
In a Money class, this is easy to see but for example with an Order class with OrderLines the Order is responsible for checking if there are duplicate OrderLine items that should be merged (saves shipping costs!)
Domain Services usually contain domain functionality that doesn't naturally fit into one of your entities. It's often functionality that is required by many other domain objects, potentially making the domain service a big nexus where many objects connect.
As for validation, it can be in various places depending on when and what you want to validate :
Factories enforce invariants upon creation of an entity
Aggregate roots enforce invariants that concern the whole aggregate
Basic validation is also often performed inside the entities themselves
You can have custom validation that requires data related to the current state of the application, in which case the validation is more likely to be done in the Application layer.

MVC Business Logic Organization [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to learn MVC with ASP.Net and am reading Steve Sanderson's book. One thing I'm confused about is where to place the business logic?
For example, when deleting a product all Sanderson has is a method in his CartController that calls the Delete method on the productsRepository. This is strange to me because if there were any business logic, such as ensuring that the product isn't in anyone's shopping cart first, etc. it would have to either be in the products repository or the CartController.
Both of these seem like bad places to put business logic; the products repository is meant to be easily replaced with another (switching from using a db to using a session) and using the Controller means you are putting the business logic in the UI layer.
Shouldn't he be using a class that contains the business logic and calls the repository's delete method instead? The repository being a member variable of the business logic class'?
I typically structure my MVC solutions in a way resembling the following:
X.Core
general extension methods, logging, and other non-web infrastructure code
X.Domain
domain entities and repositories
X.Domain.Services
domain services for orchestrating complex domain operations, such as adding a product to a shopping cart
X.Application.Core
application logic (initialization (route registration, IoC configuration, etc.), web-specific extensions, MVC filters, controller base classes, view engines, etc.)
X.Application.Models
view model classes
X.Application.Services
service classes that can return ViewModels by accessing repositories or domain services, as well as the other way around for updates
X.Application.Web
controllers, views and static resources
Some of these could be combined, but having them separate makes it easier to locate stuff and to ensure your layer boundaries are respected.
A typical controller action for showing the product cart might look like this:
public virtual ActionResult ProductCart()
{
var applicationService = <obtain or create appropriate service instance>
var userID = <obtain user ID or similar from session state>
var viewModel = applicationService.GetProductCartModel( userID );
return View( "Cart", viewModel );
}
A typical controller action for adding a product to the shopping cart might thus look something like this:
public virtual ActionResult AddProductToCart( int productID )
{
var domainService = <obtain or create appropriate service instance>
var userID = <obtain user ID or similar from session state>
var response = domainService.AddProductToCart( userID, productID );
return Json( new { Success = response.Success, Message = response.Message } );
}
I also read Sanderson's first version of his book and it was fantastic - a very easy way to pick up and start using ASP.NET MVC. Unfortunately, you can't jump straight from the concepts in his book to writing a large maintainable application. One of the biggest hurdles is figuring out where to put your business logic and other concerns that lie between the UI and persistent storage (a concept called Separation of Concerns or SOC).
If you are interested, consider reading up on Domain Driven Design. I won't suggest that I know it perfectly, but serves as a good transition from Sanderson's sample applications into something that successfully separates UI concerns, business logic, and storage concerns.
My solution has a separate service layer. The controllers communicate with the service layer (using Dependency Injection - Ninject). The service layer has access to my domain objects / business logic and my repositories (NHibernate - also spun up with Ninject). I have very little logic in my views or controllers - the controllers serve a purpose of coordinator and I strive to keep my controller actions as thin as possible.
My domain layer (entities, business logic, etc.) has no dependencies. It does not have references to my Web project or to my Repository project. It is what is often referred to as POCO or Plain Old C#/CLR Objects.
EDIT: I noticed in one of your comments you are using EF. EF does not support POCO without using something called Code First (was in Community Technology Preview status when I checked last August). Just FYI.
The reality is that there's no silver bullet to this answer, and it really is a contextual question at heart. I like to separate things as much as possible, and business logic is, if you think about it, just another layer in an app.
I worked up a BDD-inspired decisioning engine and released it as an OSS project available via NuGet. The project is called NDecision, and you can read about it on the NDecision project home page.
NDecision makes decision-tree business logic quite simple to implement, and if you're a fan of Gherkin syntax and Fluent coding practices you'll feel right at home using it. The code snapshot below is from the project site, and demonstrates how business logic could be implemented.
This might not be a solution for you, but the idea is, if you already have your domain model in one assembly - a great idea and common practice as suggested in another answer earlier, there's no reason why you can't have another assembly with your "decision tree." NDecision was written with that in mind, to separate the logic into one independent layer.
Hopefully that'll be of some assistance.
If you want scalability, it's bad practice to use data access objects directly from the GUI. So in the example you mentioned, I think you should replace the repository that directly reads or writes to the DB by some business logic class that supports business operations.
I'm trying to learn MVC with ASP.Net
and am reading Steve Sanderson's book.
One thing I'm confused about is where
to place the business logic?
In the model (M in MVC), or domain layer. These are a separate set of types (preferably in a separate project) that represent domain models, services and repositories.

Categories