Domain Events With Convention-Based Registration And Deferred Execution Support

In DDD, we establish bounded contexts and define how they will exchange information, which often occurs by raising events. According to Eric Evans, you should :

“Describe the points of contact between the models, outlining explicit translation for any communication and highlighting any sharing.”

These contexts will often communicate as part of a same database transaction. That’s actually desired, since it will assure integrity between the whole process. However, in the real world things can be tricky. Some actions might depend on committed transactions in order to get triggered. This happens, for instance, to services that run outside of the ongoing database transaction. You don’t want to send an email to notify the user that something changed and have the whole operation rolled back seconds later. Same thing happens when our application consume distributed services that do not support distributed transactions.

What We Want To Achieve

Let’s see our main goals. There are many good ways to implement domain event handlers. This implementation will use a dependency container to control the lifetime of the events raiser, it will register events with the container on a very transparent way and support delayed execution. Let’s review :

Effortless registration

In order to create a new handler for an event, we don’t want to look for a distant class in another project that has hundreds of event-to-handler bindings and add new lines. To that end, we might want to consider to use a dependency container.

Deferred execution support

Handlers that invoke code that are not bound to a transaction should be fired only once the transaction is committed.

Practical Example : Paying an Order on an E-Commerce App

Let’s take as example the payment of an order on an e-commerce application. Once the payment is processed, it raises an event. Then, the bounded context that processes customers orders handles the event and places the order for shipment. Furthermore, the bounded context that manages the inventory handles the same event to subtract from the stock the items that were ordered.

Domain-Events-01.png

Created with Balsamiq Mockups.

Firing The Event

PaymentService is instantiated by the dependency container. An event is raised on the last line of the PayOrder method.

    public class PaymentService : IPaymentService
    {
        private readonly IDomainEventsRaiser _events;
        private readonly IRepository _orderRepository;
        private readonly IRepository _paymentRepository;

        public PaymentService(IRepository paymentRepository, IRepository orderRepository, IDomainEventsRaiser events)
        {
            _paymentRepository = paymentRepository;
            _orderRepository = orderRepository;
            _events = events;
        }

        public void PayOrder(int orderId, decimal amount)
        {
            Order order = _orderRepository.GetById(orderId);

            Payment payment = new Payment()
            {
                OrderId = orderId,
                Amount = amount
            };

            _paymentRepository.Insert(payment);

            _events.Raise(new OrderPaidEvent(payment, order.Items));
        }
    }

IDomainEventsRaiser has the responsibility of raising events and it needs only one method to do so :

    public interface IDomainEventsRaiser
    {
        ///
        /// Raises the given domain event
        /// 

        /// Domain event type
        /// domainEvent">Domain event
        void Raise(T domainEvent) where T : IDomainEvent;
    }

What makes OrderPaidEvent an event is the fact that it implements the IDomainEvent interface. This interface actually does not expose any service. Its only purpose is to serve as a generic constraint to the Raise method of IDomainEventsRaiser to group classes that represent an event.

    public class OrderPaidEvent : IDomainEvent
    {
        public OrderPaidEvent(Payment payment, IEnumerable orderItems)
        {
            Payment = payment;
            OrderItems = new List(orderItems);
        }

        public Payment Payment { get; private set; }

        public List OrderItems { get; set; }
    }

Handling The Event

As we said earlier, we want effortless registration. To that end, we will use some conventions. Every handler will have to implement the interface IHandles, as described below :

    ///<summary>
    /// Handles an event. If there is a database transaction, the
    /// execution is delayed until the transaction is complete.
    /// </summary>

    /// <typeparam name="T"></typeparam>
    public interface IHandles<T> where T : IDomainEvent
    {
        void Handle(T domainEvent);
    }

Once the order is paid, its related items are subtracted from the stock. In other words, once OrderPaidEvent is raised, a SubtractInventaryWhenOrderPaidEventHandler will handle it. The IHandles interface makes the bridge  between a domain event and its handlers.

    public class SubtractInventaryWhenOrderPaidEventHandler : IHandles<OrderPaidEvent>
    {
        private readonly IInventoryService _inventory;

        public SubtractInventaryWhenOrderPaidEventHandler(IInventoryService inventory)
        {
            _inventory = inventory;
        }

        public void Handle(OrderPaidEvent domainEvent)
        {
            foreach (var item in domainEvent.OrderItems)
                _inventory.SubtractAvailability(item.InventoryItemId, item.Quantity);
        }
    }

The handler is also created by the dependency container. That allows dependencies to be passed more easily.

We can have multiple handlers for a same event. That said, once the order is paid, it can be placed for delivery. That means that a PlaceOrderWhenPaidEventHandler will handle this same event (we can also have one single handler that handles multiples events).

    public class PlaceOrderWhenPaidEventHandler : IHandles<OrderPaidEvent>
    {
        private readonly IOrderPlacementService _orderPlacement;

        public PlaceOrderWhenPaidEventHandler(IOrderPlacementService orderPlacement)
        {
            _orderPlacement = orderPlacement;
        }

        public void Handle(OrderPaidEvent domainEvent)
        {
            _orderPlacement.PlaceOrder(domainEvent.Payment.OrderId);
        }
    }

The Domain Events Raiser

Now that we understand how events are fired and handled, let’s see how the events raiser is implemented :

    ///<summary>
    /// Simple domain events raiser that is functional, but doesn't support deferred execution
    /// </summary>

    class DomainEventsRaiser : IDomainEventsRaiser
    {
        ///
        /// Locator of event handlers
        /// 

        private readonly IServiceProvider _locator;

        internal DomainEventsRaiser(IServiceProvider locator)
        {
            _locator = locator;
        }

        ///
        /// Raises the given domain event
        /// 

        /// Domain event type
        ///Domain event
        public void Raise(T domainEvent) where T : IDomainEvent
        {
            //Get all the handlers that handle events of type T
            IHandles[] allHandlers = (IHandles[])_locator.GetService(typeof(IHandles[]));

            if (allHandlers != null && allHandlers.Length > 0)
                foreach (var handler in allHandlers)
                    handler.Handle(domainEvent);
        }
    }

As we can see, a locator finds all the handlers that handles a specific event, then fires each handler sequentially. The domain events raiser is also created by the dependency container. It allows services to have its reference on their constructors.

These same principles could be used for other needs, like CQRS to handle commands.

Convention-Based Registration

You might want to use convention-based registration to services that are a part of a same concept, have similar structure and follow a same pattern of registration and resolving. A more “manual” registration can be more interesting for services that don’t fall on the first rule and require more specific needs.

We will be using Unity on this section, but any decent container should give you similar capabilities.

Container.RegisterTypes(new EventHandlersConvention());

This will make the container register all classes that implements IHandles. That allows the DomainEventsRaiser to use a locator that find the handlers for a specific event.

    ///<summary>
    /// Register the conventions that allows domain events to be raised and handled
    /// </summary>

    class EventHandlersConvention : RegistrationConvention
    {
        public override Func<type, ienumerable> GetFromTypes()
        {
            return WithMappings.FromAllInterfaces;
        }

        public override Func<type, ienumerable> GetInjectionMembers()
        {
            return (t) => new InjectionMember[0];
        }

        public override Func<type, lifetimemanager> GetLifetimeManager()
        {
            return WithLifetime.Transient;
        }

        public override Func<type, string> GetName()
        {
            return WithName.TypeName;
        }

        public override IEnumerable GetTypes()
        {
            Type handlerType = typeof(IHandles<>);

            return AllClasses.FromLoadedAssemblies(skipOnError: false).
                        Where(t => !t.IsAbstract &&
                            t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition().Equals(handlerType)));
        }
    }

Important : The lifetime of DomainEventsRaiser is not transient. It can be singleton, but I suggest scoped to the duration of a full transaction, since the state of this object (the events queue that we will see on the next section) is not reusable between one transaction and another.

Adding Deferred Execution Support

We already have a full working example of domain events that are registered using conventions. Now let’s add a teaspoon of real life.

Let’s say, once the order is paid, an e-mail is sent to the customer to inform that his payment has been processed. This is what our process now looks like :

Domain-Events-02.png

Created with Balsamiq Mockups.

We will be handling e-mail sending using the domain events raiser that we proposed for domain events. However, the e-mail should be sent only after the transaction is committed.

So, in our IHandles interface, we add a Deferred property :

    ///<summary>
    /// Handles an event. If there is a database transaction, the
    /// execution is delayed until the transaction is complete.
    /// </summary>

    /// <typeparam name="T"></typeparam>
    public interface IHandles<T> where T : IDomainEvent
    {
        void Handle(T domainEvent);

        bool Deferred { get; }
    }
One single class can handle many events. <strong>NotificationsHandler</strong> demonstrate how this behavior could be achieved :
    public class NotificationsHandler : IHandles, IHandles //<- multiple events handled by a single handler
    {
        private readonly IUserNotifier _notifier;

        public NotificationsHandler(IUserNotifier notifier) // <-- instantiated by the dependencies container
        {
            _notifier = notifier;
        }

        public bool Deferred { get { return true; } } //<- 'true' here indicates that all these events should be invoked only after the transaction is committed

        public void Handle(OrderPaidEvent domainEvent)
        {
            _notifier.Notify("Yay! Your payment has been processed.");
        }

        public void Handle(OrderShippedEvent domainEvent)
        {
            _notifier.Notify(string.Format("Your order has finally been shipped. Address : \"{0}\"", domainEvent.Order.ShipmentAddress));
        }
    }

DeferredDomainEventsRaiser

And DeferredDomainEventsRaiser replaces the simple DomainEventsRaiser that I mentioned earlier. It adds deferred handlers in a Queue and dispatch them once the transaction is committed. Please notice that :

  • Not all events are deferred. Only those that have IHandles.Deferred = true.
  • In addition, events are never deferred if there is no transaction in progress.
    ///<summary>
    /// Domain events handler that supports deferred execution
    /// </summary>

    class DeferredDomainEventsRaiser : IDomainEventsRaiser
    {
        ///
        /// Locator of event handlers
        /// 

        private readonly IServiceProvider _resolver;
        ///
        /// Collection of events queued for later execution
        /// 

        private readonly ConcurrentQueue _pendingHandlers = new ConcurrentQueue();
        ///
        /// Data access state manager
        /// 

        private readonly IDbStateTracker _dbState;

        public DeferredDomainEventsRaiser(IServiceProvider resolver, IDbStateTracker dbState)
        {
            _resolver = resolver;
            _dbState = dbState;

            _dbState.TransactionComplete += this.Flush;
            _dbState.Disposing += this.FlushOrClear;
        }

        ///
        /// Raises the given domain event
        /// 

        /// Domain event type
        /// Domain event
        public void Raise(T domainEvent) where T : IDomainEvent
        {
            //Get all the handlers that handle events of type T
            IHandles[] allHandlers = (IHandles[])_resolver.GetService(typeof(IHandles[]));

            if (allHandlers != null && allHandlers.Length > 0)
            {
                IHandles[] handlersToEnqueue = null;
                IHandles[] handlersToFire = allHandlers;

                if (_dbState.HasPendingChanges())
                {
                    //if there is a transaction in progress, events are enqueued to be executed later

                    handlersToEnqueue = allHandlers.Where(h => h.Deferred).ToArray();

                    if (handlersToEnqueue.Length > 0)
                    {
                        lock (_pendingHandlers)
                            foreach (var handler in handlersToEnqueue)
                                _pendingHandlers.Enqueue(() => handler.Handle(domainEvent));

                        handlersToFire = allHandlers.Except(handlersToEnqueue).ToArray();
                    }
                }

                foreach (var handler in handlersToFire)
                    handler.Handle(domainEvent);
            }
        }

        ///
        /// Fire all the events in the queue
        /// 

        private void Flush()
        {
            Action dispatch;
            lock (_pendingHandlers)
                while (_pendingHandlers.TryDequeue(out dispatch))
                    dispatch();
        }

        ///
        /// Execute all pending events if there is no open transaction. Otherwise, clears the queue without executing them
        /// 

        private void FlushOrClear()
        {
            if (!_dbState.HasPendingChanges())
                Flush();
            else
            {
                //If the state manager was disposed with a transaction in progress, we clear
                //the queue without firing the events because this flow is pretty inconsistent
                //(it could be caused, for instance, by an unhandled exception)
                Clear();
            }
        }

        ///
        /// Clear the pending events without firing them
        /// 

        private void Clear()
        {
            Action dispatch;
            lock (_pendingHandlers)
                while (_pendingHandlers.TryDequeue(out dispatch)) ;
        }
    }

This new interface IDbStateTracker simply expose some events about  the state of the database and it could be implemented by an UnitOfWork (see source code attached to this post, also available on GitHub).

    ///<summary>
    /// Tracks the database's state
    /// </summary>

    public interface IDbStateTracker : IDisposable
    {
        ///
        /// Triggered when disposing
        /// 

        event Action Disposing;

        ///
        /// Triggered when the transaction is completed
        /// 

        event Action TransactionComplete;

        ///
        /// Returns true if there are uncommitted pending changes. Otherwise, returns false.
        /// 

        bool HasPendingChanges();
    }

Putting It All Together

This approach allows event handlers to be registered automatically by using conventions. Also, the same design allows event handlers to be fired online or have their execution delayed until transaction is over. The source code available on GitHub) contains a full working example of the principles discussed here.

Developing secure web applications: XSS attack, the Confused Deputy and Over-Posting

The reality is that securing applications is not as much fun as we would like it to be. Nobody comes and says “Wow! Thumbs up for securing my personal data!”. However, security is undoubtedly important in many contexts and cannot be underestimated. We do not want to pass through an embarrassing position caused by a security breach.

In this article, I cover XSS, XSRF and Over-Posting, a fraction of the most common web attacks, and explain how to protect your applications against them.

Some web security principles

  • Implement security in depth: the Web tier responsible for receiving HTTP requests should not be the only layer to perform security checks. Each subsystem must take responsibility for their own security, disregarding the quality of the security checks of the upper layers.
  • Never trust user input: Never assume that you do not need to perform a security check just because it has already been done elsewhere. Moreover, validations in JavaScript can improve the user experience by avoiding unnecessary http requests, but never assume that these validations on the client side are secure. An attacker can bypass client validation without any difficulty.
  • Reduce surface area: Minimize the amount of exposed operations and restrict the inputs of each action to contain only the data required to process the action. Do not expose to the end user exception details or information about the database schema.
  • Enforce the principle of Least Privilege: Perform operations using only the privileges required for the task. If for some reason you need to elevate permissions, grant them but remove when these permissions are no longer needed.
  • Disable unnecessary features: Platforms can provide security flaws. Uninstall features that are not relevant to the execution of your application.
  • Evaluate a model of authentication and authorization that fits well to your application: Authentication is the process of identifying the user who accesses the application. Authorization is the process of verifying what operations the authenticated user can perform. There are different strategies for authentication and authorization. Check the one that best suits your application.

Defending your code against the most common attacks

Users of your site are likely to discover bugs. Some of these bugs reveal security holes. And when an attacker discovers one of these gaps, we have a problem.

Cross-Site Scripting (XSS)

XSS is one of the most common web attacks. According to WhiteHat Security, 40% of the websites has at least one breach for Cross-Site Scripting. In XSS, we inject some client script code to the remote server through user inputs or query strings.

Open http://www.insecurelabs.org/Talk/Details/6 to start playing with XSS. Pay attention to the content written inside the input of the form. Everything that you write in a comment will be rendered after the form is submitted. In a real application, a malicious script inside a comment could inject code to the page and every user that opens the browser would run that script.

XSS01

This is the result

XSS02

This is a classical XSS attack. My posted comment containing a bad script will be rendered within the list of comments of the page. When someone opens the page, the script is executed. In this particular case, the attacker is stealing the cookies related to the domain where the script was injected. Open the article Session hijacking (Wikipedia) to understand the implications of exposing your cookies.

In the words of Jaff Atwood (CodingHoror.com), article Protecting Your Cookies: HttpOnly:

Imagine, then, the surprise of my friend when he noticed some enterprising users on his website were logged in as him and happily banging away on the system with full unfettered administrative privileges.

Preventing XSS

Never trust user input. Encode everything. Instead of displaying content as-is, use HTML encode to render content.

In ASP.NET Web Forms, the code below will not be encoded.

  <%= Model.Comment %> 

Instead, use one of these approaches:

 <%: Model.Comment %> 

 

 <%= Html.Encode(Model.Comment) %> 

Razor encodes by default. The sample below gives an encoded output:

 @Model.Comment 

In ASP.NET MVC, if you want to write raw content as-is (without any encoding), you should write it explicitly and decorate your action with a [ValidateInput(false)] attribute. In this case, security concerns are at your own risk.

 @Html.Raw(Model.HtmlContent) 
[ValidateInput(false)]
public ViewResult Save(FormDataWithRawContent form)
{
...
}

Preventing Cookie Theft – Use HttpOnly and Require SSL

In the Web.config file, write:

<httpCookies domain="" httpOnlyCookies="true" requireSSL="true" />

The httpOnlyCookies attribute will prevent cookies from being accessed from client scripts. The requireSSL attribute will prevent cookies from being sent back to the server when the connection is not secure with SSL. This configuration will stop most XSS attacks and should be used whenever possible.

Cross-Site Request Forgery (XSRF) – The confused deputy

Cross-site request forgery is an attack where the attacker creates a page that includes a form that posts to the attacked site.

<form id="someform"
action="http://attackedTargetSite/Entity/Update"
method="post">

<input type="text" />
<input type="text" />

If the user who submitted the form is authenticated on the target site, the target site will receive and process the post without presenting any complications related to authentication, since the action is being performed by an authenticated user.

The confused deputy attack

XSRF is a form of confused deputy attack.

If an attacker want to perform some administrative actions on a web application that he does not have the proper privileges, a feasible approach is to confuse an user to do these things for him. In the case of an XSRF attack, the confusing deputy is the user’s browser. Here (Haacked.com) we can see a nice practical example about XSRF attack.

A confused deputy is a computer program that is innocently fooled by some other party into misusing its authority. It is a specific type of privilege escalation. In information security, the confused deputy problem is often cited as an example of why capability-based security is important.

From Wikipedia

Preventing XSRF

Reduce surface area. Minimize the amount of actions exposed. Furthermore, create a hidden HTML input field that stores a token generated by your server and validate if a submitted token is valid. This token can be stored in a session variable or cookie.

ASP.NET MVC includes some helpers to prevent against this kind of attack. It generates a anti forgery token inside the form and validate this token against the server when the form is submitted:

@using (Html.BeginForm(...))
{
@Html.AntiForgeryToken("salt")
...
}

 

[ValidateAntiForgeryToken(Salt="salt")]
public ViewResult Update()
{
...
}

Thus, if the source of the request is unknown (i.e. the antiforgery token does not exist or it is not consistent), the action will not be triggered and an error will be thrown to the client application.

Known limitations

  • Users must have cookies enabled, or requests will be rejected.
  • This method works with POST, but not with GET. This should not be a very big problem, since GET requests should only read information and never change the state of the database.
  • XSS holes create possibilities for cookies hijacking and access to the antiforgery token.

Over-Posting

ASP.NET MVC maps model properties in GET and POST operations by using some naming conventions. However, this convenience introduces a security flaw: the attacker can populate properties of the model even if they are not displayed in the form.

Consider a model PlaceReview bound to an action.


public class PlaceReview
{
	public int ReviewID { get; set; } // PK
	public int PlaceID { get; set; } // FK
	public Place Place { get; set; } // FK
	public int NumberOfLikes { get; set; }
	public string UserName { get; set; }
	public string UserComment { get; set; }
}

Now consider that the action is only interested on the UserName and UserComment properties of the model.


<ul>
		<li>
			@Html.LabelFor(m => m.UserName)
			@Html.TextBoxFor(m => m.UserName)
		</li>
		<li>
			@Html.LabelFor(m => m.UserComment)
			@Html.TextBoxFor(m => m.UserComment)
		</li>
	</ul>

A malicious user can manipulate the querystring or post data to add information and change other properties of the model. For instance, he could add “NumberOfLikes = 5000” and the corresponding property would be populated accordingly in the server side application.

Preventing Over-Posting

You can use a BindAttribute on the model class or action parameter to explicitly control the properties that should be mapped by the model binder.

[System.Web.Mvc.Bind(Include="UserName, UserComment")]
public class PlaceReview
{
	public int ReviewID { get; set; } // PK
	public int PlaceID { get; set; } // FK
	public Place Place { get; set; } // FK
	public int NumberOfLikes { get; set; }
	public string UserName { get; set; }
	public string UserComment { get; set; }
}

A similar approach involves calling UpdateModel or TryUpdateModel within the Action.

UpdateModel(placeReview, "PlaceReview",
new string[] { "UserName", "UserComment" });

A better approach is not to use data mapping to represent view model and create specific classes that contain only the properties required for the action and nothing else.

public class PlaceReviewModel
{
	public string UserName { get; set; }
	public string UserComment { get; set; }
}

This last approach significantly reduces security holes related to over-posting and eliminates a problem of stamp coupling.

Stamp coupling occurs when modules share objects and use only a part of it. Sharing more data than what was needed allows the called module to access more data than it really needs.

From Cohesion and coupling: Principles of orthogonal, scalable design

Putting it all together

No application is totally secure, but there are some best practices that can be used to avoid several vulnerabilities. We talked about XSS, XSRF and Over-Posting. Fortunately, there are enough resources available and ready to protect web applications from dangerous attacks that occur frequently out there.

Related readings