SlideShare a Scribd company logo
DDD,
CQRS &
Testing
with ASP.Net
MVC
26
September
2015
Just to introduce myself…
• I’m Andy Butland
• Blog (sporadically) at http://web-matters.blogspot.it/
• Find here a copy of slides and links to various resources
• Contact: abutland73@gmail.com / @andybutland
• I work for Zone – www.thisiszone.com - a digital agency
where I’m head of .NET development
• We develop web sites and applications using ASP.Net
MVC and CMS platforms such as Umbraco and EPiServer
• We’re primarily UK based, in London and Bristol
• But I’m lucky enough to live…
… here, in Bassano del Grappa, Italy
And what are we talking about…
• We’ll be discussing some practices I follow when building
web applications using ASP.Net MVC
• Digested and adapted from various opinions
• Adopting best practices but in a practical way
• For me at least… leads to a nicely organised, testable and
maintainable code base

Recommended for you

8 - OpenShift - A look at a container platform: what's in the box
8 - OpenShift - A look at a container platform: what's in the box8 - OpenShift - A look at a container platform: what's in the box
8 - OpenShift - A look at a container platform: what's in the box

Many already have some familiarity with containers, and maybe even with Kubernetes. But what's the difference between those and a container platform? In this session the goal is to look at OpenShift, Red Hat's container platform based on Kubernetes. We see what it's made out of, what makes it tick, and what the future of OpenShift & Kubernetes holds.

openshiftred hatopensource
Docker
DockerDocker
Docker

Docker allows building, shipping, and running applications in portable containers. It packages an application with all its dependencies into a standardized unit for software development. Major cloud providers and companies support and use Docker in production. Containers are more lightweight and efficient than virtual machines, providing faster launch times and allowing thousands to run simultaneously on the same server. Docker simplifies distributing applications and ensures a consistent environment.

containerizationdockervirtualization
Docker Online Meetup #22: Docker Networking
Docker Online Meetup #22: Docker NetworkingDocker Online Meetup #22: Docker Networking
Docker Online Meetup #22: Docker Networking

Building on top of his talk at DockerCon 2015, Jana Radhakrishnan, Lead Software Engineer at Docker, does a deep dive into Docker Networking with additional demos and insights on the product roadmap.

networkingdocker networkinglibnetwork
Standing on the shoulders…
• Much of what follows comes from various speakers,
bloggers and writers in the .Net community
• Finally read “Domain Driven Design” by Eric Evans
• Rob Conery questioned some of practices around use of
repositories
• Blog series on DDD, CQRS and other MVC practices from Jimmy
Bogard and Gabriel Schenker at lostechies.com
• Julie Lerman’s articles on DDD with Entity Framework at MSDN
• Adam Tibi’s implementation of a CQRS pattern using the IoC
container Ninject was heavily borrowed for my own use
Contents
1
2
3
4
DDD with ASP.Net MVC
and Entity Framework
CQRS using a mediator
pattern
Wrap up and Q&A
Unit testing our model,
queries and commands
1. DDD with ASP.Net MVC
and Entity Framework
Domain driven design (DDD)
• Close replication of the real-world, business problem
• Focussed on an appropriate area of application
responsibility – the “bounded context”
• Sharing of domain knowledge and vocabulary between
business experts, developers and, importantly, the
software itself – the “ubiquitous language”

Recommended for you

1. Docker Introduction.pdf
1. Docker Introduction.pdf1. Docker Introduction.pdf
1. Docker Introduction.pdf

This document provides an introduction to Docker. It begins by explaining the differences between bare metal servers, virtualization, and containerization. It then discusses how Docker uses containerization to package applications with their dependencies in lightweight containers that can run on any infrastructure. Key Docker concepts covered include images, containers, and the Docker engine. The document also briefly outlines Docker's history and commercial editions.

Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker Compose

This document introduces Docker Compose, which allows defining and running multi-container Docker applications. It discusses that Docker Compose uses a YAML file to configure and run multi-service Docker apps. The 3 steps are to define services in a Dockerfile, define the app configuration in a Compose file, and run the containers with a single command. It also covers topics like networking, environment variables, and installing Docker Compose. Hands-on labs are provided to learn Compose through examples like WordPress.

docker composedocker captain
Docker Container Introduction
Docker Container IntroductionDocker Container Introduction
Docker Container Introduction

This document discusses Docker containers and provides an introduction. It begins with an overview of Docker and how it uses containerization technology like Linux containers and namespaces to provide isolation. It describes how Docker images are composed of layers and how containers run from these images. The document then explains benefits of Docker like portability and ease of scaling. It provides details on Docker architecture and components like images, registries and containers. Finally, it demonstrates how to simply run a Docker container with a command.

dockerinnfinisionsysadmin
A rich domain model
• In essence, a DDD approach looks to push more logic
and behaviour to the application’s core model classes
• Contrasted with an “anaemic” domain model
• Consider the domain as an “API” that you provide to the rest of the
application – providing appropriate access points and retaining
control
• Lean more on code and less on SQL/data access
• More expressive, easier to write and maintain – and test
• But careful balance needed as can’t forget performance
Control via the constructor
• Avoid a public, parameterless, default constructor
• Prevents the instantiation of invalid objects by application code via
the {} syntax, e.g.
var product = new Product { Name = “Test product” };
private Question()
{
Options = new List<QuestionOption>();
}
public Question(string code, string text, int orderInSection,
QuestionSection section, QuestionType type)
: this()
{
Code = code;
Text = text;
OrderInSection = orderInSection;
Section = section;
Type = type;
}
EF requires a
parameter-less
constructor, but it can
be private.
By requiring the rest of the application to
only call this constructor, we can ensure we
have a valid initialisation of an instance.
Control of property access
• Use private property setters to prevent direct access to
properties
• Prevents the modification of an instance into an invalid state
• Instead provide validated methods to allow related property values
to be set together, ensuring a consistent state is maintained

Recommended for you

Elasticsearch Monitoring in Openshift
Elasticsearch Monitoring in OpenshiftElasticsearch Monitoring in Openshift
Elasticsearch Monitoring in Openshift

This document summarizes a presentation about monitoring Elasticsearch in OpenShift. It discusses the challenges of running Elasticsearch in OpenShift due to limited resources, and how Prometheus and Grafana are used to monitor Elasticsearch metrics. It also describes the Elasticsearch Operator which manages Elasticsearch clusters through custom resource definitions. Skilled personnel are needed to maintain the cluster through upgrades and troubleshooting.

Oracle Cloud deployment with Terraform
Oracle Cloud deployment with TerraformOracle Cloud deployment with Terraform
Oracle Cloud deployment with Terraform

The document discusses using Terraform to automate deployment of resources in Oracle Cloud Infrastructure (OCI). It begins with an introduction to Terraform and its components like providers, modules, and backends. It then covers initial steps for setting up Terraform for OCI including installing Terraform, configuring the OCI provider, and running basic commands. The document outlines next steps like using Terraform to build small OCI infrastructures and combining configurations. It introduces using modules to define reusable infrastructure components. Finally, it provides an example of a Trivadis module for deploying a training lab environment on OCI.

ocioracleterraform
Ansible
AnsibleAnsible
Ansible

Ansible is simple open source IT engine which automates application deployment,intra service orchestration,cloud provisioning and many other IT tools.we will discuss what is ansible ,its feature ,architecture,writing ansible playbook,ansible role and ansible vs chef.

ansible
public int? NumericalMin { get; private set; }
public int? NumericalMax { get; private set; }
public void SetNumericalRange(int min, int max)
{
if (min > max)
{
throw new ArgumentException(
“Max parameter must be greater than the min parameter.");
}
NumericalMin = min;
NumericalMax = max;
}
Properties can’t be set
directly
Instead a method must be called, which
can validate and ensure related properties
are populated together.
Move behaviour into the model
• Where possible implement business logic in the domain
model objects
• Object graph must be populated sufficiently to support the behaviour
• Being POCO classes, there are no dependencies that complicate
unit testing
public int GetMaximumAvailableScore()
{
if (Type.Id == (int)QuestionTypeId.MultipleSelect)
{
return Options.Sum(x => x.Score);
}
else if (Type.Id == (int)QuestionTypeId.SingleSelect)
{
return Options.Max(x => x.Score);
}
else
{
return 0;
}
}
Logic can be
encapsulated in
methods…
[TestMethod]
public void Question_GetMaximumScoreForMultiSelect_ReturnsCorrectValue()
{
// Arrange
var question = CreateMultiSelectQuestion();
// Act
var maxScore = question.GetMaximumAvailableScore();
// Assert
Assert.AreEqual(8, maxScore);
} … which can be easily
unit tested.

Recommended for you

Communication in a Microservice Architecture
Communication in a Microservice ArchitectureCommunication in a Microservice Architecture
Communication in a Microservice Architecture

There are many different approaches to how you let your microservices communicate between one another. Be it asynchronous or synchronous, choreographed or orchestrated, eventual consistent or distributedly transactional, fault tolerant or just a mess! In this session I will provide an overview on different concepts of microservice communication and their pros & cons. On the way I'll try to throw in some anecdotes, success stories and failures I learned from so that you can hopefully take something home with you.

microservices asynchronous queue mesh routing
Quarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java frameworkQuarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java framework

For years, the client-server architecture has been the de-facto standard to build applications. But a major shift happened. The one model rules them all age is over. A new range of applications and architectures has emerged and impacts how code is written and how applications are deployed and executed. HTTP microservices, reactive applications, message-driven microservices, and serverless are now central players in modern systems. Quarkus has been designed with this new world in mind and provides first-class support for these different paradigms. Developers using the Red Hat build of Quarkus can now choose between deploying natively compiled code or JVM-based code depending on an application’s needs. Natively compiled Quarkus applications are extremely fast and memory-efficient, making Quarkus a great choice for serverless and high-density cloud deployments. Speakers 1) Shanna Chan, Senior Solutions Architect at Red Hat 2) Mark Baker, Senior Solutions Architect at Red Hat Speaker Bios Shanna Chan - Shanna is passionate about how open source solutions help others in their journey of application modernization and transformation of their business into cloud infrastructures. Her background includes application developments, DevOps, and architecting solutions for large enterprises. More about Shanna at http://linkedin.com/in/shanna-chan Mark Baker - Mark’s experiences coalesce around solution /business architecture and leadership bringing together people in both post / pre-sales software projects bridging traditional legacy systems (i.e. Jakarta (JEE) MVC) with Cloud tolerant and Cloud native open source in the journey of modernization and transformation. More about Mark at http://linkedin.com/in/markwbaker-tsl

javacontainersserverless
Introduction to jenkins
Introduction to jenkinsIntroduction to jenkins
Introduction to jenkins

@abe238 - Introduction to Jenkins - presented on September 12, 2015 at the Seattle CodeCamp 2015 in Seattle University by Abe Diaz

jenkinsci
2. CQRS using a mediator
pattern
Command Query Responsibility Segregation
• In essence, CQRS involves a separation between read
and write operations in an application
• At scale we may have separate models – one highly
cached and de-normalised for reads, and a strict,
validated model for writes
• Related concepts – “event sourcing”, “eventual
consistency” – may be appropriate in certain situations
• Even for small to medium scale applications though,
CQRS has benefits over a more typical CRUD style
Benefits of CQRS
• “Slices over layers” – breaking down application by
features rather than technical tiers
• More meaningful data operations over CRUD using the
“ubiquitous language”
• e.g. “ShipOrderCommand” versus “SaveOrder(Order
order)”
• Single, discrete transactions with the ORM
• More… but smaller, more focussed and single
responsibility principle adhering classes
MVC CQRS Pattern:
Reads
CONTROLLER VIEW
VIEW
MODEL
VIEW MODEL
QUERY
HANDLER
VIEW MODEL
QUERY
DATABASE
Retrieve domain model objects
via the Entity Framework
context
Map to view model using
AutoMapper
View model passed to
strongly typed view
Query passed as a GET parameter
to the controller action method:
• Might be a simple Id
• Or something more complex for
a search feature
QUERY
DISPATCHER
Controller calls query dispatcher
passing query.
Appropriate query handler is found
from view model and query types
(using Ninject)

Recommended for you

Finite State Queries In Lucene
Finite State Queries In LuceneFinite State Queries In Lucene
Finite State Queries In Lucene

Finite-State Queries in Lucene: * Background, improvement/evolution of MultiTermQuery API in 2.9 and Flex * Implementing existing Lucene queries with NFA/DFA for better performance: Wildcard, Regex, Fuzzy * How you can use this Query programmatically to improve relevance (I'll use an English test collection/English examples) Quick overview of other Lucene features in development, such as: * Flexible Indexing * "More-Flexible" Scoring: challenges/supporting BM25, more vector-space models, field-specific scoring, etc. * Improvements to analysis Bonus: * Lucene / Solr merger explanation and future plans About the presenter: Robert Muir is a super-active Lucene developer. He works as a software developer for Abraxas Corporation. Robert received his MS in Computer Science from Johns Hopkins and BS in CS from Radford University. For the last few years Robert has been working on foreign language NLP problems - "I really enjoy working with Lucene, as it's always receptive to better int'l/language support, even though everyone seems to be a performance freak... such a weird combination!"

solrlucenemeetup
Jenkins
JenkinsJenkins
Jenkins

Intro to Jenkins, installation of Jenkins, Integrating the testing and deployment technologies. Execute the build tests.

buildingintegrationjava
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다

마이크로서비스 스타일로 만들어진 시스템을 모노리틱 스타일로 이관한 사례와 함께 스프링을 이용해 모듈형 모노리스(modular monoliths)를 만든 경험을 바탕으로 모노리틱/마이크로서비스 보다 본질적인 문제를 제기하고, 문제 해결을 위한 생각을 공유합니다. https://github.com/arawn/building-modular-monoliths-using-spring

modularmonolithsspring
MVC CQRS Pattern:
Writes
CONTROLLER
COMMAND
RESULT
COMMAND
HANDLER
COMMAND
DATABASE
Retrieve and update domain
model objects
and persist via the EF context
Simple command result is
returned (success flag,
error message and -
sometimes - return data).
Command may be POSTed as a
parameter to the controller action
method or created within the method
COMMAND
DISPATCHER
Controller calls command dispatcher
passing command.
Appropriate command handler is found
from command type
(using Ninject)
MVC CQRS Pattern:
Validated Writes
CONTROLLER
COMMAND
RESULT
COMMAND
HANDLER
COMMAND
DATABASE
Map to domain model objects
and persist via the Entity
Framework context
Simple command result is
returned
Validated view model is mapped to command
COMMAND
DISPATCHER
Controller calls command dispatcher
passing command.
Appropriate command handler is found
from command type
(using Ninject)
VIEW
MODEL
VIEW
View model is model bound to controller action
method from form POST and validated.
In case of validation error, view model
is re-populated and returned to view.
public abstract class BaseController : Controller
{
public BaseController(IQueryDispatcher queryDispatcher,
ICommandDispatcher commandDispatcher)
{
QueryDispatcher = queryDispatcher;
CommandDispatcher = commandDispatcher;
}
}
Base controller has injected
dependencies for dispatching queries
and commands.
All controllers inherit from this.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IQueryDispatcher>().To<QueryDispatcher>();
kernel.Bind<ICommandDispatcher>().To<CommandDispatcher>();
kernel.Bind(x => x
.FromAssembliesMatching(“MyApplication.dll")
.SelectAllClasses().InheritedFrom(typeof(IQueryHandler<,>))
.BindAllInterfaces());
kernel.Bind(x => x
.FromAssembliesMatching(“MyApplication.dll")
.SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>))
.BindAllInterfaces());
}
Resolved using Ninject IoC container
Which also handles the convention
based matching of the appropriate
handler to each query and command

Recommended for you

Battle of the frameworks : Quarkus vs SpringBoot
Battle of the frameworks : Quarkus vs SpringBootBattle of the frameworks : Quarkus vs SpringBoot
Battle of the frameworks : Quarkus vs SpringBoot

Join Red Hat and Vodafone for an exciting presentation on the benefits of Quarkus over competing technologies. Hear from Vodafone's experts about their successful transition to Quarkus from Spring and discover how Quarkus can help your organization cut cloud costs, improve cluster stability, and achieve better performance. A live demo will showcase the power of Quarkus through examples of HTTP requests, security approaches, exception handling, logging, and more. In summary, this informative session will provide you valuable insights into the benefits of using Quarkus while also getting real world performance and development time numbers from Vodafone, information which can and should influence your next decisions on what Server Side Java technology to choose!

software developmentmicroservicesdevoxx2023
Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applications

The document discusses hexagonal architecture, also known as ports and adapters architecture. It is an alternative to traditional multi-layer architectures that aims to decouple the application core from external influences like databases, web frameworks, and other dependencies. The core domain logic is separated from external influences by defining application programming interfaces (APIs) called "ports" that external "adapters" implement. This allows the core to be developed and tested in isolation. The document provides an example implementation of a ticket management system using this architecture.

hexagonal architecture ports adapters spring boot
CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафор

Видео и описание темы http://blog.byndyu.ru/2014/07/command-and-query-responsibility.html

patternscqrsevent sourcing
public interface IQueryDispatcher
{
Task<TResult> Dispatch<TParameter, TResult>(TParameter query)
where TParameter : IQuery
where TResult : IQueryResult;
}
The query dispatcher has a single
method that takes two type
parameters: the query definition
and the query result.
It takes the query definition as the
argument and asynchronously
returns the result.
public class QueryDispatcher : IQueryDispatcher
{
private readonly IKernel _kernel;
public QueryDispatcher(IKernel kernel)
{
_kernel = kernel;
}
public async Task<TResult> Dispatch<TParameter, TResult>
(TParameter query)
where TParameter : IQuery
where TResult : IQueryResult
{
var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>();
return await handler.Retrieve(query);
}
}
The implementation retrieves the
appropriate handler based on the
type parameters from the services
registered with the Ninject IoC
container.
public interface ICommandDispatcher
{
Task<CommandResult> Dispatch<TParameter>(TParameter command)
where TParameter : ICommand;
}
Similarly the command dispatcher
has a single method that takes a
single type parameters: the
command definition.
It takes the command definition as
the argument, asynchronously
process it and return a status result.
public class CommandDispatcher : ICommandDispatcher
{
private readonly IKernel _kernel;
public CommandDispatcher(IKernel kernel)
{
_kernel = kernel;
}
public async Task<CommandResult> Dispatch<TParameter>
(TParameter command)
where TParameter : ICommand
{
var handler = _kernel.Get<ICommandHandler<TParameter>>();
return await handler.Execute(command);
}
}
The implementation retrieves
the appropriate handler based
on the type parameter from the
services registered with the
Ninject IoC container.

Recommended for you

Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC

Technologie ASP.NET MVC je rozšiřitelnější než se na první pohled může zdát! Pokročilejší přednáška pro ty, kteří už ASP.NET MVC někdy viděli, ukazuje, jak jednoduše upravit vestavěné routování, volání akčních metod, vyhledávání views, model binding, filtry... Na praktických příkladech bude ukázáno, jak využitím této rozšiřitelnosti dosáhnout elegantnějšího a čistšího kódu.

asp.net mvcc#.net framework
DDD (Domain-Driven Design)
DDD (Domain-Driven Design)DDD (Domain-Driven Design)
DDD (Domain-Driven Design)

Este documento describe el diseño orientado a dominio (DDD), un estilo arquitectónico que separa la aplicación en capas lógicas centradas en el dominio del negocio. Explica que la capa del dominio contiene la lógica y reglas del negocio, mientras que las capas de interfaz de usuario, aplicación e infraestructura se encargan de la presentación, coordinación y almacenamiento respectivamente. También discute patrones como entidades, objetos de valor, repositorios y servicios que ayudan a modelar el dominio

metodologyn-tierddd
DDD Sydney 20111 Razor Session
DDD Sydney 20111 Razor SessionDDD Sydney 20111 Razor Session
DDD Sydney 20111 Razor Session

The document summarizes Mohamed Meligy's presentation on the Razor view engine for ASP.NET MVC. It discusses basic Razor syntax elements and helpers, themes, compiled views, and tips for using Razor. Resources provided include links to documentation on Razor and ASP.NET helpers, sample applications, and profiles of key people involved in Razor's development.

asp.net mvcrazorasp.net
public class CommandResult
{
public bool Success { get; set; }
public string Message { get; set; }
public object Data { get; set; }
}
The simple command result usually
just returns the status of the
command.
On occasion it’s useful to return
some data, most often the Id of a
newly generated record.
public async Task<ViewResult> Details(DetailsViewModelQuery query)
{
var vm = await QueryDispatcher.Dispatch<DetailsViewModelQuery,
DetailsViewModel>(query);
return View("Details", vm);
}
The controller action method is very
thin, delegating immediately to the
query dispatcher to create the view
model.
The query definition may
be as simple as the Id of
the record to retrieve.
public class DetailsViewModelQueryHandler :
IQueryHandler<DetailsViewModelQuery, DetailsViewModel>
{
public async Task<DetailsViewModel> Retrieve
(DetailsViewModelQuery query)
{
ValidateArguments();
Context = Context ?? new ApplicationDbContext();
var result = new DetailsViewModel();
var question = await Context.Questions
.SingleOrDefaultAsync(x => x.Id == query.Id);
Mapper.Map(question, result);
return result;
}
Query handler queries the EF context
and maps the domain model object
to the view model.
EF context is
instantiated or passed in
via the constructor for
testing.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<RedirectToRouteResult> SignUpForActivity
(SignUpParticipantCommand command)
{
command.ParticipantId =
User.Identity.GetUserId();
command.AddedOn = DateTime.Now;
var commandResult = await CommandDispatcher.Dispatch(command);
if (commandResult.Success)
{
TempData["SignUpMessage"] = "Thank you for signing up. ";
}
else
{
// Handle failure of operation
}
return RedirectToAction("Details", new {id = command.ActivityId, });
}
Command is model bound
from form post, with
additional details set in code.
Again controller action method
delegates to the command
dispatcher execute the
command.

Recommended for you

Web App Mvc
Web App MvcWeb App Mvc
Web App Mvc
node.jsmvcjavascript
F# Eye for the C# Guy - DDD North 2013
F# Eye for the C# Guy - DDD North 2013F# Eye for the C# Guy - DDD North 2013
F# Eye for the C# Guy - DDD North 2013

This document discusses F# and how it compares to C#. It provides examples of how common programming tasks like defining classes, dependency injection, unit testing, mocking, and debugging are simpler in F#. F# is statically typed, functional-first, object-oriented, open source, and runs on .NET. Examples show how F# code for these tasks is shorter, easier to read, easier to refactor, and contains fewer bugs than equivalent C# code. The document promotes resources for learning more about F# and provides contact information.

c#f#
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrong

The document discusses best practices for testing Rails controllers. It recommends writing declarative tests that focus on authentication, authorization, resource presence, and responses. Shared examples should be used to DRY up tests for these "small details". Tests for "big actions" like fetching a resource can be simple. Business logic belongs in models, not controllers. ActiveModel makes it easy to extract logic out of controllers and into reusable classes. Overall, the goal is to keep controllers simple and focused on their main responsibilities by writing declarative, well-factored tests.

public class SignUpParticipantCommandHandler :
ICommandHandler<SignUpParticipantCommand>
{
public async Task<CommandResult> Execute
(SignUpParticipantCommand command)
{
ValidateArguments(command);
Context = Context ?? new ApplicationDbContext();
var result = new CommandResult();
var activity = await Context.Activities
.SingleOrDefaultAsync(x => x.Id == command.ActivityId);
var participant = await Context.Participants
.SingleOrDefaultAsync(x => x.Id == command.ParticipantId);
if (activity != null && participant != null)
{
...
Related entity details are
retrieved.
if (Context.ActivityParticipants
.SingleOrDefault(x => x.Activity.Id == command.ActivityId &&
x.Participant.Id == command.ParticipantId) == null)
{
if (activity.NumberOfPlaces > Context.ActivityParticipants
.Count(x => x.Activity.Id == command.ActivityId))
{
var activityParticipant = new ActivityParticipant(activity,
participant, command.AddedOn);
Context.ActivityParticipants.Add(activityParticipant);
await Context.SaveChangesAsync();
result.Success = true;
}
else
{
result.Success = false;
result.Message = "There are not enough places remaining";
}
...
Further checks are made on
the validity of the command
before execution.
}
else
{
result.Success = false;
result.Message = "Participant is already signed up";
}
}
else
{
result.Success = false;
result.Message = "Participant and/or activity not found";
}
return result;
}
}
Appropriate results with
status and error details are
provided to the calling code.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditViewModel vm)
{
if (ModelState.IsValid)
{
var command = new AddOrEditCommand();
Mapper.Map(vm, command);
var commandResult = await CommandDispatcher.Dispatch(command);
if (commandResult.Success)
{
var newId = (int)commandResult.Data;
// Do stuff with the generated Id of if we need to...
return RedirectToAction("Index");
}
}
return View("Edit", vm);
}
View model is model
bound and validated.
If something fails,
return to view.
If validation passes, map
the view model to a
command object.

Recommended for you

Focus on the outside, testing in ASP.NET MVC
Focus on the outside, testing in ASP.NET MVCFocus on the outside, testing in ASP.NET MVC
Focus on the outside, testing in ASP.NET MVC

First stab at some talk about testing in microsoft stuffs at enterprise companies without too much experience in TDD etc. Images are all pilfered from google with no rights, if anybody wants to issue a takedown just ping me and I'll replace them with another.

software testingasp.netmvc
ASP.NET MVC Fundamental
ASP.NET MVC FundamentalASP.NET MVC Fundamental
ASP.NET MVC Fundamental

This document provides an overview and introduction to ASP.NET MVC 3 training. It discusses the evolution of ASP.NET, key concepts of MVC like models, views, and controllers, how MVC works, and differences between MVC and web forms. The training will build a simple ASP.NET MVC application and cover controllers, models, views, routing, and action results.

asp.net mvc
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)

The document discusses how to develop event-driven microservices using event sourcing and Command Query Responsibility Segregation (CQRS). It describes event sourcing, where events are stored instead of the current application state. Services update their own state by subscribing to events. CQRS is used to separate read models from write models so that queries can be optimized with materialized views of aggregated data. Implementing queries in an event-sourced application involves using separate query-side microservices to update and retrieve materialized views based on domain events from the event store.

cqrscommand query responsibility segregationmicroservices
3. Unit testing our model,
queries and commands
Applying unit testing
• By moving logic into our domain model we’ve already
made that easier to test
• These have no dependencies so can simply be instantiated
with a known state before performing the operations under
test
• With the use of the CQRS mediator pattern, our thin
controllers mean there’s little value in testing them
• But we still have a logic that we should put under test in
our query and command handlers
• These handlers are closely tied to data access code,
specifically the use of Entity Framework
Unit testing Entity Framework
• Testing with a database
• Slow
• Brittle - as hard to maintain a known, isolated data set for
tests
• Testing with in-memory objects
• Of limited value as LINQ to Objects != LINQ to Entities
• Using Effort – an in-memory database generated on the
fly - written and maintained by Tamas Flamich
• http://effort.codeplex.com/
• Fast
• Mimics true behaviour of EF very closely
Unit testing with Effort
• Install via NuGet: PM> Install-Package Effort
• Instantiate an empty, memory backed EF context
• Seed the context with a known set of data
• Can use EF API for this
• Or for faster tests and with less code, load from CSV files
• Create an instance of the query or command handler,
passing in the in-memory context
• Execute the query or command
• Assert the query result is as expected or the command
operations have persisted

Recommended for you

Unit Testing in JavaScript with MVC and QUnit
Unit Testing in JavaScript with MVC and QUnitUnit Testing in JavaScript with MVC and QUnit
Unit Testing in JavaScript with MVC and QUnit

Lars Thorup presents on unit testing JavaScript applications with the MVC pattern and QUnit testing framework. He discusses testing views, controllers, models, and services. The document recommends setting up tests for each component in isolation by injecting stubs for their dependencies. Asynchronous testing is also covered, including techniques like stopping/starting to synchronize async calls in tests. The MVC pattern with dependency injection is advocated to make the code more modular and testable.

unit testingmodel-view-controllerqunit
Dapper + QueryObject
Dapper + QueryObjectDapper + QueryObject
Dapper + QueryObject

По материалам встречи http://ineta.ru/MPPC/Meeting/2013-03-20-18-30

dapperqueryobject
Laws of test automation framework
Laws of test automation frameworkLaws of test automation framework
Laws of test automation framework

The document discusses three "laws of test automation framework": 1) Test frameworks will continue growing unless changes are made, leading to complex step definitions and refactoring issues. 2) The more complex ("messy") a test framework becomes, the more effort is required to maintain it. 3) Changes to test frameworks can cause pushback from business and technical issues like merge conflicts and build failures. The document promotes a Model-View-Controller approach to structure Cucumber tests to improve code quality and maintainability. Declarative styles are preferable to imperative to make tests more robust to business changes. Regular monitoring, desk checks, and appropriate timing of changes can help address challenges.

laws of automation framework
[TestClass]
public class RoomViewModelQueryHandlerTests : BaseDataTest
{
[TestMethod]
public void SampleTest()
{
// Arrange
SetUpContextAndTestData();
var handler = new RoomViewModelQueryHandler(Context);
var query = new RoomViewModelQuery { Id = 1 };
// Act
var result = handler.Retrieve(query).Result;
// Assert
Assert.AreEqual("Kitchen", result.RoomDescription);
}
}
Instantiate handler passing
in in-memory, seeded
context
Retrieve the result
(the view model).
Assert the view model properties
public abstract class BaseDataTest
{
protected ProductEntities Context { get; private set; }
protected void SetUpContextAndTestData()
{
InitContext();
SeedData();
}
private void InitContext()
{
var connection =
Effort.EntityConnectionFactory
.CreateTransient("name=ProductEntities");
Context = new ProductEntities(connection);
}
...
Connection to in-memory
representation of EDMX meta-
data created.
An alternative method supports
the code-first approach
private void SeedData()
{
var categories = new List<Category>
{
new Category { Id = 1, Description = "Kitchens", },
new Category { Id = 2, Description = "Bedrooms", },
};
Context.Categories.AddRange(categories);
Context.SaveChanges();
}
}
Data seeded using EF API
(or CSV files can be used)
4. Wrap-up and Q&A

Recommended for you

ASP.NET Core Unit Testing
ASP.NET Core Unit TestingASP.NET Core Unit Testing
ASP.NET Core Unit Testing

Blog post: http://WakeUpAndCode.com/asp-net-core-testing Learn all about automated unit testing in ASP.NET Core 1.0 (formerly known as ASP.NET 5) and how you can set up Visual Studio so that you can quickly test your apps in the real world.

mockingautomated testingtesting
Introducción a DDD
Introducción a DDDIntroducción a DDD
Introducción a DDD

Este documento resume los conceptos clave del Domain-Driven Design (DDD), una metodología de desarrollo de software centrada en el dominio. Explica que DDD se enfoca en hacer que el modelo del dominio sea la parte central de la aplicación. También describe conceptos como el Lenguaje Ubícuo, la Ignorancia a la Persistencia, los Servicios del Dominio y los Repositorios. Finalmente, incluye una propuesta de arquitectura básica para implementar DDD con entidades, valores, agregados y factorías.

dddarquitectura
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC

This document discusses Domain-Driven Design (DDD) and how it can be applied to ASP.NET MVC projects. It covers DDD concepts like ubiquitous language, bounded contexts, entities, value objects, domain services, and domain events. It also discusses how to structure an MVC project to separate the domain model from the rest of the application using patterns like layered architecture and ports and adapters. The document argues that DDD can provide benefits like flexibility, manageable complexity, and centralized business logic, though it may require more time and effort to implement.

asp.netarchitecturedomain-driven design
In summary
• Even with a “light-touch” of architectural patterns we
have an application that provides
• Rich domain model or core
• Data access separated into discrete read and write
operations, adhering to the single responsibility principle
• Testable logic and data access code
• Whilst these patterns can be taken a lot further where
warranted, even for small-medium scale applications
there’s value in their use
Lastly, some thanks…
• To my colleagues at Zone
• Numerous discussions, questions and advice as we’ve
evolved techniques and technologies over the years
• To everyone sharing knowledge, opinions and
techniques
• Blogs, forum threads, talks and other community
contributions that have influenced the thinking behind our
work and this presentation
• Looking forward to more discussions this afternoon!
Provided as Creative Commons 3.0 Share Alike:
http://creativecommons.org/licenses/by-nc-sa/3.0/
DDD, CQRS and testing with ASP.Net MVC

Recommended for you

A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)

This document discusses a pattern language for microservices. It begins by introducing the speaker and agenda. The core patterns of monolithic architecture and microservices architecture are described. Microservices address drawbacks of monolithic architecture by decomposing into independent services, though this introduces complexity. The document then discusses patterns for distributed data management with microservices like database per service, event-driven architecture using event sourcing, and command query responsibility segregation for queries. It concludes that patterns are useful for thinking about, discussing, and applying technology like microservices.

command query responsibility segregationpatternsgluecon
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#

10 years after the release of the original book Domain Driven Design by Eric Evans we are seeing more and more applications built on the core concepts of DDD. Still, there is a long way to go before we fully grasp all its potential. First we need to change the way we do things in our projects. In this session I will show a possible implementation in C# that I've been using in many projects.

dddtalkarchitecture
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)

Microservices are an essential enabler of agility but developing and deploying them is a challenge. In order for microservices to be loosely coupled,each service must have its own datastore. This makes it difficult to maintain data consistency across services. Deploying microservices is also a complex problem since an application typically consists of 10s or 100s of services, written in a variety of languages and frameworks. In this presentation, you will learn how to solve these problems by using an event-driven architecture to maintain data consistency and by using Docker to simplify deployment.

event-driven architecturemicroservicesevent sourcing
webnextconf.eu

More Related Content

What's hot

Introduction to Docker - 2017
Introduction to Docker - 2017Introduction to Docker - 2017
Introduction to Docker - 2017
Docker, Inc.
 
An Introduction To Jenkins
An Introduction To JenkinsAn Introduction To Jenkins
An Introduction To Jenkins
Knoldus Inc.
 
Intro to containerization
Intro to containerizationIntro to containerization
Intro to containerization
Balint Pato
 
8 - OpenShift - A look at a container platform: what's in the box
8 - OpenShift - A look at a container platform: what's in the box8 - OpenShift - A look at a container platform: what's in the box
8 - OpenShift - A look at a container platform: what's in the box
Kangaroot
 
Docker
DockerDocker
Docker Online Meetup #22: Docker Networking
Docker Online Meetup #22: Docker NetworkingDocker Online Meetup #22: Docker Networking
Docker Online Meetup #22: Docker Networking
Docker, Inc.
 
1. Docker Introduction.pdf
1. Docker Introduction.pdf1. Docker Introduction.pdf
1. Docker Introduction.pdf
AmarGautam15
 
Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker Compose
Ajeet Singh Raina
 
Docker Container Introduction
Docker Container IntroductionDocker Container Introduction
Docker Container Introduction
Innfinision Cloud and BigData Solutions
 
Elasticsearch Monitoring in Openshift
Elasticsearch Monitoring in OpenshiftElasticsearch Monitoring in Openshift
Elasticsearch Monitoring in Openshift
Lukas Vlcek
 
Oracle Cloud deployment with Terraform
Oracle Cloud deployment with TerraformOracle Cloud deployment with Terraform
Oracle Cloud deployment with Terraform
Stefan Oehrli
 
Ansible
AnsibleAnsible
Ansible
Knoldus Inc.
 
Communication in a Microservice Architecture
Communication in a Microservice ArchitectureCommunication in a Microservice Architecture
Communication in a Microservice Architecture
Per Bernhardt
 
Quarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java frameworkQuarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java framework
SVDevOps
 
Introduction to jenkins
Introduction to jenkinsIntroduction to jenkins
Introduction to jenkins
Abe Diaz
 
Finite State Queries In Lucene
Finite State Queries In LuceneFinite State Queries In Lucene
Finite State Queries In Lucene
otisg
 
Jenkins
JenkinsJenkins
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
Arawn Park
 
Battle of the frameworks : Quarkus vs SpringBoot
Battle of the frameworks : Quarkus vs SpringBootBattle of the frameworks : Quarkus vs SpringBoot
Battle of the frameworks : Quarkus vs SpringBoot
Christos Sotiriou
 
Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applications
Fabricio Epaminondas
 

What's hot (20)

Introduction to Docker - 2017
Introduction to Docker - 2017Introduction to Docker - 2017
Introduction to Docker - 2017
 
An Introduction To Jenkins
An Introduction To JenkinsAn Introduction To Jenkins
An Introduction To Jenkins
 
Intro to containerization
Intro to containerizationIntro to containerization
Intro to containerization
 
8 - OpenShift - A look at a container platform: what's in the box
8 - OpenShift - A look at a container platform: what's in the box8 - OpenShift - A look at a container platform: what's in the box
8 - OpenShift - A look at a container platform: what's in the box
 
Docker
DockerDocker
Docker
 
Docker Online Meetup #22: Docker Networking
Docker Online Meetup #22: Docker NetworkingDocker Online Meetup #22: Docker Networking
Docker Online Meetup #22: Docker Networking
 
1. Docker Introduction.pdf
1. Docker Introduction.pdf1. Docker Introduction.pdf
1. Docker Introduction.pdf
 
Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker Compose
 
Docker Container Introduction
Docker Container IntroductionDocker Container Introduction
Docker Container Introduction
 
Elasticsearch Monitoring in Openshift
Elasticsearch Monitoring in OpenshiftElasticsearch Monitoring in Openshift
Elasticsearch Monitoring in Openshift
 
Oracle Cloud deployment with Terraform
Oracle Cloud deployment with TerraformOracle Cloud deployment with Terraform
Oracle Cloud deployment with Terraform
 
Ansible
AnsibleAnsible
Ansible
 
Communication in a Microservice Architecture
Communication in a Microservice ArchitectureCommunication in a Microservice Architecture
Communication in a Microservice Architecture
 
Quarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java frameworkQuarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java framework
 
Introduction to jenkins
Introduction to jenkinsIntroduction to jenkins
Introduction to jenkins
 
Finite State Queries In Lucene
Finite State Queries In LuceneFinite State Queries In Lucene
Finite State Queries In Lucene
 
Jenkins
JenkinsJenkins
Jenkins
 
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
 
Battle of the frameworks : Quarkus vs SpringBoot
Battle of the frameworks : Quarkus vs SpringBootBattle of the frameworks : Quarkus vs SpringBoot
Battle of the frameworks : Quarkus vs SpringBoot
 
Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applications
 

Viewers also liked

CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафор
Alexander Byndyu
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC
topascz
 
DDD (Domain-Driven Design)
DDD (Domain-Driven Design)DDD (Domain-Driven Design)
DDD (Domain-Driven Design)
Senior Dev
 
DDD Sydney 20111 Razor Session
DDD Sydney 20111 Razor SessionDDD Sydney 20111 Razor Session
DDD Sydney 20111 Razor Session
Mohamed Meligy
 
F# Eye for the C# Guy - DDD North 2013
F# Eye for the C# Guy - DDD North 2013F# Eye for the C# Guy - DDD North 2013
F# Eye for the C# Guy - DDD North 2013
Phillip Trelford
 
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrong
johnnygroundwork
 
Focus on the outside, testing in ASP.NET MVC
Focus on the outside, testing in ASP.NET MVCFocus on the outside, testing in ASP.NET MVC
Focus on the outside, testing in ASP.NET MVC
Rob Ashton
 
ASP.NET MVC Fundamental
ASP.NET MVC FundamentalASP.NET MVC Fundamental
ASP.NET MVC Fundamental
ldcphuc
 
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Chris Richardson
 
Unit Testing in JavaScript with MVC and QUnit
Unit Testing in JavaScript with MVC and QUnitUnit Testing in JavaScript with MVC and QUnit
Unit Testing in JavaScript with MVC and QUnit
Lars Thorup
 
Dapper + QueryObject
Dapper + QueryObjectDapper + QueryObject
Dapper + QueryObject
Alexander Byndyu
 
Laws of test automation framework
Laws of test automation frameworkLaws of test automation framework
Laws of test automation framework
vodqancr
 
ASP.NET Core Unit Testing
ASP.NET Core Unit TestingASP.NET Core Unit Testing
ASP.NET Core Unit Testing
Shahed Chowdhuri
 
Introducción a DDD
Introducción a DDDIntroducción a DDD
Introducción a DDD
sergiopolo
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC
Steven Smith
 
A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)
Chris Richardson
 
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#
Pascal Laurin
 
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)
Chris Richardson
 
Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)
Chris Richardson
 

Viewers also liked (20)

CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафор
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC
 
DDD (Domain-Driven Design)
DDD (Domain-Driven Design)DDD (Domain-Driven Design)
DDD (Domain-Driven Design)
 
DDD Sydney 20111 Razor Session
DDD Sydney 20111 Razor SessionDDD Sydney 20111 Razor Session
DDD Sydney 20111 Razor Session
 
Web App Mvc
Web App MvcWeb App Mvc
Web App Mvc
 
F# Eye for the C# Guy - DDD North 2013
F# Eye for the C# Guy - DDD North 2013F# Eye for the C# Guy - DDD North 2013
F# Eye for the C# Guy - DDD North 2013
 
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrong
 
Focus on the outside, testing in ASP.NET MVC
Focus on the outside, testing in ASP.NET MVCFocus on the outside, testing in ASP.NET MVC
Focus on the outside, testing in ASP.NET MVC
 
ASP.NET MVC Fundamental
ASP.NET MVC FundamentalASP.NET MVC Fundamental
ASP.NET MVC Fundamental
 
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
Developing Event-driven Microservices with Event Sourcing & CQRS (gotoams)
 
Unit Testing in JavaScript with MVC and QUnit
Unit Testing in JavaScript with MVC and QUnitUnit Testing in JavaScript with MVC and QUnit
Unit Testing in JavaScript with MVC and QUnit
 
Dapper + QueryObject
Dapper + QueryObjectDapper + QueryObject
Dapper + QueryObject
 
Laws of test automation framework
Laws of test automation frameworkLaws of test automation framework
Laws of test automation framework
 
ASP.NET Core Unit Testing
ASP.NET Core Unit TestingASP.NET Core Unit Testing
ASP.NET Core Unit Testing
 
Introducción a DDD
Introducción a DDDIntroducción a DDD
Introducción a DDD
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC
 
A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)
 
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#
 
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)
 
Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)
 

Similar to DDD, CQRS and testing with ASP.Net MVC

CQRS and Event Sourcing
CQRS and Event SourcingCQRS and Event Sourcing
CQRS and Event Sourcing
Sergey Seletsky
 
Getting started with MVC 5 and Visual Studio 2013
Getting started with MVC 5 and Visual Studio 2013Getting started with MVC 5 and Visual Studio 2013
Getting started with MVC 5 and Visual Studio 2013
Thomas Robbins
 
Intro to ColdBox MVC at Japan CFUG
Intro to ColdBox MVC at Japan CFUGIntro to ColdBox MVC at Japan CFUG
Intro to ColdBox MVC at Japan CFUG
Ortus Solutions, Corp
 
2011 NetUG HH: ASP.NET MVC & HTML 5
2011 NetUG HH: ASP.NET MVC & HTML 52011 NetUG HH: ASP.NET MVC & HTML 5
2011 NetUG HH: ASP.NET MVC & HTML 5
Daniel Fisher
 
Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...
Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...
Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...
Alex Maclinovsky
 
ASP.NET MVC 2.0
ASP.NET MVC 2.0ASP.NET MVC 2.0
ASP.NET MVC 2.0
Buu Nguyen
 
Divide and Conquer – Microservices with Node.js
Divide and Conquer – Microservices with Node.jsDivide and Conquer – Microservices with Node.js
Divide and Conquer – Microservices with Node.js
Sebastian Springer
 
Asp 1a-aspnetmvc
Asp 1a-aspnetmvcAsp 1a-aspnetmvc
Asp 1a-aspnetmvc
Fajar Baskoro
 
Aspnetmvc 1
Aspnetmvc 1Aspnetmvc 1
Aspnetmvc 1
Fajar Baskoro
 
Asp.net mvc presentation by Nitin Sawant
Asp.net mvc presentation by Nitin SawantAsp.net mvc presentation by Nitin Sawant
Asp.net mvc presentation by Nitin Sawant
Nitin Sawant
 
Tdd,Ioc
Tdd,IocTdd,Ioc
ASP.NET MVC 5 - EF 6 - VS2015
ASP.NET MVC 5 - EF 6 - VS2015ASP.NET MVC 5 - EF 6 - VS2015
ASP.NET MVC 5 - EF 6 - VS2015
Hossein Zahed
 
Mcknight well built extensions
Mcknight well built extensionsMcknight well built extensions
Mcknight well built extensions
Richard McKnight
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, Ciklum
Alina Vilk
 
Novedades de MongoDB 3.6
Novedades de MongoDB 3.6Novedades de MongoDB 3.6
Novedades de MongoDB 3.6
MongoDB
 
Architecting for Microservices Part 2
Architecting for Microservices Part 2Architecting for Microservices Part 2
Architecting for Microservices Part 2
Elana Krasner
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO Devs
WO Community
 
El camino a las Cloud Native Apps - Introduction
El camino a las Cloud Native Apps - IntroductionEl camino a las Cloud Native Apps - Introduction
El camino a las Cloud Native Apps - Introduction
Plain Concepts
 
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
CodeMill digital skills
 
Elements for an iOS Backend
Elements for an iOS BackendElements for an iOS Backend
Elements for an iOS Backend
Laurent Cerveau
 

Similar to DDD, CQRS and testing with ASP.Net MVC (20)

CQRS and Event Sourcing
CQRS and Event SourcingCQRS and Event Sourcing
CQRS and Event Sourcing
 
Getting started with MVC 5 and Visual Studio 2013
Getting started with MVC 5 and Visual Studio 2013Getting started with MVC 5 and Visual Studio 2013
Getting started with MVC 5 and Visual Studio 2013
 
Intro to ColdBox MVC at Japan CFUG
Intro to ColdBox MVC at Japan CFUGIntro to ColdBox MVC at Japan CFUG
Intro to ColdBox MVC at Japan CFUG
 
2011 NetUG HH: ASP.NET MVC & HTML 5
2011 NetUG HH: ASP.NET MVC & HTML 52011 NetUG HH: ASP.NET MVC & HTML 5
2011 NetUG HH: ASP.NET MVC & HTML 5
 
Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...
Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...
Three Degrees of Mediation: Challenges and Lessons in building Cloud-agnostic...
 
ASP.NET MVC 2.0
ASP.NET MVC 2.0ASP.NET MVC 2.0
ASP.NET MVC 2.0
 
Divide and Conquer – Microservices with Node.js
Divide and Conquer – Microservices with Node.jsDivide and Conquer – Microservices with Node.js
Divide and Conquer – Microservices with Node.js
 
Asp 1a-aspnetmvc
Asp 1a-aspnetmvcAsp 1a-aspnetmvc
Asp 1a-aspnetmvc
 
Aspnetmvc 1
Aspnetmvc 1Aspnetmvc 1
Aspnetmvc 1
 
Asp.net mvc presentation by Nitin Sawant
Asp.net mvc presentation by Nitin SawantAsp.net mvc presentation by Nitin Sawant
Asp.net mvc presentation by Nitin Sawant
 
Tdd,Ioc
Tdd,IocTdd,Ioc
Tdd,Ioc
 
ASP.NET MVC 5 - EF 6 - VS2015
ASP.NET MVC 5 - EF 6 - VS2015ASP.NET MVC 5 - EF 6 - VS2015
ASP.NET MVC 5 - EF 6 - VS2015
 
Mcknight well built extensions
Mcknight well built extensionsMcknight well built extensions
Mcknight well built extensions
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, Ciklum
 
Novedades de MongoDB 3.6
Novedades de MongoDB 3.6Novedades de MongoDB 3.6
Novedades de MongoDB 3.6
 
Architecting for Microservices Part 2
Architecting for Microservices Part 2Architecting for Microservices Part 2
Architecting for Microservices Part 2
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO Devs
 
El camino a las Cloud Native Apps - Introduction
El camino a las Cloud Native Apps - IntroductionEl camino a las Cloud Native Apps - Introduction
El camino a las Cloud Native Apps - Introduction
 
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
Containerisation Hack of a Legacy Software Solution - Alex Carter - CodeMill ...
 
Elements for an iOS Backend
Elements for an iOS BackendElements for an iOS Backend
Elements for an iOS Backend
 

Recently uploaded

INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdfINDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
jackson110191
 
Quality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of TimeQuality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of Time
Aurora Consulting
 
How RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptxHow RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptx
SynapseIndia
 
The Increasing Use of the National Research Platform by the CSU Campuses
The Increasing Use of the National Research Platform by the CSU CampusesThe Increasing Use of the National Research Platform by the CSU Campuses
The Increasing Use of the National Research Platform by the CSU Campuses
Larry Smarr
 
20240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 202420240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 2024
Matthew Sinclair
 
Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
Tatiana Al-Chueyr
 
DealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 editionDealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 edition
Yevgen Sysoyev
 
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly DetectionAdvanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
Bert Blevins
 
Mitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing SystemsMitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing Systems
ScyllaDB
 
20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf
Sally Laouacheria
 
Implementations of Fused Deposition Modeling in real world
Implementations of Fused Deposition Modeling  in real worldImplementations of Fused Deposition Modeling  in real world
Implementations of Fused Deposition Modeling in real world
Emerging Tech
 
Recent Advancements in the NIST-JARVIS Infrastructure
Recent Advancements in the NIST-JARVIS InfrastructureRecent Advancements in the NIST-JARVIS Infrastructure
Recent Advancements in the NIST-JARVIS Infrastructure
KAMAL CHOUDHARY
 
Active Inference is a veryyyyyyyyyyyyyyyyyyyyyyyy
Active Inference is a veryyyyyyyyyyyyyyyyyyyyyyyyActive Inference is a veryyyyyyyyyyyyyyyyyyyyyyyy
Active Inference is a veryyyyyyyyyyyyyyyyyyyyyyyy
RaminGhanbari2
 
Research Directions for Cross Reality Interfaces
Research Directions for Cross Reality InterfacesResearch Directions for Cross Reality Interfaces
Research Directions for Cross Reality Interfaces
Mark Billinghurst
 
Observability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetryObservability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetry
Eric D. Schabell
 
find out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challengesfind out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challenges
huseindihon
 
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdfWhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
ArgaBisma
 
7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf
Enterprise Wired
 
Coordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar SlidesCoordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar Slides
Safe Software
 
Measuring the Impact of Network Latency at Twitter
Measuring the Impact of Network Latency at TwitterMeasuring the Impact of Network Latency at Twitter
Measuring the Impact of Network Latency at Twitter
ScyllaDB
 

Recently uploaded (20)

INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdfINDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
 
Quality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of TimeQuality Patents: Patents That Stand the Test of Time
Quality Patents: Patents That Stand the Test of Time
 
How RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptxHow RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptx
 
The Increasing Use of the National Research Platform by the CSU Campuses
The Increasing Use of the National Research Platform by the CSU CampusesThe Increasing Use of the National Research Platform by the CSU Campuses
The Increasing Use of the National Research Platform by the CSU Campuses
 
20240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 202420240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 2024
 
Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
 
DealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 editionDealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 edition
 
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly DetectionAdvanced Techniques for Cyber Security Analysis and Anomaly Detection
Advanced Techniques for Cyber Security Analysis and Anomaly Detection
 
Mitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing SystemsMitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing Systems
 
20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf
 
Implementations of Fused Deposition Modeling in real world
Implementations of Fused Deposition Modeling  in real worldImplementations of Fused Deposition Modeling  in real world
Implementations of Fused Deposition Modeling in real world
 
Recent Advancements in the NIST-JARVIS Infrastructure
Recent Advancements in the NIST-JARVIS InfrastructureRecent Advancements in the NIST-JARVIS Infrastructure
Recent Advancements in the NIST-JARVIS Infrastructure
 
Active Inference is a veryyyyyyyyyyyyyyyyyyyyyyyy
Active Inference is a veryyyyyyyyyyyyyyyyyyyyyyyyActive Inference is a veryyyyyyyyyyyyyyyyyyyyyyyy
Active Inference is a veryyyyyyyyyyyyyyyyyyyyyyyy
 
Research Directions for Cross Reality Interfaces
Research Directions for Cross Reality InterfacesResearch Directions for Cross Reality Interfaces
Research Directions for Cross Reality Interfaces
 
Observability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetryObservability For You and Me with OpenTelemetry
Observability For You and Me with OpenTelemetry
 
find out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challengesfind out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challenges
 
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdfWhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
WhatsApp Image 2024-03-27 at 08.19.52_bfd93109.pdf
 
7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf
 
Coordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar SlidesCoordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar Slides
 
Measuring the Impact of Network Latency at Twitter
Measuring the Impact of Network Latency at TwitterMeasuring the Impact of Network Latency at Twitter
Measuring the Impact of Network Latency at Twitter
 

DDD, CQRS and testing with ASP.Net MVC

  • 2. Just to introduce myself… • I’m Andy Butland • Blog (sporadically) at http://web-matters.blogspot.it/ • Find here a copy of slides and links to various resources • Contact: abutland73@gmail.com / @andybutland • I work for Zone – www.thisiszone.com - a digital agency where I’m head of .NET development • We develop web sites and applications using ASP.Net MVC and CMS platforms such as Umbraco and EPiServer • We’re primarily UK based, in London and Bristol • But I’m lucky enough to live…
  • 3. … here, in Bassano del Grappa, Italy
  • 4. And what are we talking about… • We’ll be discussing some practices I follow when building web applications using ASP.Net MVC • Digested and adapted from various opinions • Adopting best practices but in a practical way • For me at least… leads to a nicely organised, testable and maintainable code base
  • 5. Standing on the shoulders… • Much of what follows comes from various speakers, bloggers and writers in the .Net community • Finally read “Domain Driven Design” by Eric Evans • Rob Conery questioned some of practices around use of repositories • Blog series on DDD, CQRS and other MVC practices from Jimmy Bogard and Gabriel Schenker at lostechies.com • Julie Lerman’s articles on DDD with Entity Framework at MSDN • Adam Tibi’s implementation of a CQRS pattern using the IoC container Ninject was heavily borrowed for my own use
  • 6. Contents 1 2 3 4 DDD with ASP.Net MVC and Entity Framework CQRS using a mediator pattern Wrap up and Q&A Unit testing our model, queries and commands
  • 7. 1. DDD with ASP.Net MVC and Entity Framework
  • 8. Domain driven design (DDD) • Close replication of the real-world, business problem • Focussed on an appropriate area of application responsibility – the “bounded context” • Sharing of domain knowledge and vocabulary between business experts, developers and, importantly, the software itself – the “ubiquitous language”
  • 9. A rich domain model • In essence, a DDD approach looks to push more logic and behaviour to the application’s core model classes • Contrasted with an “anaemic” domain model • Consider the domain as an “API” that you provide to the rest of the application – providing appropriate access points and retaining control • Lean more on code and less on SQL/data access • More expressive, easier to write and maintain – and test • But careful balance needed as can’t forget performance
  • 10. Control via the constructor • Avoid a public, parameterless, default constructor • Prevents the instantiation of invalid objects by application code via the {} syntax, e.g. var product = new Product { Name = “Test product” };
  • 11. private Question() { Options = new List<QuestionOption>(); } public Question(string code, string text, int orderInSection, QuestionSection section, QuestionType type) : this() { Code = code; Text = text; OrderInSection = orderInSection; Section = section; Type = type; } EF requires a parameter-less constructor, but it can be private. By requiring the rest of the application to only call this constructor, we can ensure we have a valid initialisation of an instance.
  • 12. Control of property access • Use private property setters to prevent direct access to properties • Prevents the modification of an instance into an invalid state • Instead provide validated methods to allow related property values to be set together, ensuring a consistent state is maintained
  • 13. public int? NumericalMin { get; private set; } public int? NumericalMax { get; private set; } public void SetNumericalRange(int min, int max) { if (min > max) { throw new ArgumentException( “Max parameter must be greater than the min parameter."); } NumericalMin = min; NumericalMax = max; } Properties can’t be set directly Instead a method must be called, which can validate and ensure related properties are populated together.
  • 14. Move behaviour into the model • Where possible implement business logic in the domain model objects • Object graph must be populated sufficiently to support the behaviour • Being POCO classes, there are no dependencies that complicate unit testing
  • 15. public int GetMaximumAvailableScore() { if (Type.Id == (int)QuestionTypeId.MultipleSelect) { return Options.Sum(x => x.Score); } else if (Type.Id == (int)QuestionTypeId.SingleSelect) { return Options.Max(x => x.Score); } else { return 0; } } Logic can be encapsulated in methods…
  • 16. [TestMethod] public void Question_GetMaximumScoreForMultiSelect_ReturnsCorrectValue() { // Arrange var question = CreateMultiSelectQuestion(); // Act var maxScore = question.GetMaximumAvailableScore(); // Assert Assert.AreEqual(8, maxScore); } … which can be easily unit tested.
  • 17. 2. CQRS using a mediator pattern
  • 18. Command Query Responsibility Segregation • In essence, CQRS involves a separation between read and write operations in an application • At scale we may have separate models – one highly cached and de-normalised for reads, and a strict, validated model for writes • Related concepts – “event sourcing”, “eventual consistency” – may be appropriate in certain situations • Even for small to medium scale applications though, CQRS has benefits over a more typical CRUD style
  • 19. Benefits of CQRS • “Slices over layers” – breaking down application by features rather than technical tiers • More meaningful data operations over CRUD using the “ubiquitous language” • e.g. “ShipOrderCommand” versus “SaveOrder(Order order)” • Single, discrete transactions with the ORM • More… but smaller, more focussed and single responsibility principle adhering classes
  • 20. MVC CQRS Pattern: Reads CONTROLLER VIEW VIEW MODEL VIEW MODEL QUERY HANDLER VIEW MODEL QUERY DATABASE Retrieve domain model objects via the Entity Framework context Map to view model using AutoMapper View model passed to strongly typed view Query passed as a GET parameter to the controller action method: • Might be a simple Id • Or something more complex for a search feature QUERY DISPATCHER Controller calls query dispatcher passing query. Appropriate query handler is found from view model and query types (using Ninject)
  • 21. MVC CQRS Pattern: Writes CONTROLLER COMMAND RESULT COMMAND HANDLER COMMAND DATABASE Retrieve and update domain model objects and persist via the EF context Simple command result is returned (success flag, error message and - sometimes - return data). Command may be POSTed as a parameter to the controller action method or created within the method COMMAND DISPATCHER Controller calls command dispatcher passing command. Appropriate command handler is found from command type (using Ninject)
  • 22. MVC CQRS Pattern: Validated Writes CONTROLLER COMMAND RESULT COMMAND HANDLER COMMAND DATABASE Map to domain model objects and persist via the Entity Framework context Simple command result is returned Validated view model is mapped to command COMMAND DISPATCHER Controller calls command dispatcher passing command. Appropriate command handler is found from command type (using Ninject) VIEW MODEL VIEW View model is model bound to controller action method from form POST and validated. In case of validation error, view model is re-populated and returned to view.
  • 23. public abstract class BaseController : Controller { public BaseController(IQueryDispatcher queryDispatcher, ICommandDispatcher commandDispatcher) { QueryDispatcher = queryDispatcher; CommandDispatcher = commandDispatcher; } } Base controller has injected dependencies for dispatching queries and commands. All controllers inherit from this.
  • 24. private static void RegisterServices(IKernel kernel) { kernel.Bind<IQueryDispatcher>().To<QueryDispatcher>(); kernel.Bind<ICommandDispatcher>().To<CommandDispatcher>(); kernel.Bind(x => x .FromAssembliesMatching(“MyApplication.dll") .SelectAllClasses().InheritedFrom(typeof(IQueryHandler<,>)) .BindAllInterfaces()); kernel.Bind(x => x .FromAssembliesMatching(“MyApplication.dll") .SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>)) .BindAllInterfaces()); } Resolved using Ninject IoC container Which also handles the convention based matching of the appropriate handler to each query and command
  • 25. public interface IQueryDispatcher { Task<TResult> Dispatch<TParameter, TResult>(TParameter query) where TParameter : IQuery where TResult : IQueryResult; } The query dispatcher has a single method that takes two type parameters: the query definition and the query result. It takes the query definition as the argument and asynchronously returns the result.
  • 26. public class QueryDispatcher : IQueryDispatcher { private readonly IKernel _kernel; public QueryDispatcher(IKernel kernel) { _kernel = kernel; } public async Task<TResult> Dispatch<TParameter, TResult> (TParameter query) where TParameter : IQuery where TResult : IQueryResult { var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>(); return await handler.Retrieve(query); } } The implementation retrieves the appropriate handler based on the type parameters from the services registered with the Ninject IoC container.
  • 27. public interface ICommandDispatcher { Task<CommandResult> Dispatch<TParameter>(TParameter command) where TParameter : ICommand; } Similarly the command dispatcher has a single method that takes a single type parameters: the command definition. It takes the command definition as the argument, asynchronously process it and return a status result.
  • 28. public class CommandDispatcher : ICommandDispatcher { private readonly IKernel _kernel; public CommandDispatcher(IKernel kernel) { _kernel = kernel; } public async Task<CommandResult> Dispatch<TParameter> (TParameter command) where TParameter : ICommand { var handler = _kernel.Get<ICommandHandler<TParameter>>(); return await handler.Execute(command); } } The implementation retrieves the appropriate handler based on the type parameter from the services registered with the Ninject IoC container.
  • 29. public class CommandResult { public bool Success { get; set; } public string Message { get; set; } public object Data { get; set; } } The simple command result usually just returns the status of the command. On occasion it’s useful to return some data, most often the Id of a newly generated record.
  • 30. public async Task<ViewResult> Details(DetailsViewModelQuery query) { var vm = await QueryDispatcher.Dispatch<DetailsViewModelQuery, DetailsViewModel>(query); return View("Details", vm); } The controller action method is very thin, delegating immediately to the query dispatcher to create the view model. The query definition may be as simple as the Id of the record to retrieve.
  • 31. public class DetailsViewModelQueryHandler : IQueryHandler<DetailsViewModelQuery, DetailsViewModel> { public async Task<DetailsViewModel> Retrieve (DetailsViewModelQuery query) { ValidateArguments(); Context = Context ?? new ApplicationDbContext(); var result = new DetailsViewModel(); var question = await Context.Questions .SingleOrDefaultAsync(x => x.Id == query.Id); Mapper.Map(question, result); return result; } Query handler queries the EF context and maps the domain model object to the view model. EF context is instantiated or passed in via the constructor for testing.
  • 32. [HttpPost] [ValidateAntiForgeryToken] public async Task<RedirectToRouteResult> SignUpForActivity (SignUpParticipantCommand command) { command.ParticipantId = User.Identity.GetUserId(); command.AddedOn = DateTime.Now; var commandResult = await CommandDispatcher.Dispatch(command); if (commandResult.Success) { TempData["SignUpMessage"] = "Thank you for signing up. "; } else { // Handle failure of operation } return RedirectToAction("Details", new {id = command.ActivityId, }); } Command is model bound from form post, with additional details set in code. Again controller action method delegates to the command dispatcher execute the command.
  • 33. public class SignUpParticipantCommandHandler : ICommandHandler<SignUpParticipantCommand> { public async Task<CommandResult> Execute (SignUpParticipantCommand command) { ValidateArguments(command); Context = Context ?? new ApplicationDbContext(); var result = new CommandResult(); var activity = await Context.Activities .SingleOrDefaultAsync(x => x.Id == command.ActivityId); var participant = await Context.Participants .SingleOrDefaultAsync(x => x.Id == command.ParticipantId); if (activity != null && participant != null) { ... Related entity details are retrieved.
  • 34. if (Context.ActivityParticipants .SingleOrDefault(x => x.Activity.Id == command.ActivityId && x.Participant.Id == command.ParticipantId) == null) { if (activity.NumberOfPlaces > Context.ActivityParticipants .Count(x => x.Activity.Id == command.ActivityId)) { var activityParticipant = new ActivityParticipant(activity, participant, command.AddedOn); Context.ActivityParticipants.Add(activityParticipant); await Context.SaveChangesAsync(); result.Success = true; } else { result.Success = false; result.Message = "There are not enough places remaining"; } ... Further checks are made on the validity of the command before execution.
  • 35. } else { result.Success = false; result.Message = "Participant is already signed up"; } } else { result.Success = false; result.Message = "Participant and/or activity not found"; } return result; } } Appropriate results with status and error details are provided to the calling code.
  • 36. [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Edit(EditViewModel vm) { if (ModelState.IsValid) { var command = new AddOrEditCommand(); Mapper.Map(vm, command); var commandResult = await CommandDispatcher.Dispatch(command); if (commandResult.Success) { var newId = (int)commandResult.Data; // Do stuff with the generated Id of if we need to... return RedirectToAction("Index"); } } return View("Edit", vm); } View model is model bound and validated. If something fails, return to view. If validation passes, map the view model to a command object.
  • 37. 3. Unit testing our model, queries and commands
  • 38. Applying unit testing • By moving logic into our domain model we’ve already made that easier to test • These have no dependencies so can simply be instantiated with a known state before performing the operations under test • With the use of the CQRS mediator pattern, our thin controllers mean there’s little value in testing them • But we still have a logic that we should put under test in our query and command handlers • These handlers are closely tied to data access code, specifically the use of Entity Framework
  • 39. Unit testing Entity Framework • Testing with a database • Slow • Brittle - as hard to maintain a known, isolated data set for tests • Testing with in-memory objects • Of limited value as LINQ to Objects != LINQ to Entities • Using Effort – an in-memory database generated on the fly - written and maintained by Tamas Flamich • http://effort.codeplex.com/ • Fast • Mimics true behaviour of EF very closely
  • 40. Unit testing with Effort • Install via NuGet: PM> Install-Package Effort • Instantiate an empty, memory backed EF context • Seed the context with a known set of data • Can use EF API for this • Or for faster tests and with less code, load from CSV files • Create an instance of the query or command handler, passing in the in-memory context • Execute the query or command • Assert the query result is as expected or the command operations have persisted
  • 41. [TestClass] public class RoomViewModelQueryHandlerTests : BaseDataTest { [TestMethod] public void SampleTest() { // Arrange SetUpContextAndTestData(); var handler = new RoomViewModelQueryHandler(Context); var query = new RoomViewModelQuery { Id = 1 }; // Act var result = handler.Retrieve(query).Result; // Assert Assert.AreEqual("Kitchen", result.RoomDescription); } } Instantiate handler passing in in-memory, seeded context Retrieve the result (the view model). Assert the view model properties
  • 42. public abstract class BaseDataTest { protected ProductEntities Context { get; private set; } protected void SetUpContextAndTestData() { InitContext(); SeedData(); } private void InitContext() { var connection = Effort.EntityConnectionFactory .CreateTransient("name=ProductEntities"); Context = new ProductEntities(connection); } ... Connection to in-memory representation of EDMX meta- data created. An alternative method supports the code-first approach
  • 43. private void SeedData() { var categories = new List<Category> { new Category { Id = 1, Description = "Kitchens", }, new Category { Id = 2, Description = "Bedrooms", }, }; Context.Categories.AddRange(categories); Context.SaveChanges(); } } Data seeded using EF API (or CSV files can be used)
  • 45. In summary • Even with a “light-touch” of architectural patterns we have an application that provides • Rich domain model or core • Data access separated into discrete read and write operations, adhering to the single responsibility principle • Testable logic and data access code • Whilst these patterns can be taken a lot further where warranted, even for small-medium scale applications there’s value in their use
  • 46. Lastly, some thanks… • To my colleagues at Zone • Numerous discussions, questions and advice as we’ve evolved techniques and technologies over the years • To everyone sharing knowledge, opinions and techniques • Blogs, forum threads, talks and other community contributions that have influenced the thinking behind our work and this presentation • Looking forward to more discussions this afternoon!
  • 47. Provided as Creative Commons 3.0 Share Alike: http://creativecommons.org/licenses/by-nc-sa/3.0/