Sunday, November 11, 2012

CQRS Query Engine - Writing a Testable, maintainable and extensible CQRS Query Engine - Part 3

  1. Designing the Query Engine
  2. Encapsulating common behavior (template pattern)
  3. Implementing Queries
  4. Creating the Query Resolver

Finally in this chapter I will show you the result of the Query Engine and in the next post I will show a way to decouple the query handler from your code.


So let’s start creating queries.


Querying By ID


The first Query I want to create is this one, just a simple query by ID


A table/view can have a primary key composed of just one field or by several fields, with this approach you can express the intent of the query explicitly and specify any number of ID’s to query your objects. Furthermore, sometimes your tables/views could have unique indexes additional to the primary key, you can use this approach to also find each unique items


So let’s see the code:


We need an object implementing the IQueryID mark interface to specify it as the ID we want to search for.


public sealed class MovieID : IQueryID
{
    public MovieID(Guid id)
    {
        this.ID = id;
    }

    public Guid ID { get; private set; }
}

That’s it, we are explicitly specifying the ID used by our Movie entity.


What we’re actually doing is: we are taking an implicit hidden domain concept (the Movie Identifier) and we are making it explicit


The next step is to create the query:


public class FindMovieByIDQueryHandler : QueryByIDHandler<MovieID, Movie>
{
    private IMoviesQueryRepository moviesQueryRepository;

    public FindMovieByIDQueryHandler(IMoviesQueryRepository moviesQueryRepository)
    {
        this.moviesQueryRepository = moviesQueryRepository;
    }

    protected override IQueryable<Movie> InitialItems
    {
        get { return this.moviesQueryRepository.GetItems(); }
    }

    protected override Movie FindItem(MovieID queryID, IQueryable<Movie> items)
    {
        return items.FirstOrDefault(x => x.ID.Equals(queryID.ID));
    }
}

That’s it. You created your first query completely isolated so that it can be safely unit tested. And since this query is isolated, creating new queries won’t interfere in any way with any other queries created, so there’s no risk to break existing queries =), you won’t require to change any interfaces nor existing implementations in order to add a new query, you could even create this query in a new assembly, drop it to your application’s bin folder and use reflection to load it into your IoC container when the application starts.


But we are missing something, first let me remember you the definition of the QueryByIDHandler class:


public abstract class QueryByIDHandler<TQueryID, TQueryResult> : IQueryByIDHandler<TQueryID, TQueryResult>
    where TQueryID : IQueryID

The class implements IQueryByIDHandler<TQueryID, TQueryResult>, so with this code, you would have to inject this dependency (interface) in the object you want to use your query, so let’s imagine that you want to use it in a MVC application, your code would look like:


Note: I know that you would never use a handler in this way, I’m just using it as an example. And I want to emphasize, the following code is not meant to be used in this way because you would be tight coupling your code with this specific Query Handler


public partial class MoviesController : Controller
{
    private IQueryByIDHandler<MovieID, Movie> queryByIdHandler;

    public MoviesController(IQueryByIDHandler<MovieID, Movie> queryByIdHandler)
    {
        this.queryByIdHandler = queryByIdHandler;
    }
}

Please pay special attention to:


IQueryByIDHandler<MovieID, Movie> queryByIdHandler

This doesn’t look right to me. The nature of the IQueryByIDHandler is to be generic so that we can use it to create custom queries, but using it like this we are hiding the intention of the query.


So what’s the intention? Well in this case the intention is to simply provide a way to query the Movies collection to find a specific Movie by ID


To me the correct naming would be something like:


IFindMovieByIDQueryHandler

In this case we are making the concept and the intention of the query explicit in the application. The readability of the code is dramatically increased when you read:


IFindMovieByIDQueryHandler

vs


IQueryByIDHandler<MovieID, Movie>

In order to create this interface we need code like this:


public interface IFindMovieByIDQueryHandler : IQueryByIDHandler<MovieID, Movie>
{
}

And then use it to mark our query:


public class FindMovieByIDQueryHandler : QueryByIDHandler<MovieID, Movie>, IFindMovieByIDQueryHandler
{
    private IMoviesQueryRepository moviesQueryRepository;

    public FindMovieByIDQueryHandler(IMoviesQueryRepository moviesQueryRepository)
    {
        this.moviesQueryRepository = moviesQueryRepository;
    }

    protected override IQueryable<Movie> InitialItems
    {
        get { return this.moviesQueryRepository.GetItems(); }
    }

    protected override Movie FindItem(MovieID queryID, IQueryable<Movie> items)
    {
        return items.FirstOrDefault(x => x.ID.Equals(queryID.ID));
    }
}

And finally the updated controller would look like (Again just for demonstration purpose):


public partial class MoviesController : Controller
{
    private IFindMovieByIDQueryHandler findMovieByIDHandler;

    public MoviesController(IFindMovieByIDQueryHandler findMovieByIDHandler)
    {
        this.findMovieByIDHandler = findMovieByIDHandler;
    }
}

If you want to learn more about Making Roles Explicit, please see this Uddi Dahan video


Querying all items in the collection


In order to query all items (the typical FindAll method) we will create the interface to expose the query concept


public interface IFindAllMoviesQueryHandler : IQueryHandler<Movie>
{
}

Then the implementation of the query


public class FindAllMoviesQueryHandler : QueryHandler<Movie>, IFindAllMoviesQueryHandler
{
    private IMoviesQueryRepository moviesQueryRepository;

    public FindAllMoviesQueryHandler(IMoviesQueryRepository moviesQueryRepository)
    {
        this.moviesQueryRepository = moviesQueryRepository;
    }

    protected override IQueryable<Movie> ApplyDefaultOrder(IQueryable<Movie> items)
    {
        return items.OrderByDescending(x => x.ID);
    }

    protected override IQueryable<Movie> InitialItems
    {
        get { return this.moviesQueryRepository.GetItems(); }
    }
}

The code is actually straightforward, so it doesn’t require explanation


Applying specific queries


This is the most interesting part of the Query Engine, and also the most used in RL applications.


Here we will define all the specific queries needed in the application but only when they are required, and like I explained before, adding new queries won’t affect in any way to any existing query


So let’s start by making the query concept explicit, in order to do it, we need an object implementing the IQuery interface, something like this:


public sealed class FindMoviesByTitleQuery : IQuery
{
    public FindMoviesByTitleQuery(string title)
    {
        this.Title = title;
    }

    public string Title { get; private set; }
}

In this query class you will define all fields needed in order to apply the query, in this case I just need to query by title


Then, let’s create the mark of the query handler related to this query:


public interface IFindMoviesByTitleQueryHandler : IQueryHandler<FindMoviesByTitleQuery, Movie>
{
}

And finally the implementation:


public class FindMoviesByTitleQueryHandler : QueryHandler<FindMoviesByTitleQuery, Movie>, IFindMoviesByTitleQueryHandler
{
    private IMoviesQueryRepository moviesQueryRepository;

    public FindMoviesByTitleQueryHandler(IMoviesQueryRepository moviesQueryRepository)
    {
        this.moviesQueryRepository = moviesQueryRepository;
    }

    protected override IQueryable<Movie> ApplyDefaultOrder(IQueryable<Movie> items)
    {
        return items.OrderBy(x => x.Title);
    }

    protected override IQueryable<Movie> InitialItems
    {
        get { return this.moviesQueryRepository.GetItems(); }
    }

    protected override IQueryable<Movie> ApplyQuery(FindMoviesByTitleQuery query, IQueryable<Movie> items)
    {
        var customQuery = items;

        if (!string.IsNullOrWhiteSpace(query.Title))
        {
            customQuery = customQuery.Where(x => x.Title.ToLower().Contains(query.Title.ToLower()));
        }

        return customQuery;
    }
}

Again, the code is straightforward and self explanatory therefore it doesn’t require any explanation


At this point, you would be able to use the query handlers in your application by exposing them as dependencies of your objects, using DI, and by adding them to your IoC container, however, like I said before, if you use them this way, you would be tight coupling your handlers with your code


As an exercise for the reader, go ahead and do it, create a simple application and use the handlers directly by injecting them in your objects, just to play with them


In the next post I will show you a way to completely decouple the handlers from your code.

CQRS Query Engine - Writing a Testable, maintainable and extensible CQRS Query Engine - Part 2

  1. Designing the Query Engine
  2. Encapsulating common behavior (template pattern)
  3. Implementing Queries
  4. Creating the Query Resolver

In the previous post I created the design of the Query Engine, in this post I will create the initial implementation


I created several abstract classes to encapsulate common behavior:


public abstract  class QueryPageAndSortingBase<TQueryResult>
{
    protected abstract IQueryable<TQueryResult> ApplyDefaultOrder(IQueryable<TQueryResult> items);

    protected virtual IQueryable<TQueryResult> ApplyPagingAndSorting(IQueryable<TQueryResult> items, PagingAndSortingInfo pagingAndSortingInfo)
    {
        Condition.Requires(pagingAndSortingInfo).IsNotNull();
        Condition.Requires(items).IsNotNull();

        var customQuery = items;
        var page = pagingAndSortingInfo.Page;
        var pageIndex = page - 1;
        var pagesize = pagingAndSortingInfo.PageSize;
        var orderDirection = pagingAndSortingInfo.OrderDirection;
        var orderField = pagingAndSortingInfo.OrderByField;

        if (!string.IsNullOrWhiteSpace(orderField))
        {
            switch (orderDirection)
            {
                case OrderDirection.Ascending:
                    customQuery = customQuery.OrderBy(orderField);
                    break;
                case OrderDirection.Descending:
                    customQuery = customQuery.OrderBy(string.Format("{0} descending", orderField));
                    break;
                default:
                    throw new ArgumentOutOfRangeException("pagingAndSortingInfo", "Sorting can only be Ascending or Descending.");
            }
        }
        else
        {
            customQuery = this.ApplyDefaultOrder(customQuery);
        }

        customQuery = customQuery.Skip(pageIndex * pagesize).Take(pagesize);
        Condition.Ensures(customQuery).IsNotNull();

        return customQuery;
    }
}

The QueryPageAndSortingBase<TQueryResult> class is used to encapsulate paging and sorting behavior


public abstract class QueryHandlerBase<TQueryResult> : QueryPageAndSortingBase<TQueryResult>
{
    protected abstract IQueryable<TQueryResult> InitialItems { get; }

    protected virtual IQueryable<TQueryResult> HandleCustomQuery(IQueryable<TQueryResult> items, PagingAndSortingInfo pagingAndSortingInfo = null)
    {
        Condition.Requires(items).IsNotNull();

        var customQuery = items;

        if (pagingAndSortingInfo != null)
        {
            customQuery = this.ApplyPagingAndSorting(items: customQuery, pagingAndSortingInfo: pagingAndSortingInfo);
        }

        Condition.Ensures(customQuery).IsNotNull();

        return customQuery;
    }
}

The QueryHandlerBase<TQueryResult> controls the flow to call the QueryPageAndSortingBase<TQueryResult>.ApplyPagingAndSorting method. This method is in charge to apply the paging and sorting.


public abstract class QueryHandler<TQuery, TQueryResult> : QueryHandlerBase<TQueryResult>,
    IQueryHandler<TQuery, TQueryResult>
    where TQuery : IQuery
{
    public virtual QueryResults<TQueryResult> HandleQuery(TQuery query, PagingAndSortingInfo pagingAndSortingInfo = null)
    {
        Condition.Requires(query).Evaluate(query != null);
        Condition.Requires(this.InitialItems).IsNotNull();

        var queryProcessed = this.ApplyQuery(query, this.InitialItems);
        Condition.Ensures(queryProcessed).IsNotNull();

        var res = this.HandleCustomQuery(queryProcessed, pagingAndSortingInfo);
        Condition.Ensures(res).IsNotNull();

        return QueryResults.Of(res.ToList(), queryProcessed.Count());
    }

    protected abstract IQueryable<TQueryResult> ApplyQuery(TQuery query, IQueryable<TQueryResult> items);
}

The QueryHandler<TQuery, TQueryResult> controls the flow to apply a custom and explicit query, and apply paging and sorting when required.


public abstract class QueryHandler<TQueryResult> : QueryHandlerBase<TQueryResult>,
    IQueryHandler<TQueryResult>
{
    public virtual QueryResults<TQueryResult> HandleQuery(PagingAndSortingInfo pagingAndSortingInfo = null)
    {
        Condition.Requires(this.InitialItems).IsNotNull();

        var initialItems = this.InitialItems;
        var res = this.HandleCustomQuery(initialItems, pagingAndSortingInfo);
        Condition.Ensures(res).IsNotNull();

        return QueryResults.Of(res.ToList(), initialItems.Count());
    }
}

The QueryHandler<TQueryResult> class is used to control the flow to query all the elements applying paging and sorting when required


Unit testing


I’ll show you the unit tests of these base classes, since they are abstract, and most of the methods I want to test are protected I can’t use Moq =((((( buaaa, meaning that I have to write some testing mocks manually..... but anyway, let’s do it:


QueryPageAndSortingBase Tests


Manual Mock


public class QueryPageAndSortingBaseMock : QueryPageAndSortingBase<Movie>
{
    protected override IQueryable<Movie> ApplyDefaultOrder(IQueryable<Movie> items)
    {
        return items.OrderByDescending(x => x.Title);
    }
}

Tests


[TestClass]
public class QueryPageAndSortingBaseTests
{
    [TestClass]
    public class TheApplyPagingAndSortingMethod
    {
        [TestMethod]
        public void it_should_apply_the_default_order_when_the_order_field_is_null_or_empty()
        {
            var sut = new QueryPageAndSortingBaseMock();
            var items = Builder<Movie>.CreateListOfSize(10).Build().AsQueryable();
            var expectedItems = items.OrderByDescending(x => x.Title);
            var methodInfo = sut.GetType().GetMethod("ApplyPagingAndSorting", BindingFlags.Instance | BindingFlags.NonPublic);
            var pagingInfo = new PagingAndSortingInfo(orderByField: string.Empty);

            var res = (IQueryable<Movie>)methodInfo.Invoke(sut, new object[] { items, pagingInfo });

            res.Should().NotBeNull()
                .And.HaveCount(items.Count())
                .And.ContainInOrder(expectedItems);
        }

        [TestMethod]
        public void it_should_order_in_ascending_mode_when_the_order_fiels_is_not_null_and_the_order_direction_is_Ascending()
        {
            var sut = new QueryPageAndSortingBaseMock();
            var items = Builder<Movie>.CreateListOfSize(10).Build().AsQueryable();
            var expectedItems = items.OrderBy(x => x.ID);
            var methodInfo = sut.GetType().GetMethod("ApplyPagingAndSorting", BindingFlags.Instance | BindingFlags.NonPublic);
            var pagingInfo = new PagingAndSortingInfo(orderByField: "ID", orderDirection: OrderDirection.Ascending);

            var res = (IQueryable<Movie>)methodInfo.Invoke(sut, new object[] { items, pagingInfo });

            res.Should().NotBeNull()
                .And.HaveCount(items.Count())
                .And.ContainInOrder(expectedItems);
        }

        [TestMethod]
        public void it_should_order_in_descending_mode_when_the_order_fiels_is_not_null_and_the_order_direction_is_Descending()
        {
            var sut = new QueryPageAndSortingBaseMock();
            var items = Builder<Movie>.CreateListOfSize(10).Build().AsQueryable();
            var expectedItems = items.OrderByDescending(x => x.ID);
            var methodInfo = sut.GetType().GetMethod("ApplyPagingAndSorting", BindingFlags.Instance | BindingFlags.NonPublic);
            var pagingInfo = new PagingAndSortingInfo(orderByField: "ID", orderDirection: OrderDirection.Descending);

            var res = (IQueryable<Movie>)methodInfo.Invoke(sut, new object[] { items, pagingInfo });

            res.Should().NotBeNull()
                .And.HaveCount(items.Count())
                .And.ContainInOrder(expectedItems);
        }

        [TestMethod]
        public void it_should_paginate_the_results()
        {
            var sut = new QueryPageAndSortingBaseMock();
            var page = 3;
            var pageSize = 4;
            var pageIndex = page - 1;
            var pagingInfo = new PagingAndSortingInfo(orderByField: "Title", orderDirection: OrderDirection.Descending, page: page, pageSize: pageSize);
            var items = Builder<Movie>.CreateListOfSize(20).Build().AsQueryable();
            var expectedItems = items.OrderByDescending(x => x.Title).Skip(pageIndex * pageSize).Take(pageSize);
            var methodInfo = sut.GetType().GetMethod("ApplyPagingAndSorting", BindingFlags.Instance | BindingFlags.NonPublic);

            var res = (IQueryable<Movie>)methodInfo.Invoke(sut, new object[] { items, pagingInfo });

            res.Should().NotBeNull()
                .And.HaveCount(pageSize)
                .And.ContainInOrder(expectedItems);
        }
    }
}

QueryHandlerBase Tests


Manual Mocks


public class QueryHandlerBaseMock : QueryHandlerBase<Movie>
{
    protected override IQueryable<Movie> InitialItems
    {
        get { throw new NotImplementedException(); }
    }

    protected override IQueryable<Movie> ApplyDefaultOrder(IQueryable<Movie> items)
    {
        throw new NotImplementedException();
    }
}

Tests


[TestClass]
public class QueryHandlerBaseTests
{
    [TestClass]
    public class TheHandleCustomQueryMethod
    {
        [TestMethod]
        public void it_should_not_apply_paging_nor_sorting_when_the_pagingAndSortingInfo_parameter_is_null()
        {
            var sut = new QueryHandlerBaseMock();
            var items = Builder<Movie>.CreateListOfSize(20).Build().AsQueryable();
            var paging = (PagingAndSortingInfo)null;
            var methodInfo = sut.GetType().GetMethod("HandleCustomQuery", BindingFlags.NonPublic | BindingFlags.Instance);

            var res = (IQueryable<Movie>)methodInfo.Invoke(sut, new object[] { items, paging });

            res.Should().NotBeNull()
                .And.HaveCount(items.Count())
                .And.ContainInOrder(items);
        }

        [TestMethod]
        public void it_should_apply_paging_and_sorting_when_the_pagingAndSortingInfo_parameter_is_not_null()
        {
            var sut = new QueryHandlerBaseMock();
            var items = Builder<Movie>.CreateListOfSize(20).Build().AsQueryable();
            var paging = new PagingAndSortingInfo(orderByField: "ID");
            var pageIndex = paging.Page - 1;
            var expectedItems = items.OrderBy(x => x.ID).Skip(pageIndex * paging.PageSize).Take(paging.PageSize);
            var methodInfo = sut.GetType().GetMethod("HandleCustomQuery", BindingFlags.NonPublic | BindingFlags.Instance);

            var res = (IQueryable<Movie>)methodInfo.Invoke(sut, new object[] { items, paging });

            res.Should().NotBeNull()
                .And.HaveCount(expectedItems.Count())
                .And.ContainInOrder(expectedItems);
        }
    }
}

Uff that was too much code for a post, the rest of the tests will be available when I post the full code =)


In the next post, I will show you how to use these objects and how easy is to create query objects


This is the graphical representation of these classes:




Saturday, November 10, 2012

CQRS Query Engine - Writing a Testable, maintainable and extensible CQRS Query Engine

  1. Designing the Query Engine
  2. Encapsulating common behavior (template pattern)
  3. Implementing Queries
  4. Creating the Query Resolver

In my last post I blogged about writing a Query Repository in a test-friendly way but even when the code was testable I still believe it can be improved in several ways.


I’m going to build a small, simple and test-friendly Query Engine. This will be the first post in this series.


If you are familiar with CQRS you will find the code of this post familiar, since I’m following the same patterns used in the Commands branch in a CQRS architecture


The traditional query repository


Before start, let’s see how a typical query repository looks like (assuming a fictitious Movies query repository):


public interface IMoviesQueryRepository
{
    Movie FindByID(Guid movieID);
    IQueryable<Movie> FindAll();
    IQueryable<Movie> FindByTitle(string title);
    IQueryable<Movie> FindByDirectors(string[] director);
    IQueryable<Movie> FindByActors(string[] actors);
    IQueryable<Movie> FindByReleaseDate(DateTime date);
}

There are several problems with an interface like this, I will talk about them in a minute.


The problem


Now let’s say that you start with a design like this and that you implement all these methods and use DI to inject the query repository wherever you want to use it. Now imagine that after awhile, you find out that you need to query your movies by Category so you just go and add the following method to your interface:


IQueryable<Movie> FindByCategory(string category);

You have to go and edit all your implementations of your IMoviesQueryRepository (including all testing mocks) in order to be able to compile again your solution, then you add implementation of this new method in all of them.


So far so good, after a couple of days you realize that now you need a couple of filters more, let’s say that now you need to query by a list of categories and by the average cost of making each movie, so again you add the following methods to your interface:


IQueryable<Movie> FindByCategories(string[] categories);
IQueryable<Movie> FindByAverageCost(decimal averageCost);

And you repeat all the implementation process again.


This process will continue during the whole development lifecycle. And there are several filters that might be needed during this time for example, querying by rating, by amount of tickets sold, etc. etc.


So a design like this is not flexible, is not testable and is hard to maintain


Let’s see several problems with this design:


  • It violates the open-closed pricniple (open for extension/closed to modification).


    The problem when you don’t follow this principle is the problem described before, you will have to go and edit all your implementations in order to add new functionality. You could potentially introduce new bugs to the application that would affect more than just one query (perhaps all of them?)

  • A design like this can lead to violate the YAGNI principle (You Ain’t Gonna Need It)


    Why? Simply because in order to avoid the problem described before, you could try to think about all the possible filters that you might need in the application. This will lead you to write tons of query filters that you won’t ever need

  • This design is not test friendly I just wrote the result of these queries as IQueryable objects on purpose to ilustrate the point that this design is not test friendly, and actually you won’t be able to test in isolation your queries if you expose in your public API IQueryable objects. The reason is that your query logic will actually be spread out in several places in your application.


Let’s see some approaches that won’t work


Anti Unit Testing approach


The simplest approach is to forget about unit testing (oO) and consume the IQueryable object directly in all the places where you will need it (usually the user interface)


I don’t have to tell you that I would never recommend something like this. But surprisingly in Stackoverflow I've seen a lot of code like this, and a lot of examples over the internet about MVC using this approach.


Naive approach


Well let’s say that you realize that unit test is so important in any application that you decide to go back to the original design and try to figure out how to fix it.


So a really simplistic approach would be to call for a small meeting with all your developers and tell them that even when you expose an IQueryable object in your query repository they should never add new queries on it.... in order to “guarantee” that the query is encapsulated and therefore testable in isolation.....


….Good luck with that!


So now hopefully you will want to see the solution already... and here it is


This is my solution to the problem


Encapsulating the query


The first thing to do to refactor the original design is to encapsulate the query in order to guarantee that the query will actually be unit-tested in isolation. I’m going to follow the same approach I used in my last post, I will create a new DTO object to wrap my query results.


This object would look something like:


public sealed class QueryResults
{
    public static QueryResults<TTarget> Of<TTarget>(IList<TTarget> results, int virtualRowsCount)
    {
        Condition.Requires(results).IsNotNull();
        Condition.Requires(virtualRowsCount).IsGreaterOrEqual(0);

        return new QueryResults<TTarget>(results, virtualRowsCount);
    }
}

public class QueryResults<TTarget>
{
    public QueryResults(IList<TTarget> results, int virtualRowsCount)
    {
        Condition.Requires(results).IsNotNull();
        Condition.Requires(virtualRowsCount).IsGreaterOrEqual(0);

        this.VirtualRowsCount = virtualRowsCount;
        this.Results = results;
    }

    public int VirtualRowsCount { get; protected set; }

    public IList<TTarget> Results { get; protected set; }
}

Since the query will be encapsulated you also need an object to pass paging and sorting parameters:


public sealed class PagingAndSortingInfo
{
    public PagingAndSortingInfo(
        int page = 1,
        int pageSize = 10,
        string orderByField = "",
        OrderDirection orderDirection = OrderDirection.Ascending)
    {
        Condition.Requires(page).IsGreaterOrEqual(1);
        Condition.Requires(pageSize).IsGreaterOrEqual(1); ;

        this.Page = page;
        this.PageSize = pageSize;
        this.OrderByField = orderByField;
        this.OrderDirection = orderDirection;
    }

    public int Page { get; private set; }

    public int PageSize { get; private set; }

    public string OrderByField { get; private set; }

    public OrderDirection OrderDirection { get; private set; }
}

public enum OrderDirection
{
    Ascending,
    Descending
}

So your query repository would look like:


public interface IMoviesQueryRepository
{
    Movie FindByID(Guid movieID);
    QueryResults<Movie> FindAll(PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByTitle(string title, PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByDirectors(string[] director, PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByActors(string[] actors, PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByReleaseDate(DateTime date, PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByCategory(string category, PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByCategories(string[] categories, PagingAndSortingInfo pagingAndSortingInfo = null);
    QueryResults<Movie> FindByAverageCost(decimal averageCost, PagingAndSortingInfo pagingAndSortingInfo = null);
}

Following this approach you will be able to unit test in isolation your queries, but you would still have the original problem.


Designing the Query Engine


OK, so now let’s design the query engine.


First of all I have a couple of interfaces that I’m using to mark my objects:


public interface IQuery
{
}

public interface IQueryID
{
}

  • The IQuery interface is the equivalent to the ICommand interface in the Commands branch in a CQRS architecture. This is used to mark value objects as query objects

  • The IQueryID interface is used to mark a value object as the query id. This will allows us to query by id using any type of id and even with composed id’s.


I created three interfaces in order to represent the queries in an application This is the core of the Query Engine:


public interface IQueryHandler<TQuery, TQueryResult> where TQuery : IQuery
{
    QueryResults<TQueryResult> HandleQuery(TQuery query, PagingAndSortingInfo pagingAndSortingInfo = null);
}

public interface IQueryHandler<TQueryResult>
{
    QueryResults<TQueryResult> HandleQuery(PagingAndSortingInfo pagingAndSortingInfo = null);
}

public interface IQueryByIDHandler<TQueryID, TQueryResult> where TQueryID : IQueryID
{
    TQueryResult HandleQuery(TQueryID queryID);
}

  • The IQueryHandler overload using the IQuery interface will be used to define explicitly the queries in your application

  • The IQueryHandler overload without the IQuery interface will be used to query all the records from the table

  • The IQueryByIDHandler will be used to query an entity/table/view by ID


This is a graphical representation:










Stay in touch, in the next post I will create base classes to encapsulate common behavior

Monday, October 29, 2012

Unit Testing your Repository Query Logic

  • Have you ever tried to unit test your Query Logic using repositories??

  • If you do, have you ended writing integration tests instead of unit tests??


Even if you have not tried, you might find this post useful.


I´m going to show you a simple way to unit test your Query Logic. It doesn’t matter what back-end system you are using (relational database, in-memory database, xml file, etc etc etc) nor what ORM tool you are using (EF, NHibernate) as long as you encapsulate the code to interact with these external services using an independent component and that you can defer query execution on your back-end system using an IQueryable object.


In order to do it, we need to write the code in a test-friendly way.


Let´s begin with some concepts and principles related to this problem.


  • SRP. Single Responsibility Principle. I believe this is the most important principle out there that should be followed. When you break it, you are creating code that is going to be harder to test. There is however one exception to the rule, when you are writing a controller and I don’t mean a MVC controller, I mean the concept used in the more general sense of the controller in Responsibility Driven Design as a Role Stereotype

  • DI. Dependency Injection


    Dependency injection is a software design pattern that allows a choice of component to be made at run-time rather than compile time


    Dependency Injection as specified before is a Design Pattern and DI by itself does not require the use of a IoC container although, it is used with one most of the time but this is not required.

  • Law of Demeter


    The Law of Demeter (LoD) or Principle of Least Knowledge is a design guideline for developing software, particularly object-oriented programs. In its general form, the LoD is a specific case of loose coupling


    • Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
    • Each unit should only talk to its friends; don't talk to strangers.
    • Only talk to your immediate friends.

For more info watch this Misko Hevery video


So let’s see how a typical Query repository looks like:


public interface IQueryRepository
{
    IQueryable<Movie> GetMovies(string title);
}

public class QueryReprository : IQueryRepository
{
    public IQueryable<Movie> GetMovies(string title)
    {
        var ctx = new MoviesContext();
        var movies = ctx.Movies.AsQueryable();

        if (!string.IsNullOrWhiteSpace(title))
        {
            movies = movies.Where(x => x.Title.Contains(title));
        }

        return movies;
    }
}

Looks familiar? If you write a repository like this, you won't be able to test your query logic in isolation.


There are basically four problems with this implementation that prevent our code to be unit tested:


  • We are using the evil anti-test keyword new inside our repository to create the EF context

  • Using the EF context directly, to retrieve the IQueryable<Movie> collection to perform the query on it instead of just recieve the collection itself

  • Even when the GetMovies method looks extremely simple, it is violating the SRP. This method is doing too much work.


    • It is creating the EF context

    • It is getting the Movies collection

    • It implements the query logic

  • The GetMovies violates the Law of Demeter, because it’s using directly the EF context, which doesn't actually requires. What we need is to work directly with the movies collection instead


All these problems make impossible to unit test our query logic, if you have repositories like this one, you would have to write integration tests instead.


Refactoring the ugly code


Now let’s refactor this simple code to make it test-friendly.


Removing the new operator


In order to remove the new operator we need to use DI.


First we need to write a custom factory in charge to create the EF context for us. (I wrote a blog about a thread-safe implementation)


This is a simplified version


public interface IContextResolver
{
    TContext GetCurrentContext<TContext>() where TContext : DbContext;

    void ReleaseContext();
}

public class ContextResolver : IContextResolver
{
    private HttpContextBase httpContextBase;
    private string connectionString;
    private const string ContextPerRequestItemName = "EF_Context_Per_Request_Item_Name";

    public ContextResolver(HttpContextBase httpContextBase, string connectionString = "")
    {
        Condition.Requires(httpContextBase).IsNotNull();

        this.httpContextBase = httpContextBase;
        this.connectionString = connectionString;
    }

    public TContext GetCurrentContext<TContext>() where TContext : DbContext
    {
        var ctx = this.GetContext<TContext>();

        if (ctx == null)
        {
            ctx = this.CreateContext<TContext>();
        }

        Condition.Ensures(ctx).IsNotNull();
        return ctx;
    }

    public void ReleaseContext()
    {
        var ctx = this.GetContext<DbContext>();

        if (ctx != null)
        {
            ctx.Dispose();
        }
    }

    private TContext GetContext<TContext>() where TContext : DbContext
    {
        return this.httpContextBase.Items[ContextPerRequestItemName] as TContext;
    }

    private TContext CreateContext<TContext>() where TContext : DbContext
    {
        var ctx = default(TContext);

        if (string.IsNullOrWhiteSpace(this.connectionString))
        {
            ctx = (TContext)Activator.CreateInstance(typeof(TContext));
        }
        else
        {
            ctx = (TContext)Activator.CreateInstance(typeof(TContext), this.connectionString);
        }

        this.httpContextBase.Items[ContextPerRequestItemName] = ctx;

        Condition.Ensures(ctx).IsNotNull();
        return ctx;
    }
}

This class is simply acting as a generic factory to instantiate EF Contexts using the Context Per Request pattern


Isolate the EF Context from our repository


This might seem odd at first, but when you clearly identify and separate the responsibilities of each object, your code will become automatically easier to unit-test


So let’s start by identifying what needs to be separated.


The problem in the last code sample is that the repository communicates directly with the EF context to retrieve the IQueryable collection of objects in order to create the query.


What we really need is the collection of objects to work on


Since the IQueryable interface is capable of execute deferred queries, it’s perfect to expose the initial collection of objects to perform the query.


So let’s add the following objects


public interface IMoviesDataProvider
{
    IQueryable<Movie> GetMoviess();
}

This simple interface will be in charge to provide the initial objects as an IQueryable collection to perform the query


public class MoviesDataProvider : IMoviesDataProvider
{
    private IContextResolver contextResolver;

    public MoviesDataProvider(IContextResolver contextResolver)
    {
        this.contextResolver = contextResolver;
    }

    public IQueryable<Movie> GetMoviess()
    {
        var context = this.contextResolver.GetCurrentContext<MoviesContext>();
        var items = context.Movies.AsQueryable();

        Condition.Ensures(items).IsNotNull();
        return items;
    }
}

Notice how the implementation has become really simple. This implementation will be in charge to communicate directly to the backend system to expose the data as an IQueryable collection. Since this object will talk directly with the database using EF, we use DI to pass a reference to the IContextResolver object (remember, this object will be in charge to get the correct instance of the EF context using the Context per Request Pattern)


Implement the Query Logic


The next step is to implement your query logic in your repository object.


This is quite simple since now we have identified and isolated single responsibilities in several objects.


So let’s refactor our repository code:


public class MoviesRepository : IMoviesRepository
{
    private IMoviesDataProvider moviesDataProvider;

    public MoviesRepository(
        IMoviesDataProvider moviesDataProvider)
    {
        this.moviesDataProvider = moviesDataProvider;
    }

    public QueryResults<Movie> FilterMoviesByTitle(string title, PagingInfo pagingInfo = null)
    {
        var movies = this.moviesDataProvider.GetMoviess();

        if (!string.IsNullOrWhiteSpace(title))
        {
            movies = movies.Where(x => x.Title.Contains(title));
        }

        return QueryResults.Of(movies.ToList(), movies.Count());
    }
}

    public interface IMoviesRepository
    {
        QueryResults FilterMoviesByTitle(string title, PagingInfo pagingInfo = null);
    }


There are several things to note on this simple code:


  • The repository no longer depends on the EF Context, now it depends on the IMoviesDataProvider interface which can now be easily mocked to return a dummy in-memory collection to work on when unit testing.

  • The Query Logic is being encapsulated in this layer

  • The result of the query is an in-memory object IList (which is wrapped in the QueryResults object) which means that at this point the query is being executed on the server.

  • Since the query has been executed at this point, we can safely return in-memory objects represented by the IList collection


Some people would argue about the use of the IList instead of returning an IQueryable.


With an IQueryable you get more flexibility since you can actually keep modifying the query all the way until the GUI, but in essence, that’s the problem. Since the query will be spread out across the application, there’s no way to test it in isolation.


For more info about IQueryable


Here is the code of the QueryResults and PagingInfo objects:


public sealed class QueryResults
{
    public static QueryResults<TTarget> Of<TTarget>(IList<TTarget> results, int virtualRowsCount)
    {
        Condition.Requires(results).IsNotNull();
        Condition.Requires(virtualRowsCount).IsGreaterOrEqual(0);

        return new QueryResults<TTarget>(results, virtualRowsCount);
    }
}

public class QueryResults<TTarget>
{
    public QueryResults(IList<TTarget> results, int virtualRowsCount)
    {
        Condition.Requires(results).IsNotNull();
        Condition.Requires(virtualRowsCount).IsGreaterOrEqual(0);

        this.VirtualRowsCount = virtualRowsCount;
        this.Results = results;
    }

    public int VirtualRowsCount { get; protected set; }

    public IList<TTarget> Results { get; protected set; }
}

public sealed class PagingInfo
{
    public PagingInfo(
        int page = 1, 
        int pageSize = 10, 
        string orderByField = "", 
        OrderDirection orderDirection = DataLayer.OrderDirection.Ascending)
    {
        Condition.Requires(page).IsGreaterOrEqual(1);
        Condition.Requires(pageSize).IsGreaterOrEqual(1);;

        this.Page = page;
        this.PageSize = pageSize;
        this.OrderByField = orderByField;
        this.OrderDirection = orderDirection;
    }

    public int Page { get; private set; }

    public int PageSize { get; private set; }

    public string OrderByField { get; private set; }

    public OrderDirection OrderDirection { get; private set; }
}

These objects are simple DTO’s


Writing the Unit Tests


Finally we can have fun writing our unit tests:


[TestClass]
public class MoviesRepositoryTests
{
    [TestClass]
    public class TheFilterByTitleMethod
    {
        [TestMethod]
        public void it_should_not_apply_a_filter_when_the_title_is_empty()
        {
            var fixture = new Fixture().Customize(new AutoMoqCustomization());
            var moviesDataProviderMock = fixture.Freeze<Mock<IMoviesDataProvider>>();
            var movies = Builder<Movie>.CreateListOfSize(10).Build().AsQueryable();

            moviesDataProviderMock.Setup(x => x.GetMoviess()).Returns(movies);

            var sut = fixture.CreateAnonymous<MoviesRepository>();

            sut.Should().NotBeNull();

            var res = sut.FilterMoviesByTitle(string.Empty, null);

            res.Should().NotBeNull();
            res.VirtualRowsCount.Should().Be(10);
            res.Results.Should().NotBeNull().And.NotBeEmpty().And.NotContainNulls()
                .And.OnlyHaveUniqueItems().And.ContainInOrder(movies);
        }

        [TestMethod]
        public void it_should_apply_the_filter_when_the_title_parameter_is_not_null()
        {
            var fixture = new Fixture().Customize(new AutoMoqCustomization());
            var moviesDataProviderMock = fixture.Freeze<Mock<IMoviesDataProvider>>();
            var numberOfElements = 10;
            var numberOfMatchingTitles = 3;
            var title = "Testing";
            var movies = Builder<Movie>.CreateListOfSize(numberOfElements)
                .TheFirst(numberOfMatchingTitles)
                    .With(x => x.Title, title)
                .Build().AsQueryable();
            var matchingMovies = movies.Where(x => x.Title.Contains(title));

            moviesDataProviderMock.Setup(x => x.GetMoviess()).Returns(movies);

            var sut = fixture.CreateAnonymous<MoviesRepository>();

            var res = sut.FilterMoviesByTitle(title);

            res.Should().NotBeNull();

            res.VirtualRowsCount.Should().Be(numberOfMatchingTitles);
            res.Results.Should().NotBeNull().And.NotBeEmpty().And.NotContainNulls()
                .And.OnlyHaveUniqueItems().And.ContainInOrder(matchingMovies);
            res.Results.Count.Should().Be(numberOfMatchingTitles);
        }
    }
}

Have fun!

Thursday, October 25, 2012

EntityFramework context per request-lifetime thread-safe with Unit Tests

When using EntityFramework, you need a consistent way to manage the context object lifecycle. The most accepted way to do this is creating a context per HTTP Request


I´m going to show you a basic thread-safe implementation.


Building the component


Context Resolver Contract


public interface IContextResolver
{
    TContext GetCurrentContext<TContext>() where TContext : DbContext;

    void ReleaseContext();
}

This interface is really simple, it just defines two methods.


  • The GetCurrentContext method will be used to get or create the EntityFramework context object.

  • The ReleaseContext method will be in charge to call Dispose in your context in order to release resources.


Context Resolver implementation


public class ContextResolver : IContextResolver
{
    private static object syncRoot = new Object();
    private string connectionString;
    private volatile HttpContextBase httpContextBase;
    private const string ContextItemName = "Context_Per_Request";

    public ContextResolver(HttpContextBase httpContext, string connectionString)
    {
        Condition.Requires(httpContext).IsNotNull();
        Condition.Requires(connectionString).IsNotNullOrWhiteSpace();

        this.connectionString = connectionString;
        this.httpContextBase = httpContext;
    }

    public TContext GetCurrentContext<TContext>() where TContext : DbContext
    {
        TContext context = default(TContext);

        lock (syncRoot)
        {
            context = this.httpContextBase.Items[ContextItemName] as TContext;
        }

        if (context == null)
        {
            lock (syncRoot)
            {
                if (context == null)
                {
                    context = (TContext)Activator.CreateInstance(typeof(TContext), this.connectionString);
                    this.httpContextBase.Items.Add(ContextItemName, context);
                }
            }
        }

        Condition.Ensures(context).IsNotNull().IsOfType(typeof(TContext));
        return context;
    }

    public void ReleaseContext()
    {
        DbContext context = default(DbContext);

        lock (syncRoot)
        {
            context = this.httpContextBase.Items[ContextItemName] as DbContext;
        }

        if (context != null)
        {
            context.Dispose();
        }
    }
}

The implementation is straightforward, the only tricky part is the addition of lock statements when reading and writing the EntityFramework context.


The C# specification clearly defines what operations are "atomic" in section 5.5. The atomic operations are reads and writes of variables of any reference type, or, effectively, any built-in value type that takes up four bytes or less


Source


In order to implement the context per HTTP request pattern, we use HttpContext.Items. The objects we store in this dictionary, will be accessible only during the current HTTP request.


Gets a key/value collection that can be used to organize and share data between an IHttpModule interface and an IHttpHandler interface during an HTTP request.


Usage


You just have to configure your DI container (if any) to inject the correct instance of IContextResolver.


Injecting


For simplicity I will inject it in my MVC controller


private IContextResolver contextResolver;

public HomeController(IContextResolver contextResolver)
{
    this.contextResolver = contextResolver;
}

public ActionResult SimpleData()
{
    var ctx = this.contextResolver.GetCurrentContext<pubsEntities>();

    return View(ctx.jobs);
}

In Global.asax


During the whole request, all the calls to IContextResolver.GetCurrentContext are going to return the same context instance, we now need to dispose the context after the request has been processed. We can do this in the PostRequestHandlerExecute application event in the Global.asax file.


public MvcApplication()
{
    this.PostRequestHandlerExecute += MvcApplication_PostRequestHandlerExecute;
}

void MvcApplication_PostRequestHandlerExecute(object sender, EventArgs e)
{
    var resolver = ServiceLocator.Current.GetInstance<IContextResolver>();

    resolver.ReleaseContext();
}

Notice the use of the ServiceLocator... your first impression might be: “hey dude, that’s an anti-pattern”...


Most of the time it is an anti-pattern, but in this case, we are using it inside the Composition Root Object of the Web Application, therefore we are allowed to use the container, actually I could change the code to use directly my DI container (Ninject - Kernel in this case), but this will get me the same result, even though, I would be adding an explicit dependency to Ninject.


Unit Testing


It’s time to show you the unit tests I created for this small but useful component


Builder


I tend to use builders to create my SUT objects, it seems like a consistent way to create testing objects


public class ConcreteResolverBuilder
{
    private ContextResolver Instance { get; set; }

    private static volatile HttpContextBase httpContextBase;
    private static volatile Dictionary<string, object> items;
    private static object syncRoot = new Object();

    public static HttpContextBase HttpContextBase
    {
        get
        {
            if (httpContextBase == null)
            {
                lock (syncRoot)
                {
                    if (httpContextBase == null)
                    {
                        var mock = new Mock<HttpContextBase>();

                        items = new Dictionary<string, object>();
                        mock.Setup(x => x.Items).Returns(items);

                        httpContextBase = mock.Object;
                    }
                }
            }

            httpContextBase.Should().NotBeNull();
            return httpContextBase;
        }
    }

    public ConcreteResolverBuilder Initialize()
    {
        this.Instance = new ContextResolver(
            HttpContextBase,
            ConfigurationManager.ConnectionStrings["Msts"].ConnectionString);

        return this;
    }

    public ContextResolver Build()
    {
        this.Instance.Should().NotBeNull();
        return this.Instance;
    }

    public static implicit operator ContextResolver(ConcreteResolverBuilder builder)
    {
        return builder.Build();
    }
}

I´m implementing a singleton pattern just because I want to mock an HttpContextBase object to simulate a real HTTP request


I´m also configuring the HttpContextBase.Items properties with Moq to return a Dictionary object


Note that since my intention is to simulate concurrent threads, I'm marking my HttpContextBase and Dictionary members as volatile


The Tests


[TestClass]
public class ContextResolverTests
{
    [TestClass]
    public class TheCreateContextInstanceMethod
    {
        [TestMethod]
        public void it_should_resolve_a_valid_instance()
        {
            ContextResolver sut = new ConcreteResolverBuilder().Initialize();
            var res = sut.GetCurrentContext<PubsContext>();

            res.Should().NotBeNull().And.BeOfType<PubsContext>();
        }

        [TestMethod]
        public void it_should_return_the_same_instance_even_when_calling_it_from_different_threads()
        {
            ContextResolver sut = new ConcreteResolverBuilder().Initialize();
            var firstResolvedContext = sut.GetCurrentContext<PubsContext>();
            var numberOfConcurrentProcess = 10000;
            var contextResolverInstances = new BlockingCollection<DbContext>();
            var tasks = new Task[numberOfConcurrentProcess];

            for (int i = 0; i < numberOfConcurrentProcess; i++)
            {
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    var context = new ConcreteResolverBuilder().Initialize().Build().GetCurrentContext<PubsContext>();

                    contextResolverInstances.Add(context);
                }, TaskCreationOptions.LongRunning);
            }

            Task.WaitAll(tasks);

            contextResolverInstances
                .Should()
                    .NotBeNull()
                .And
                    .NotBeEmpty()
                .And
                    .HaveCount(numberOfConcurrentProcess)
                .And
                    .ContainItemsAssignableTo<DbContext>()
                .And
                    .NotContainNulls();

            var firstResolvedContextHashCode = (firstResolvedContext as object).GetHashCode();

            firstResolvedContextHashCode.Should().NotBe(default(int));

            foreach (var item in contextResolverInstances)
            {
                var itemHashCode = (item as object).GetHashCode();

                itemHashCode.Should().NotBe(default(int));
                itemHashCode.Should().Be(firstResolvedContextHashCode);
                item.Should().Be(firstResolvedContext);

                var areReferenceEquals = ReferenceEquals(item, firstResolvedContext);

                areReferenceEquals.Should().BeTrue();
            }
        }
    }
}

  • The first test is really simple, it just ensures that we can create a context

  • The second test is more interesting, this is where I’m actually testing the concurrency of my implementation.


    • I keep track of the first context created to compare all subsequent contexts with this one.


      var firstResolvedContext = sut.GetCurrentContext<PubsContext>();
      
    • I set the number of concurrent operations


      var numberOfConcurrentProcess = 10000;
      
    • Now I create a list to store all the created contexts. Note that I’m using the BlockingCollection object which is thread-safe


      var contextResolverInstances = new BlockingCollection<DbContext>();
      
    • I’m storing all the parallel tasks in an array


      var tasks = new Task[numberOfConcurrentProcess];
      
    • I create and start all the tasks. On each task, I’m creating a new instance of my SUT (my concrete implementation of: IContextResolver) and adding to contextResolverInstances the result of IContextResolver.GetCurrentContext. Also note that I'm using: TaskCreationOptions.LongRunning to force the TPL to run my tasks in background threads


      for (int i = 0; i < numberOfConcurrentProcess; i++)
                  {
                      tasks[i] = Task.Factory.StartNew(() =>
                      {
                          var context = new ConcreteResolverBuilder().Initialize().Build().GetCurrentContext<PubsContext>();
      
                          contextResolverInstances.Add(context);
                      }, TaskCreationOptions.LongRunning);
                  }
      
    • I wait for all the tasks to complete by calling:


      Task.WaitAll(tasks);
      
    • The rest of the code are assertions, to confirm that just one instance was created among all threads




In the next screenshot you can see how the tasks are being executed on different threads





Thursday, October 4, 2012

WCF REST Data service in Visual Studio 2012 Express for Web

If you are using Visual Studio Express for Web, you might notice that the WCF Data Service template is not available to use.


I’m going to explain a step-by-step guide to create a WCF Data Service.


  • Create an empty Web project with the name WcfDataServiceInExpressEditions:

  • Add the following nuget packages:


  • Add the following settings to the web.config right under <configuration>


    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"></modules>
    </system.webServer>
    <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    
  • Create an ADO.NET Entity Data Model and connect to any database you own and drag a couple of tables to the designer

  • Add a new WCF Service to your project name it: PubsService

  • Delete the file containing the interface IPubsService.cs

  • Change the declaration of your service as follows:


    public class PubsService : DataService<Pubs>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
            // Examples:
            config.SetEntitySetAccessRule("jobs", EntitySetRights.AllRead);
            // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
        }
    }
    
  • Change the markup of the .svc file to include the correct factory:


    Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services"
    

That’s it, run the application, and you will see something like this:



This is the list of all the tables configured in the InitializeService method


To test the queries try something like this:


http://localhost:55575/PubsService.svc/jobs/?$filter=min_lvl gt 150



Download the code of this article


Happy coding

Sunday, September 23, 2012

Custom ASP.NET SiteMapProvider combining a database, the file system and static content

Hi, I had some trouble while creating a custom SiteMapProvider, at first and after reading several blogs, it appeared that this wasn’t so easy.... but it turns out that it’s really simple once you know the basis.


The SiteMapProvider I want to create, is one that combines data from a database, files in the file system and static nodes defined in the XML sitemap file.


Note: This is not about the Sitemap.xml file used by search engine crawlers, the site map I’m going to build is the sitemap provider used in ASP.Net to ptovide navigation.


Let’s begin.


First thing first. In ASP.Net there’s a default sitemap provider already registered in the web.config file located in: %windir%\Microsoft.NET\Framework\%version%\Config\web.config


And looks like:


    <siteMap>
        <providers>
            <add siteMapFile="web.sitemap" name="AspNetXmlSiteMapProvider"
                type="System.Web.XmlSiteMapProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </providers>
    </siteMap>

The XmlSiteMapProvider inherits from: StaticSiteMapProvider


Most of the blogs will tell you that you must inherit StaticSiteMapProvider and implement your own provider almost from scratch. But it turns out that you can inherit XmlSiteMapProvider and customize it. I have not found a problem so far, if you know a problem with this approach please let me know.


So lets create our solution. (I am working with Visual Studio 2012 Express for Web V.11.0.50727.1 RTMREL)


Adding static content


  • Create an empty Web Application called MixedSiteMapProvider in Visual Studio
  • Create a class right under the project root called: CustomSitemapProvider and inherit from XmlSiteMapProvider
  • Register the custom sitemap provider in the web.config file:

        <system.web>
          <siteMap defaultProvider="CustomProvider">
            <providers>
              <add name="CustomProvider" type="MixedSiteMapProvider.CustomSitemapProvider" siteMapFile="Web.sitemap" />
            </providers>
          </siteMap>
        </system.web>

  • Create a sitemap file called Web.sitemap right under the root project and add the following content:

        <?xml version="1.0" encoding="utf-8" ?>
        <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
            <siteMapNode url="~/" title="Home"  description="Static file">
              <siteMapNode url="~/Default2.aspx" title="Default2" description="Another static file">
              </siteMapNode>
              <siteMapNode title="My File System Content" url="" description="">
              </siteMapNode>
            </siteMapNode>
        </siteMap>

  • Create a MasterPage called Site.master right under the project root and add the following code:

        <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="MixedSiteMapProvider.Site" %>

        <!DOCTYPE html>

        <html xmlns="http://www.w3.org/1999/xhtml">
        <head runat="server">
            <title></title>
            <asp:ContentPlaceHolder ID="head" runat="server">
            </asp:ContentPlaceHolder>
        </head>
        <body>
            <form id="form1" runat="server">
                <asp:SiteMapDataSource runat="server" ID="smds" ShowStartingNode="true" />
                <div>
                    <asp:SiteMapPath runat="server" ID="siteMapPath1">
                    </asp:SiteMapPath>
                </div>
                <div>
                    <asp:Menu runat="server" ID="menu" DataSourceID="smds">
                    </asp:Menu>
                </div>
                <div>
                    <asp:TreeView runat="server" ID="tv" DataSourceID="smds">
                    </asp:TreeView>
                </div>
                <div>
                    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
                    </asp:ContentPlaceHolder>
                </div>
            </form>
        </body>
        </html>

  • Create a content ASPX file called Default.aspx right under the project root and select Site.master as its MasterPage

  • Create a content ASPX file called Default2.aspx right under the project root and select Site.master as its MasterPage

  • Run the application and you will see the sitemap provider works as expected reading the content of the Web.sitemap file


Adding File System content


Now we are going to discover the files under a custom path to add them as part of our SiteMapProvider


The StaticSiteMapProvider and the XmlSiteMapProvider works similar. There’s a method called BuildSiteMap in charge to build the nodes structure. The tricky part is to know that this method is actually going to be called on many internal operations of the base class. For example when adding a child node (AddNode method), when finding a node (FindSiteMapNode and FindSiteMapNodeFromKey method), etc.


This is important to keep it in mind because this means that if you do not write taking this consideration you could get a StackOverFlowException. The easiest way to solve this, is creating a flag at instance level (more about this in a minute)


ASP.Net keeps in memory each sitemap provider instance as long as the application is not restarted. This means that by default we get cached our custom sitemap provider. Since we already saw that the BuildSiteMap method is going to be called several times on each page for every concurrent user, we need to build our implementation to be thread-safe. The easiest way to do this is by locking each action with lock


OK, lets roll and create our custom sitemap nodes from the file system.


  • Create a subfolder called Topics right under the project root and add three ASPX files, name them Page1.aspx, Page2.aspx and Page3.aspx

  • Update our CustomSitemapProvider as follows:


using System;
using System.IO;
using System.Linq;
using System.Web;

namespace MixedSiteMapProvider
{
    public class CustomSitemapProvider : XmlSiteMapProvider
    {
        private const string FileSystemContentNodeTitle = "My File System Content";
        private readonly object LockObject = new Object();
        private SiteMapNode WorkingNode { get; set; }
        private bool BuildingNodes { get; set; }

        // this method has to be overriden in order to create the sitemap nodes
        public override SiteMapNode BuildSiteMap()
        {
            // we block the method to make it thread-safe
            lock (LockObject)
            {
                // this condition is the KEY, we need to ensure that this method is executed
                // only once. The problem is that internally, the SiteMapProvider class calls
                // this method several times. If we do not use this condition, we would get a
                // StackOverflowException
                if (this.BuildingNodes)
                {
                    return this.WorkingNode;
                }

                // we call the base BuildSiteMap method to get all the static nodes registered
                // statically in the Web.sitemap file. From here, we will configure this SiteMapNode
                // collection to add our custom nodes
                this.WorkingNode = base.BuildSiteMap();
                this.BuildingNodes = true;

                var fileSystemNode = 
                    this.WorkingNode.ChildNodes.OfType<SiteMapNode>().FirstOrDefault(x => x.Title.Equals(FileSystemContentNodeTitle, StringComparison.InvariantCultureIgnoreCase));

                if (fileSystemNode == null)
                {
                    // if we didn't find a node to explicitly add our content from the file system
                    // we will create a custom node
                    fileSystemNode = new SiteMapNode(this, "FileSystemNode", string.Empty, FileSystemContentNodeTitle);
                    this.AddNode(fileSystemNode, this.WorkingNode);
                }

                // we iterate through all the files contained in the filesystem folder
                foreach (var file in Directory.GetFiles(HttpContext.Current.Server.MapPath("~/Topics/"), "*.aspx"))
                {
                    this.AddNode(
                        new SiteMapNode(this, file, VirtualPathUtility.ToAbsolute("~/Topics/") + Path.GetFileName(file), Path.GetFileNameWithoutExtension(file)), 
                        fileSystemNode);
                }

                return this.WorkingNode;
            }
        }
    }
}

I think the code is self explanatory (along the comments).


I just want to emphasize the importance of the lock process lock (LockObject) to make the method thread-safe and the flag condition if (this.BuildingNodes) to prevent the execution of the method more than once.


If you run your application you will see something like:






Adding database records


The last step is to complement our dynamic sitemap with records from the database.


Since we already created the most difficult part, this should be really simple.


I’m going to use the PUBS database, and let say that we want to show in our navigation all the job descriptions that exist in the jobs table and inside each one of these categories we want to list all its employees.


  • Get the PUBS database from here and install it

  • Add the following connection string to your web.config file


  <connectionStrings>
    <add name="Pubs" providerName="System.Data.SqlClient" connectionString="Data Source=.\sqlexpress;Initial Catalog=pubs;Integrated Security=True" />
  </connectionStrings>


  • Create a new LINQ To SQL class named Pubs right under the root of your project

  • Connect to the database and drag and drop the jobs and employee tables to de PubsDataContext designer. Save the file and close it

  • Add three content ASPX files choosing the Site.master master page right under the root of your project and name them: JobsList.aspx, JobDetails.aspx and EmployeeDetails.aspx

  • Add the following markup to the JobsList.aspx file



<%@ Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="JobsList.aspx.cs" Inherits="MixedSiteMapProvider.JobsList" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <asp:LinqDataSource runat="server" ID="lds"
        TableName="jobs" ContextTypeName="MixedSiteMapProvider.PubsDataContext">
    </asp:LinqDataSource>
    <asp:GridView runat="server" ID="gv" DataSourceID="lds" AutoGenerateColumns="false">
        <Columns>
            <asp:HyperLinkField HeaderText="Job description" DataTextField="job_desc" DataNavigateUrlFormatString="~/JobDetails.aspx?id={0}" DataNavigateUrlFields="job_id" />
        </Columns>
    </asp:GridView>
</asp:Content>


  • Add the following markup to JobDetails.aspx


    <asp:LinqDataSource runat="server" ID="lds"
        TableName="jobs"
        ContextTypeName="MixedSiteMapProvider.PubsDataContext">
    </asp:LinqDataSource>
    <asp:QueryExtender runat="server" ID="qeJob" TargetControlID="lds">
        <asp:PropertyExpression>
            <asp:QueryStringParameter Name="job_id" Type="Int16" ValidateInput="true" QueryStringField="id" />
        </asp:PropertyExpression>
    </asp:QueryExtender>
    <asp:DetailsView runat="server" DataSourceID="lds" />
    <hr />
    <asp:LinqDataSource runat="server" ID="ldsempl"
        TableName="employee"
        ContextTypeName="MixedSiteMapProvider.PubsDataContext">
    </asp:LinqDataSource>
    <asp:QueryExtender runat="server" ID="qeEmpl" TargetControlID="ldsempl">
        <asp:PropertyExpression>
            <asp:QueryStringParameter QueryStringField="id" Type="Int16" ValidateInput="true" Name="job_id" />
        </asp:PropertyExpression>
    </asp:QueryExtender>
    <asp:GridView runat="server" ID="gv" DataSourceID="ldsempl" AutoGenerateColumns="false" ItemType="MixedSiteMapProvider.employee">
        <Columns>
            <asp:TemplateField HeaderText="Employee name">
                <ItemTemplate>
                    <asp:HyperLink NavigateUrl='<%# "~/EmployeeDetails.aspx?id=" + Item.emp_id %>' runat="server" Text='<%# Item.fname + " " + Item.lname %>' />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>


  • Add the following code to EmployeeDetails.aspx


    <asp:LinqDataSource runat="server" ID="lds"
        TableName="employee" ContextTypeName="MixedSiteMapProvider.PubsDataContext">
    </asp:LinqDataSource>
    <asp:QueryExtender runat="server" ID="qeEmployee" TargetControlID="lds">
        <asp:PropertyExpression>
            <asp:QueryStringParameter Name="emp_id" Type="String" ValidateInput="true" QueryStringField="id" />
        </asp:PropertyExpression>
    </asp:QueryExtender>
    <asp:DetailsView runat="server" DataSourceID="lds" />


  • Add the following node to the Web.sitemap file


      <siteMapNode title="PUBS Jobs">
      </siteMapNode>


  • Add the following code to the CustomSitemapProvider class


private const string PubsContentNodeTitle = "PUBS Jobs";

  • Add the following code to the end of the BuildSiteMap method in the CustomSitemapProvider class, just before the return this.WorkingNode; line


        // adding the jobs and employees from the database to the sitemap
        var pubsNode = this.WorkingNode.ChildNodes.OfType<SiteMapNode>().FirstOrDefault(x => x.Title.Equals(PubsContentNodeTitle, StringComparison.InvariantCultureIgnoreCase));

        // if the node does not exists, we will create a new node to serve as the base
        // for our database nodes
        if (pubsNode == null)
        {
            pubsNode = new SiteMapNode(this, PubsContentNodeTitle, VirtualPathUtility.ToAbsolute("~/JobsList.aspx"), PubsContentNodeTitle);
            this.AddNode(pubsNode, this.WorkingNode);
        }

        using (var ctx = new PubsDataContext())
        {
            foreach (var empl in ctx.employee)
            {
                var job = empl.jobs;
                var jobNode = this.FindSiteMapNodeFromKey(string.Format("Job:{0}", job.job_desc));

                // if the job node has not been created yet, we will create it
                if (jobNode == null)
                {
                    jobNode = new SiteMapNode(this, string.Format("Job:{0}", job.job_desc), VirtualPathUtility.ToAbsolute("~/JobDetails.aspx?id=" + job.job_id.ToString()), job.job_desc);
                    this.AddNode(jobNode, pubsNode);
                }

                // we add the employee node
                this.AddNode(
                    new SiteMapNode(this, "Employee:" + empl.emp_id, VirtualPathUtility.ToAbsolute("~/EmployeeDetails.aspx?id=" + empl.emp_id), empl.fname + " " + empl.lname), 
                    jobNode);
            }
        }


That’s it.... wow this was a really loong post... sorry about that. There was a lot of code for a simple task =(


If you run the application you will something like this: (after applying some style)




Download the code of this article

Browse the full code in Github

Monday, September 17, 2012

Enabling unobtrusive validation from scratch in ASP.Net 4.5 webforms

Download the code of this article

I was playing with Visual Studio 2012 specifically with the new Validation features and I found they work great, specially the new unobtrusive validation, then I tried to enable this kind of validation on a new Empty Web Application, and I found that this is not out-of-the-box, you need to make some configurations to your Web Application.

There are three ways to enable the unobtrusive validation on a Web Application:

Via the web.config file


<configuration>  
  <appsettings>  
   <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms">  
  </add></appsettings>  
 </configuration>  

Via the Global.asax file

protected void Application_Start(object sender, EventArgs e)
{
   ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None;
}

On each page:
protected void Page_Load(object sender, EventArgs e)
{
   this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.WebForms;
}

To disable the unobtrusive validation set the UnobtrusiveValidationMode property to None

Unobtrusive validation is actually enabled by default in ASP.Net 4.5.

We'll start with a simple example, create an Empty Web Application and add a MasterPage called Site.master and a content page for this master called Default.aspx.

Add the following code to the Default.aspx file:


    <asp:TextBox runat="server" ID="txt" />
    <asp:RequiredFieldValidator ErrorMessage="txt is required" ControlToValidate="txt" runat="server" Text="*" Display="Dynamic" />
    <asp:Button Text="Send info" runat="server" />



If you try to run a simple ASPX page using a validator, the following exception will be thrown:
"WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. Please add a ScriptResourceMapping named jquery(case-sensitive)".
Before fixing this, let's disable the unobtrusive validation to see the result.

On the page:

protected void Page_Load(object sender, EventArgs e)
{
   this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
}

Now run the page and the validation will work as it used to work in ASP.Net 4.0

If you examine the rendered HTML, you will see that the gross inline script is rendered:



<script type="text/javascript">
//<![CDATA[
var Page_Validators =  new Array(document.getElementById("ContentPlaceHolder1_ctl00"));
//]]>
</script>

<script type="text/javascript">
//<![CDATA[
var ContentPlaceHolder1_ctl00 = document.all ? document.all["ContentPlaceHolder1_ctl00"] : document.getElementById("ContentPlaceHolder1_ctl00");
ContentPlaceHolder1_ctl00.controltovalidate = "ContentPlaceHolder1_txt";
ContentPlaceHolder1_ctl00.errormessage = "txt is required";
ContentPlaceHolder1_ctl00.display = "Dynamic";
ContentPlaceHolder1_ctl00.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
ContentPlaceHolder1_ctl00.initialvalue = "";
//]]>
</script>


<script type="text/javascript">
//<![CDATA[

var Page_ValidationActive = false;
if (typeof(ValidatorOnLoad) == "function") {
    ValidatorOnLoad();
}

function ValidatorOnSubmit() {
    if (Page_ValidationActive) {
        return ValidatorCommonOnSubmit();
    }
    else {
        return true;
    }
}
        
document.getElementById('ContentPlaceHolder1_ctl00').dispose = function() {
    Array.remove(Page_Validators, document.getElementById('ContentPlaceHolder1_ctl00'));
}
//]]>
</script>



Now let's re-enable the unobtrusive validation. In order to fix the previous exception, we need to install the following Nuget packages: (I like to install jQuery first to get the latest version, although this is not required.)



  1. jQuery
  2. ASPNET.ScriptManager.jQuery
  3. Microsoft.AspNet.ScriptManager.MSAjax
  4. Microsoft.AspNet.ScriptManager.WebForms

At this point, if you run the application again, the exception will be gone =) how cool eh?. This is because the following Nuget packages automatically register the scripts needed with the ScriptManager control.

Let's examine the code added by these Nuget packages using ILSpy:

  • AspNet.ScriptManager.jQuery
    
        public static class PreApplicationStartCode
        {
            public static void Start()
            {
                string str = "1.8.1";
                ScriptManager.ScriptResourceMapping.AddDefinition("jquery", new ScriptResourceDefinition
                {
                    Path = "~/Scripts/jquery-" + str + ".min.js",
                    DebugPath = "~/Scripts/jquery-" + str + ".js",
                    CdnPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-" + str + ".min.js",
                    CdnDebugPath = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-" + str + ".js",
                    CdnSupportsSecureConnection = true,
                    LoadSuccessExpression = "window.jQuery"
                });
            }
        }
    
  • Microsoft.AspNet.ScriptManager.MSAjax
    public static void Start()
    {
        ScriptManager.ScriptResourceMapping.AddDefinition("MsAjaxBundle", new ScriptResourceDefinition
        {
            Path = "~/bundles/MsAjaxJs",
            CdnPath = "http://ajax.aspnetcdn.com/ajax/4.5/6/MsAjaxBundle.js",
            LoadSuccessExpression = "window.Sys",
            CdnSupportsSecureConnection = true
        });
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjax.js", "window.Sys && Sys._Application && Sys.Observer");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxCore.js", "window.Type && Sys.Observer");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxGlobalization.js", "window.Sys && Sys.CultureInfo");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxSerialization.js", "window.Sys && Sys.Serialization");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxComponentModel.js", "window.Sys && Sys.CommandEventArgs");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxNetwork.js", "window.Sys && Sys.Net && Sys.Net.WebRequestExecutor");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxHistory.js", "window.Sys && Sys.HistoryEventArgs");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxWebServices.js", "window.Sys && Sys.Net && Sys.Net.WebServiceProxy");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxTimer.js", "window.Sys && Sys.UI && Sys.UI._Timer");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxWebForms.js", "window.Sys && Sys.WebForms");
        PreApplicationStartCode.AddMsAjaxMapping("MicrosoftAjaxApplicationServices.js", "window.Sys && Sys.Services");
    }
    private static void AddMsAjaxMapping(string name, string loadSuccessExpression)
    {
        ScriptManager.ScriptResourceMapping.AddDefinition(name, new ScriptResourceDefinition
        {
            Path = "~/Scripts/WebForms/MsAjax/" + name,
            CdnPath = "http://ajax.aspnetcdn.com/ajax/4.5/6/" + name,
            LoadSuccessExpression = loadSuccessExpression,
            CdnSupportsSecureConnection = true
        });
    }
    
  • Microsoft.AspNet.ScriptManager.WebForms
    
    public static void Start()
    {
        ScriptManager.ScriptResourceMapping.AddDefinition("WebFormsBundle", new ScriptResourceDefinition
        {
            Path = "~/bundles/WebFormsJs",
            CdnPath = "http://ajax.aspnetcdn.com/ajax/4.5/6/WebFormsBundle.js",
            LoadSuccessExpression = "window.WebForm_PostBackOptions",
            CdnSupportsSecureConnection = true
        });
    }
    

As you can see these Nuget packages automatically register the scripts using the ScriptManager object (besides installing the required JavaScript files)

Run the application and examine the rendered HTML. You will note that it's much cleaner now, in this case the inline script has been moved to an external file that can be rendered using bundles to increase performance. The rendered script looks like:

<script src="Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js" type="text/javascript"></script>
<script src="Scripts/jquery-1.8.1.js" type="text/javascript"></script>

Much better right?. Notice how ASP.Net used HTML5 custom attributes:


<input name="ctl00$ContentPlaceHolder1$txt" type="text" id="ContentPlaceHolder1_txt" />
    <span data-val-controltovalidate="ContentPlaceHolder1_txt" data-val-errormessage="txt is required" data-val-display="Dynamic" id="ContentPlaceHolder1_ctl00" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="display:none;">*</span>
    <input type="submit" name="ctl00$ContentPlaceHolder1$ctl01" value="Send info" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;ctl00$ContentPlaceHolder1$ctl01&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" />

The data-val-* are custom attributes used by the unobtrusive validation engine

If you click the button to trigger the validation you will be pleased to see that it works as expected...but we are not done yet =/

The settings we have applied won't work if you intend to use an UpdatePanel control (yeah the evil UpdatePanel again...). This is because this control requires a ScriptManager control on the page (or MasterPage) and we do not have any yet. So let's add a simple ScriptManager control to the master page and see what happens. Add the following code to the Site.master page right under the <form...


        <asp:ScriptManager runat="server" ID="scriptManager">
        </asp:ScriptManager>

Run the page again and fire the validation... oops... the client validation has gone =( We only have server validation. I'm not sure why this happens but my best guess is that the just added ScriptManager control is overriding our code settings.

To fix it, change the declaration of the ScriptManager control on the Site.master page to:


    <asp:ScriptManager runat="server" ID="scriptManager1">
        <Scripts>
            <asp:ScriptReference Name="MsAjaxBundle" />
            <asp:ScriptReference Name="jquery" />
            <asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" />
            <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" />
            <asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" />
            <asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" />
            <asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" />
            <asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" />
            <asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" />
            <asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" />
            <asp:ScriptReference Name="WebFormsBundle" />
        </Scripts>
    </asp:ScriptManager>

Run the application and our little example will work again as expected

Sadly these new settings are the equivalent to the settings added by code and we need to add them to be able to use the traditional Microsoft AJAX controls.

There's one last thing we need to configure, this is because there's actually a bug with the ValidationSummary control.

To test it, update the Default.aspx page as follows:


    <asp:ValidationSummary ID="ValidationSummary1" runat="server" />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <br />
    <asp:TextBox runat="server" ID="txt" />
    <asp:RequiredFieldValidator ErrorMessage="txt is required" ControlToValidate="txt" runat="server" Text="*" Display="Dynamic" />
    <asp:Button Text="Send info" runat="server" />

Now run the page again, scroll down until you can see the button and click it... woot your page jumped to the top... the workaround to solve this little bug is to add the following code to the Site.master


        <script>
            window.scrollTo = function () {

            };
        </script>

Reference links:



If you found this post useful please leave your comments, I will be happy to hear from you.