tag:blogger.com,1999:blog-32197915448740332062024-03-13T08:10:22.175-07:00Jupaol's coding adventuresCoding for fun with the .Net FrameworkAnonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-3219791544874033206.post-88084874036937390832015-03-03T15:38:00.000-08:002015-03-03T15:42:54.908-08:00Changing TransactionScope - Timeout at runtime<p>So... <code class="prettyprint cs">TransactionScope</code>...</p>
<p>If you have worked with the <code class="prettyprint cs">TransactionScope</code> in the past you might have noticed that it can be tricky, <a href="http://blogs.msdn.com/b/dbrowne/archive/2010/06/03/using-new-transactionscope-considered-harmful.aspx">and even dangerous</a> if you don't use it correctly.</p>
<p>So anyways, I have tried to change the <code class="prettyprint cs">TransactionScope</code> timeout property at runtime and the thing still goes back to the default timeout of 10 minutes.</p>
<p>This is because the 'TransactionScope' uses the following object to get the <em>maximum timeout for a transaction</em>: <code class="prettyprint cs">TransactionManager.MaximumTimeout</code>. If you decompile it you will see the following:</p>
<pre class="prettyprint cs"><code class="prettyprint cs">if (!TransactionManager._cachedMaxTimeout)
{
lock (TransactionManager.ClassSyncObject)
{
if (!TransactionManager._cachedMaxTimeout)
{
TransactionManager._maximumTimeout = TransactionManager.MachineSettings.MaxTimeout;
TransactionManager._cachedMaxTimeout = true;
}
}
}
</code></pre>
<p>Pay special attention to: <strong><code class="prettyprint cs">TransactionManager.MachineSettings.MaxTimeout</code></strong></p>
<p>It always reads from the machine settings defined on the machine.config (C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config)</p>
<p>And this specific section is defined as follows:</p>
<pre class="prettyprint xml"><code><sectionGroup name="system.transactions" type="System.Transactions.Configuration.TransactionsSectionGroup, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null">
<section name="defaultSettings" type="System.Transactions.Configuration.DefaultSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
<section name="machineSettings" type="System.Transactions.Configuration.MachineSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null" allowDefinition="MachineOnly" allowExeDefinition="MachineOnly"/>
</sectionGroup>
</code></pre>
<p>Note that it's marked with: <strong><code class="prettyprint xml">allowExeDefinition="MachineOnly"</code></strong> that's why we cannot override it in our config files - shame :(</p>
<p>So basically I can think in two options to increase the maximum transaction timeout:</p>
<h3>Updating the machine.config file</h3>
<p>You could do it although I wouldn't recommend it so I won't bother to show you how... <a href="http://stackoverflow.com/questions/12055511/transaction-scope-timeout-on-10-minutes">well take a quick look</a></p>
<h3>Hacking - using reflection</h3>
<p>Or do it the Ninja way...</p>
<pre class="prettyprint cs"><code class="prettyprint cs">private void ConfigureTransactionTimeout(TimeSpan value)
{
//initializing internal stuff
// ReSharper disable once NotAccessedVariable
var timespan = TransactionManager.MaximumTimeout;
//initializing it again to be sure
// ReSharper disable once RedundantAssignment
timespan = TransactionManager.MaximumTimeout;
SetTransactionManagerField("_cachedMaxTimeout", true);
SetTransactionManagerField("_maximumTimeout", value);
Condition.Ensures(TransactionManager.MaximumTimeout, "TransactionManager.MaximumTimeout").IsEqualTo(value);
}
private void SetTransactionManagerField(string fieldName, object value)
{
var cacheField = typeof (TransactionManager).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static);
Condition.Ensures(cacheField, "cacheField").IsNotNull();
cacheField.SetValue(null, value);
}
</code></pre>
<p>And use it like:</p>
<pre class="prettyprint cs"><code class="prettyprint cs">ConfigureTransactionTimeout(TimeSpan.FromMinutes(20));
var timespan = TransactionManager.MaximumTimeout;
var transactionOptions = new TransactionOptions
{
IsolationLevel = isolationLevel,
Timeout = timespan
};
var ts = new TransactionScope(transactionScopeOption, transactionOptions);
</code></pre>
<p>There you go</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com0Concord, CA, USA37.9779776 -122.031073337.877841100000005 -122.1924348 38.0781141 -121.8697118tag:blogger.com,1999:blog-3219791544874033206.post-73906460073938180662015-03-02T18:05:00.000-08:002015-03-02T18:08:37.092-08:00Testing Ninject container<p>I've found really useful to test our IoC container to make sure that all the components that are registered can be resolved.</p>
<p>This is the way I usually test my Ninject container</p>
<h3>The model</h3>
<p>so let's say that we have the following model:</p>
<pre class="prettyprint cs"><code>public interface ICommand { }
public interface ICommandHandler<in T> where T : ICommand
{
void Handle(T command);
}
public class DeploySqlScriptsUsingAGlobalTransactionCommand : ICommand
{
public DeploySqlScriptsUsingAGlobalTransactionCommand(IEnumerable<string> scripts)
{
Scripts = scripts;
}
public IEnumerable<string> Scripts { get; private set; }
}
public class DeploySqlScriptsUsingAGlobalTransactionCommandHandler :
ICommandHandler<DeploySqlScriptsUsingAGlobalTransactionCommand>
{
private readonly IScriptDeployerService _scriptDeployerService;
public DeploySqlScriptsUsingAGlobalTransactionCommandHandler(IScriptDeployerService scriptDeployerService)
{
_scriptDeployerService = scriptDeployerService;
}
public void Handle(DeploySqlScriptsUsingAGlobalTransactionCommand command)
{
//shalalalalal
command.Scripts.ToList().ForEach(_scriptDeployerService.Deploy);
Console.WriteLine("Scripts deployed");
}
}
public interface IScriptDeployerService
{
void Deploy(string script);
}
</code></pre>
<p>Note that we don't have a concrete implementation of <code>IScriptDeployerService</code></p>
<h3>The test</h3>
<p>So we create this test to make sure that the container is valid:</p>
<pre class="prettyprint cs"><code>[TestMethod]
public void it_should_resolve_all_registered_components_in_the_container()
{
#region Binding container
var kernel = new StandardKernel();
kernel.Bind(config =>
{
config.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces();
});
ServiceLocator.SetLocatorProvider(() => new NinjectServiceLocator(kernel));
kernel.Bind<IServiceLocator>().ToConstant(ServiceLocator.Current);
#endregion
#region Testing container
var field = typeof (KernelBase).GetField("bindings",
BindingFlags.Instance | BindingFlags.NonPublic);
field.Should().NotBeNull();
var bindingsMap = field.GetValue(kernel) as Multimap<Type, IBinding>;
bindingsMap.Should().NotBeNull();
bindingsMap.Should().NotBeEmpty();
var locator = ServiceLocator.Current.GetInstance<IServiceLocator>();
locator.Should().NotBeNull();
bindingsMap.SelectMany(x => x.Value).ToList()
.ForEach(binding => ServiceLocator.Current.Invoking(instance =>
{
var services = instance.GetAllInstances(binding.Service);
services.Count().Should().BeGreaterOrEqualTo(1);
if (services.Count() == 1)
{
instance.GetInstance(binding.Service);
}
}).ShouldNotThrow());
#endregion
}
</code></pre>
<h3>The error</h3>
<p>When we run the test we receive the following error from Ninject:</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV7VhqEgIJ0Jtg22YiQZAwN9Ma1W60dOdb-_0vTJJQ2i0m_t5BHAP4DvXWu23MQjO3y9c8Y7W9yawApuEASbtIIqaeVUdtLpnUq5RlOxG1_eV2DYE-YsF_-TI3FVn8v5A9kX3F71mzrTs/s1600/TestResults02.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgV7VhqEgIJ0Jtg22YiQZAwN9Ma1W60dOdb-_0vTJJQ2i0m_t5BHAP4DvXWu23MQjO3y9c8Y7W9yawApuEASbtIIqaeVUdtLpnUq5RlOxG1_eV2DYE-YsF_-TI3FVn8v5A9kX3F71mzrTs/s320/TestResults02.png" /></a>
<blockquote>
<p>Result Message:
Did not expect any exception, but found Ninject.ActivationException with message "Error activating IScriptDeployerService
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IScriptDeployerService into parameter scriptDeployerService of constructor of type DeploySqlScriptsUsingAGlobalTransactionCommandHandler
1) Request for ICommandHandler{DeploySqlScriptsUsingAGlobalTransactionCommand}</p>
</blockquote>
<p>Very explicit</p>
<h3>The fix</h3>
<p>So now let's fix it:</p>
<p>Let's add the missing concrete implementation:</p>
<pre class="prettyprint cs"><code>public class ScriptDeployerService : IScriptDeployerService
{
public void Deploy(string script)
{
Console.WriteLine("Script deployed: {0}", script);
}
}
</code></pre>
<h3>The result</h3>
<p>And now our test pass =) Awesome</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWAJhv5B2KF4A1PRjpvOKEc6aGIkvYGstL9OXfV7lYwE2msUWntp6AC04UkYU4y_pWtpL47zOEzYEu7ZIyJnZTKnXYyLkne15BfE79KKatmvOHoNMGBIEYrgmrUZOjtNGdm8GWogrCoaE/s1600/TestResults01.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWAJhv5B2KF4A1PRjpvOKEc6aGIkvYGstL9OXfV7lYwE2msUWntp6AC04UkYU4y_pWtpL47zOEzYEu7ZIyJnZTKnXYyLkne15BfE79KKatmvOHoNMGBIEYrgmrUZOjtNGdm8GWogrCoaE/s320/TestResults01.png" /></a>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com0Concord, CA, USA37.9779776 -122.031073337.877841100000005 -122.1924348 38.0781141 -121.8697118tag:blogger.com,1999:blog-3219791544874033206.post-43836965987369109112015-03-02T03:21:00.001-08:002015-03-02T11:53:22.228-08:00Binding Decorators - Mediators with Ninject<p>So let's talk about Ninject and how to bind decorators, I will illustrate it decorating Command Handlers in a CQRS architecture</p>
<p>Using this pattern will allow you to follow the Single Responsibility Principle in your command handlers.</p>
<p>Why? Let's take a look</p>
<p>So a typical command handler will validate its command and to achieve this we have several options:</p>
<h3>Inside the command</h3>
<pre class="prettyprint cs"><code>public class GrantAccessToNightClubCommandHandler : ICommandHandler<GrantAccessToNightClub>
{
public void Handle(GrantAccessToNightClub command)
{
if (command.Age < 21)
{
throw new InvalidOperationException("Age was not satisfied");
}
//do stuff
}
}
</code></pre>
<p>So I don't like this approach because the validation is lost inside the handlers <a href="http://www.infoq.com/presentations/Making-Roles-Explicit-Udi-Dahan">take a look to Make roles explicit by Udi Dahan</a></p>
<p>So let's try another approach</p>
<h3>Injecting validators into the command handler</h3>
<pre class="prettyprint cs"><code>public class GrantAccessToNightClubCommandHandler : ICommandHandler<GrantAccessToNightClub>
{
private readonly IValdiatorRunner<GrantAccessToNightClub> _valdiatorRunner;
public GrantAccessToNightClubCommandHandler(IValdiatorRunner<GrantAccessToNightClub> valdiatorRunner)
{
_valdiatorRunner = valdiatorRunner;
}
public void Handle(GrantAccessToNightClub command)
{
_valdiatorRunner.Run(command);
//valid at this point
//do stuff
}
}
</code></pre>
<p>I won't go into detail about the <code>IValidatorRunner</code> implementation, but it loads dynamically validators for the specified command and runs them all</p>
<p>I used to like this technique since it provides a good separation of concerns, making the roles explicit but still... it looks like the command handler is doing too much, it's not following the SRP</p>
<p>Let's see the third option</p>
<h3>Using Decorators</h3>
<pre class="prettyprint cs"><code>public class CommandHandlerValidator<TCommand> : ICommandHandler<TCommand> where TCommand : ICommand
{
private readonly IEnumerable<IValdiator<TCommand>> _valdiators;
private readonly ICommandHandler<TCommand> _commandHandler;
public CommandHandlerValidator(
IEnumerable<IValdiator<TCommand>> valdiators,
ICommandHandler<TCommand> commandHandler)
{
_valdiators = valdiators;
_commandHandler = commandHandler;
}
public void Handle(TCommand command)
{
_valdiators.ToList().ForEach(x => x.ApplyTo(command));
// wow everything is valid here, lets continue
_commandHandler.Handle(command);
}
}
public class GrantAccessToNightClubCommandHandler : ICommandHandler<GrantAccessToNightClub>
{
public void Handle(GrantAccessToNightClub command)
{
//do stuff
}
}
</code></pre>
<p>Wow, now it looks like we are following the SRP therefore everything starts to look simpler and easier to maintain and extend. Just by following the SRP. Wow it blows my mind</p>
<p>Now imagine that we want to apply authorization to our command handlers, again we can solve this by decorating them like:</p>
<pre class="prettyprint cs"><code>public class CommandHandlerAuthenticator<TCommand> : ICommandHandler<TCommand> where TCommand : ICommand
{
private readonly ICommandHandler<TCommand> _commandHandler;
public CommandHandlerAuthenticator(ICommandHandler<TCommand> commandHandler)
{
_commandHandler = commandHandler;
}
public void Handle(TCommand command)
{
Authenticate(command);
//when authenticated simply...
_commandHandler.Handle(command);
}
private void Authenticate(TCommand command)
{
// some authentication
}
}
</code></pre>
<p>Now the trick is to inject the Decorators. I'm a big fan of Ninject so I will show you how to do it the Ninja style.</p>
<p>You need to define the injectors in the order that you want them, if you take a closer look to the previous code again, we have not specified <em>what concrete command handler</em> is going to be injected into the <code>CommandHandlerValidator</code> or the <code>CommandHandlerAuthenticator</code>. All we've defined is that a <code>ICommandHandler</code> will be injected somehow. </p>
<p>All this configuration will be done via our container. It's awesome</p>
<pre class="prettyprint cs"><code>//we bind everythig except our command handlers since we will treat them as decorators
kernel.Bind(config =>
{
config.From(fromTypes.Select(x => x.Assembly))
.SelectAllClasses()
.Where(x => !x.IsAssignableToGenericType(typeof(ICommandHandler<>)))
.BindAllInterfaces();
});
kernel.Bind(config =>
{
config.From(fromTypes.Select(x => x.Assembly)).SelectAllClasses()
.Where(x => x.IsAssignableToGenericType(typeof(ICommandHandler<>)))
.BindAllInterfaces().Configure(x => x.WhenInjectedInto(typeof(CommandHandlerValidator<>)));
});
kernel.Bind(typeof(ICommandHandler<>)).To(typeof(CommandHandlerValidator<>))
.WhenInjectedInto(typeof(CommandHandlerAuthenticator<>));
kernel.Bind(typeof(ICommandHandler<>)).To(typeof(CommandHandlerAuthenticator<>));
</code></pre>
<p>This code can be read as follows (from bottom to top):</p>
<ul>
<li>When I ask an <code>ICommandHandler</code> give me <code>CommandHandlerAuthenticator</code></li>
<li>Then when I'm injecting a <code>CommandHandlerAuthenticator</code> give me a <code>CommandHandlerValidator</code></li>
<li>And finally, when I'm injecting a <code>CommandHandlerValidator</code> give me my <code>ICommandHandler</code></li>
</ul>
<p>It's tricky I know... but it works great</p>
<p>This code could be improved maybe creating an Extension Method to bind decorators.</p>
<p>So when you test it like this:</p>
<pre class="prettyprint cs"><code>var guard = kernel.Get<ICommandHandler<GrantAccessToNightClub>>();
guard.Handle(new GrantAccessToNightClub("jp", 21));
</code></pre>
<p>This is the output:</p>
<pre class="prettyprint cs"><code>Test Name: TestMethod1
Test Outcome: Passed
Result StandardOutput:
Authenticating...
Valdiating: 21: Granted
Valdiation done, lets continue
Finally doing some work here...
</code></pre>
<p>Now the fun part, <strong>TEST IT</strong></p>
<p>I don't know how to call this kind of test, I don't believe it's a unit test, integration test perhaps uhmm well I just call them <strong><em>Wiring tests</em></strong></p>
<pre class="prettyprint cs"><code>[TestMethod]
public void it_should_resolve_the_CommandHandlerDecorators()
{
var kernel = new StandardKernel();
var fromTypes = new[]
{
typeof (DecoratorTests)
};
//we bind everythig except our command handlers since we will treat them as decorators
kernel.Bind(config =>
{
config.From(fromTypes.Select(x => x.Assembly))
.SelectAllClasses()
.Where(x => !x.IsAssignableToGenericType(typeof(ICommandHandler<>)))
.BindAllInterfaces();
});
kernel.Bind(config =>
{
config.From(fromTypes.Select(x => x.Assembly)).SelectAllClasses()
.Where(x => x.IsAssignableToGenericType(typeof(ICommandHandler<>)))
.BindAllInterfaces().Configure(x => x.WhenInjectedInto(typeof(CommandHandlerValidator<>)));
});
kernel.Bind(typeof(ICommandHandler<>)).To(typeof(CommandHandlerValidator<>))
.WhenInjectedInto(typeof(CommandHandlerAuthenticator<>));
kernel.Bind(typeof(ICommandHandler<>)).To(typeof(CommandHandlerAuthenticator<>));
var field = typeof(KernelBase).GetField("bindings",
BindingFlags.Instance | BindingFlags.NonPublic);
field.Should().NotBeNull();
var bindingsMap = field.GetValue(kernel) as Multimap<Type, IBinding>;
bindingsMap.Should().NotBeNull();
bindingsMap.Should().NotBeEmpty();
var commandHandlerBindings = bindingsMap.SelectMany(x => x.Value)
.Where(x => x.Service.IsAssignableToGenericType(typeof(ICommandHandler<>))).ToList();
commandHandlerBindings.Should().NotBeNullOrEmpty();
commandHandlerBindings.Where(x => !x.Service.IsGenericTypeDefinition).ToList().ForEach(x =>
{
var handlers = kernel.GetAll(x.Service);
foreach (var instance in handlers)
{
instance.GetType().IsAssignableToGenericType(typeof(CommandHandlerAuthenticator<>)).Should().BeTrue();
// testing that the CommandHandlerValdiator was injected into CommandHandlerAuthenticator
VerifyInnerCommandHandler(instance, x.Service, typeof (CommandHandlerValidator<>),
typeof (CommandHandlerAuthenticator<>));
var innerCommandHandler = instance.GetType().GetField("_commandHandler",
BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
// testing that the ICommandHandler was injected into CommandHandlerValdiator
VerifyInnerCommandHandler(innerCommandHandler, x.Service, typeof (ICommandHandler<>),
typeof (CommandHandlerAuthenticator<>), typeof (CommandHandlerValidator<>));
}
});
}
private void VerifyInnerCommandHandler(object instance, Type service, Type expectedType, params Type[] notExpectedTypes)
{
var innerHandlerField = instance.GetType().GetField("_commandHandler",
BindingFlags.Instance | BindingFlags.NonPublic);
innerHandlerField.Should().NotBeNull();
var innerHandler = innerHandlerField.GetValue(instance);
innerHandler.GetType().IsAssignableToGenericType(expectedType).Should().BeTrue();
foreach (var notExpectedType in notExpectedTypes)
{
innerHandler.GetType().IsAssignableToGenericType(notExpectedType).Should().BeFalse();
}
Console.WriteLine("{0} should be: {1}", innerHandler.GetType(), service);
service.IsInstanceOfType(innerHandler).Should().BeTrue();
service.IsAssignableFrom(innerHandler.GetType()).Should().BeTrue();
innerHandler.GetType().IsAssignableToGenericType(expectedType).Should().BeTrue();
}
</code></pre>
<p>Ohh almost forgot, I'm using the following <code>Type</code> extension: <a href="http://tmont.com/blargh/2011/3/determining-if-an-open-generic-type-isassignablefrom-a-type"><code>IsAssignableToGenericType</code></a></p>
<p>There you go</p>
<p>Hope you have enjoyed it</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com0Concord, CA, USA37.9779776 -122.031073337.877841100000005 -122.1924348 38.0781141 -121.8697118tag:blogger.com,1999:blog-3219791544874033206.post-80135913876030848262014-06-23T13:40:00.001-07:002014-06-23T13:46:11.674-07:00Building/Publishing ClickOnce projects in a TFS build server without installing Visual Studio<p>If you have tried to build or publish a ClickOnce project in a build server, you might find that you receive the following error:</p><blockquote><p>Could not find required file 'setup.bin'</p></blockquote><p>This basically means that MSBuild can't locate a bootstrap file needed to be able to build/publish ClickOnce applications</p><p>I have tried to fix it by installing the following Windows SDK on the TFS build servers:</p><ul><li><a href="http://msdn.microsoft.com/en-US/windows/desktop/aa904949.aspx">Windows SDK for Windows 8.1</a></li>
<li><a href="http://msdn.microsoft.com/en-us/windows/hh852363.aspx">Windows Software Development Kit (SDK) for Windows 8</a></li>
</ul><p>Unfortunately, this was not enough to fix it.</p><p>After a lot of research, I found that the missing <strong>setup.bin</strong> file is actually installed locally in my developer environment where I have installed Visual Studio</p><p>So the fix looks like <em>hacky</em> but it works perfectly</p><p>Procedure to fix it:</p><ol><li>In the TFS build server, <a href="http://msdn.microsoft.com/en-US/windows/desktop/hh852363.aspx">install this Windows SKD</a></li>
<li>From your local environment (with Visual Studio installed), copy the following two folders<br />
<ul><li>C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Bootstrapper\Engine</li>
<li>C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Bootstrapper\Schemas</li>
</ul></li>
<li>Paste those two folders in your TFS build server:<br />
<ul><li>C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Bootstrapper</li>
</ul></li>
<li><p>Update the Windows Registry in the TFS build server by running the following command (save the text in a file with the extension <strong>.reg</strong> and double click it):</p><pre class="prettyprint cs"><code>Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\GenericBootstrapper\11.0]
"Path"="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.0A\\Bootstrapper\\"
</code></pre><br />
</li>
</ol><p>That's it, the next time you try to build and publish your ClickOnce application in the TFS build server will run smoothly</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com0Dublin, OH 43016, USA40.0761455 -83.1541796000000239.978982 -83.315541100000019 40.173309 -82.992818100000022tag:blogger.com,1999:blog-3219791544874033206.post-52239498362226990892012-11-11T04:00:00.003-08:002012-11-13T10:30:11.932-08:00CQRS Query Engine - Writing a Testable, maintainable and extensible CQRS Query Engine - Part 3<ol><li><a href="http://jupaol.blogspot.mx/2012/11/cqrs-query-engine-writing-testable.html">Designing the Query Engine</a></li>
<li><a href="http://jupaol.blogspot.com/2012/11/cqrs-query-engine-writing-testable2.html">Encapsulating common behavior (template pattern)</a></li>
<li><a href="http://jupaol.blogspot.com/2012/11/cqrs-query-engine-writing-testable3.html">Implementing Queries</a></li>
<li>Creating the Query Resolver</li>
</ol><br />
<p>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.</p><br />
<p>So let’s start creating queries.</p><br />
<h2>Querying By ID</h2><br />
<p>The first Query I want to create is this one, just a simple query by ID</p><br />
<p>A table/view can have a primary key composed of just one field or by several fields, with this approach you can express the <em>intent of the query explicitly</em> 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</p><br />
<p>So let’s see the code:</p><br />
<p>We need an object implementing the <code>IQueryID</code> mark interface to specify it as the <em>ID</em> we want to search for.</p><br />
<pre class="prettyprint cs"><code>public sealed class MovieID : IQueryID
{
public MovieID(Guid id)
{
this.ID = id;
}
public Guid ID { get; private set; }
}
</code></pre><br />
<p>That’s it, we are explicitly specifying the ID used by our Movie entity. </p><br />
<p>What we’re actually doing is: we are taking an implicit hidden domain concept (the Movie Identifier) and we are making it explicit</p><br />
<p>The next step is to create the query:</p><br />
<pre class="prettyprint cs"><code>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));
}
}
</code></pre><br />
<p>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 <strong>won’t interfere in any way with any other queries created</strong>, 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.</p><br />
<p>But we are missing something, first let me remember you the definition of the <code>QueryByIDHandler</code> class:</p><br />
<pre class="prettyprint cs"><code>public abstract class QueryByIDHandler<TQueryID, TQueryResult> : IQueryByIDHandler<TQueryID, TQueryResult>
where TQueryID : IQueryID
</code></pre><br />
<p>The class implements <code>IQueryByIDHandler<TQueryID, TQueryResult></code>, 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:</p><br />
<p><strong>Note: I know that you would never use a <em>handler</em> 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</strong></p><br />
<pre class="prettyprint cs"><code>public partial class MoviesController : Controller
{
private IQueryByIDHandler<MovieID, Movie> queryByIdHandler;
public MoviesController(IQueryByIDHandler<MovieID, Movie> queryByIdHandler)
{
this.queryByIdHandler = queryByIdHandler;
}
}
</code></pre><br />
<p>Please pay special attention to:</p><br />
<pre class="prettyprint cs"><code>IQueryByIDHandler<MovieID, Movie> queryByIdHandler
</code></pre><br />
<p>This doesn’t look right to me. The nature of the <code>IQueryByIDHandler</code> is to be <em>generic</em> so that we can use it to create custom queries, but using it like this we are hiding <strong>the intention of the query</strong>. </p><br />
<p>So what’s the intention? Well in this case the intention is to simply provide a way to query the <em>Movies</em> collection to find a specific <em>Movie by ID</em></p><br />
<p>To me the correct naming would be something like:</p><br />
<pre class="prettyprint cs"><code>IFindMovieByIDQueryHandler
</code></pre><br />
<p>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:</p><br />
<pre class="prettyprint cs"><code>IFindMovieByIDQueryHandler
</code></pre><br />
<p>vs</p><br />
<pre class="prettyprint cs"><code>IQueryByIDHandler<MovieID, Movie>
</code></pre><br />
<p>In order to create this interface we need code like this:</p><br />
<pre class="prettyprint cs"><code>public interface IFindMovieByIDQueryHandler : IQueryByIDHandler<MovieID, Movie>
{
}
</code></pre><br />
<p>And then use it to mark our query:</p><br />
<pre class="prettyprint cs"><code>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));
}
}
</code></pre><br />
<p>And finally the updated controller would look like (<strong>Again just for demonstration purpose</strong>):</p><br />
<pre class="prettyprint cs"><code>public partial class MoviesController : Controller
{
private IFindMovieByIDQueryHandler findMovieByIDHandler;
public MoviesController(IFindMovieByIDQueryHandler findMovieByIDHandler)
{
this.findMovieByIDHandler = findMovieByIDHandler;
}
}
</code></pre><br />
<p>If you want to learn more about <a href="http://www.infoq.com/presentations/Making-Roles-Explicit-Udi-Dahan">Making Roles Explicit, please see this Uddi Dahan video</a></p><br />
<h2>Querying all items in the collection</h2><br />
<p>In order to query all items (the typical <code>FindAll</code> method) we will create the interface to expose the query concept</p><br />
<pre class="prettyprint cs"><code>public interface IFindAllMoviesQueryHandler : IQueryHandler<Movie>
{
}
</code></pre><br />
<p>Then the implementation of the query</p><br />
<pre class="prettyprint cs"><code>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(); }
}
}
</code></pre><br />
<p>The code is actually straightforward, so it doesn’t require explanation</p><br />
<h2>Applying specific queries</h2><br />
<p>This is the most interesting part of the Query Engine, and also the most used in RL applications.</p><br />
<p>Here we will define all the specific queries needed in the application <strong>but only when they are required</strong>, and like I explained before, adding new queries <strong>won’t affect in any way to any existing query</strong></p><br />
<p>So let’s start by making the query concept explicit, in order to do it, we need an object implementing the <code>IQuery</code> interface, something like this:</p><br />
<pre class="prettyprint cs"><code>public sealed class FindMoviesByTitleQuery : IQuery
{
public FindMoviesByTitleQuery(string title)
{
this.Title = title;
}
public string Title { get; private set; }
}
</code></pre><br />
<p>In this <em>query class</em> you will define all fields needed in order to apply the query, in this case I just need to query by <em>title</em></p><br />
<p>Then, let’s create the <em>mark of the query handler</em> related to this query:</p><br />
<pre class="prettyprint cs"><code>public interface IFindMoviesByTitleQueryHandler : IQueryHandler<FindMoviesByTitleQuery, Movie>
{
}
</code></pre><br />
<p>And finally the implementation:</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre><br />
<p>Again, the code is straightforward and self explanatory therefore it doesn’t require any explanation</p><br />
<p>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</p><br />
<p>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 <em>play with them</em></p><br />
<p>In the next post I will show you a way to completely decouple the handlers from your code.</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com1Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-42408610320290958672012-11-11T01:14:00.000-08:002012-11-13T08:01:59.327-08:00CQRS Query Engine - Writing a Testable, maintainable and extensible CQRS Query Engine - Part 2<ol><li><a href="http://jupaol.blogspot.mx/2012/11/cqrs-query-engine-writing-testable.html">Designing the Query Engine</a></li>
<li><a href="http://jupaol.blogspot.com/2012/11/cqrs-query-engine-writing-testable2.html">Encapsulating common behavior (template pattern)</a></li>
<li><a href="http://jupaol.blogspot.com/2012/11/cqrs-query-engine-writing-testable3.html">Implementing Queries</a></li>
<li>Creating the Query Resolver</li>
</ol><br />
<p>In the previous post I created the design of the Query Engine, in this post I will create the initial implementation</p><br />
<p>I created several abstract classes to encapsulate common behavior:</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre><br />
<p>The <code>QueryPageAndSortingBase<TQueryResult></code> class is used to encapsulate paging and sorting behavior</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre><br />
<p>The <code>QueryHandlerBase<TQueryResult></code> controls the flow to call the <code>QueryPageAndSortingBase<TQueryResult>.ApplyPagingAndSorting</code> method. This method is in charge to apply the paging and sorting. </p><br />
<pre class="prettyprint cs"><code>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);
}
</code></pre><br />
<p>The <code>QueryHandler<TQuery, TQueryResult></code> controls the flow to <strong>apply a custom and explicit query</strong>, and apply paging and sorting when required.</p><br />
<pre class="prettyprint cs"><code>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());
}
}
</code></pre><br />
<p>The <code>QueryHandler<TQueryResult></code> class is used to control the flow to query all the elements applying paging and sorting when required</p><br />
<h1>Unit testing</h1><br />
<p>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:</p><br />
<h2>QueryPageAndSortingBase Tests</h2><br />
<h3>Manual Mock</h3><br />
<pre class="prettyprint cs"><code>public class QueryPageAndSortingBaseMock : QueryPageAndSortingBase<Movie>
{
protected override IQueryable<Movie> ApplyDefaultOrder(IQueryable<Movie> items)
{
return items.OrderByDescending(x => x.Title);
}
}
</code></pre><br />
<h3>Tests</h3><br />
<pre class="prettyprint cs"><code>[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);
}
}
}
</code></pre><br />
<h2>QueryHandlerBase Tests</h2><br />
<h3>Manual Mocks</h3><br />
<pre class="prettyprint cs"><code>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();
}
}
</code></pre><br />
<h3>Tests</h3><br />
<pre class="prettyprint cs"><code>[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);
}
}
}
</code></pre><br />
<p>Uff that was too much code for a post, the rest of the tests will be available when I post the full code =)</p><br />
<p>In the next post, I will show you how to use these objects and how easy is to create query objects</p><br />
<p>This is the graphical representation of these classes:</p><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqNNMopXV_YOD0Dse5sfjOnVnP_-Z68j8gfLFXHFLXvtetifAOZ5RM7M10_kTv1qZwOXMyNMO_FnOEd9GHArTEBVH9IEUKLoNbmMPGeieZ-LI8LLTPY5MkzgAV0dvF8CiuGXXifzfb_ls/s1600/queryengine+2+-++01.PNG" imageanchor="1" style=""><img border="0" height="278" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqNNMopXV_YOD0Dse5sfjOnVnP_-Z68j8gfLFXHFLXvtetifAOZ5RM7M10_kTv1qZwOXMyNMO_FnOEd9GHArTEBVH9IEUKLoNbmMPGeieZ-LI8LLTPY5MkzgAV0dvF8CiuGXXifzfb_ls/s320/queryengine+2+-++01.PNG" /></a><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzpc7F8yMSHV9d8WAGDUJwbe1koZZpBMcxThBWWwJsl5bnAuq4l2T6iKE96el650nu2W9II8EgWZU1CSLaFeIipX7WbvHSm3ym6qPGwR8_lqUNdTNoYcqtEU1tYavDr9psS7_kGvnytXM/s1600/queryengine+2+-++02.PNG" imageanchor="1" style=""><img border="0" height="255" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzpc7F8yMSHV9d8WAGDUJwbe1koZZpBMcxThBWWwJsl5bnAuq4l2T6iKE96el650nu2W9II8EgWZU1CSLaFeIipX7WbvHSm3ym6qPGwR8_lqUNdTNoYcqtEU1tYavDr9psS7_kGvnytXM/s320/queryengine+2+-++02.PNG" /></a>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com0Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-33468960687700091262012-11-10T20:46:00.001-08:002012-11-11T04:03:15.453-08:00CQRS Query Engine - Writing a Testable, maintainable and extensible CQRS Query Engine<ol><li><a href="http://jupaol.blogspot.mx/2012/11/cqrs-query-engine-writing-testable.html">Designing the Query Engine</a></li>
<li><a href="http://jupaol.blogspot.com/2012/11/cqrs-query-engine-writing-testable2.html">Encapsulating common behavior (template pattern)</a></li>
<li><a href="http://jupaol.blogspot.com/2012/11/cqrs-query-engine-writing-testable3.html">Implementing Queries</a></li>
<li>Creating the Query Resolver</li>
</ol><br />
<p>In my <a href="http://jupaol.blogspot.mx/2012/10/unit-testing-your-repository-query-logic.html">last post I blogged about writing a Query Repository in a test-friendly way</a> but even when the code was testable I still believe it can be improved in several ways.</p><br />
<p>I’m going to build a small, simple and test-friendly <strong>Query Engine</strong>. This will be the first post in this series.</p><br />
<p>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 <em>Commands branch</em> in a CQRS architecture</p><br />
<h3>The traditional query repository</h3><br />
<p>Before start, let’s see how a typical query repository looks like (assuming a fictitious Movies query repository):</p><br />
<pre class="prettyprint cs"><code>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);
}
</code></pre><br />
<p>There are several problems with an interface like this, I will talk about them in a minute.</p><br />
<h3>The problem</h3><br />
<p>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 <em>Category</em> so you just go and add the following method to your interface:</p><br />
<pre class="prettyprint cs"><code>IQueryable<Movie> FindByCategory(string category);
</code></pre><br />
<p>You have to go and edit all your implementations of your <code>IMoviesQueryRepository</code> (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.</p><br />
<p>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:</p><br />
<pre class="prettyprint cs"><code>IQueryable<Movie> FindByCategories(string[] categories);
IQueryable<Movie> FindByAverageCost(decimal averageCost);
</code></pre><br />
<p>And you repeat all the implementation process again. </p><br />
<p>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.</p><br />
<p>So a design like this is not flexible, is not testable and is hard to maintain</p><br />
<p>Let’s see several problems with this design:</p><br />
<ul><li><p>It violates the <a href="http://en.wikipedia.org/wiki/Open/closed_principle">open-closed pricniple (open for extension/closed to modification)</a>. </p><br />
<p>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?)</p></li>
<li><p>A design like this can lead to violate the <a href="http://en.wikipedia.org/wiki/You_ain't_gonna_need_it">YAGNI principle (You Ain’t Gonna Need It)</a></p><br />
<p>Why? Simply because in order to avoid the problem described before, you could try to think <em>about all the possible filters that you might need in the application</em>. This will lead you to write tons of query filters that you won’t ever need</p></li>
<li><p><a href="http://jupaol.blogspot.mx/2012/10/unit-testing-your-repository-query-logic.html">This design is not test friendly</a> I just wrote the result of these queries as <code>IQueryable</code> objects on purpose to ilustrate the point that this design is not test friendly, and actually you won’t be able to <strong>test in isolation your queries</strong> <a href="http://blog.ploeh.dk/2012/03/26/IQueryableIsTightCoupling.aspx">if you expose in your public API <code>IQueryable</code> objects</a>. The reason is that your query logic will actually be spread out in several places in your application.</p></li>
</ul><br />
<p>Let’s see some approaches that <em>won’t work</em></p><br />
<h3>Anti Unit Testing approach</h3><br />
<p>The simplest approach is to forget about unit testing (oO) and consume the <code>IQueryable</code> object directly in all the places where you will need it (usually the user interface)</p><br />
<p>I don’t have to tell you that <strong>I would never recommend something like this</strong>. But surprisingly in <a href="http://stackoverflow.com/">Stackoverflow</a> I've seen a lot of code like this, and a lot of examples over the internet about MVC using this approach.</p><br />
<h3>Naive approach</h3><br />
<p>Well let’s say that you realize that unit test is <strong>so important in any application</strong> that you decide to go back to the original design and try to figure out how to fix it.</p><br />
<p>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 <code>IQueryable</code> object in your query repository they should never add new queries on it.... in order to <em>“guarantee”</em> that the query is encapsulated and therefore testable in isolation.....</p><br />
<p>….Good luck with that!</p><br />
<p>So now hopefully you will want to see the solution already... and here it is</p><br />
<p>This is my solution to the problem</p><br />
<h3>Encapsulating the query</h3><br />
<p>The first thing to do to refactor the original design is to encapsulate the query in order to <strong>guarantee that the query will actually be unit-tested in isolation</strong>. <a href="http://jupaol.blogspot.mx/2012/10/unit-testing-your-repository-query-logic.html">I’m going to follow the same approach I used in my last post</a>, I will create a new DTO object to wrap my query results.</p><br />
<p>This object would look something like:</p><br />
<pre class="prettyprint cs"><code>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; }
}
</code></pre><br />
<p>Since the query will be encapsulated you also need an object to pass paging and sorting parameters:</p><br />
<pre class="prettyprint cs"><code>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
}
</code></pre><br />
<p>So your query repository would look like:</p><br />
<pre class="prettyprint cs"><code>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);
}
</code></pre><br />
<p>Following this approach you will be able to unit test in isolation your queries, but you would still have the original problem. </p><br />
<h1>Designing the Query Engine</h1><br />
<p>OK, so now let’s design the query engine.</p><br />
<p>First of all I have a couple of interfaces that I’m using to mark my objects:</p><br />
<pre class="prettyprint cs"><code>public interface IQuery
{
}
public interface IQueryID
{
}
</code></pre><br />
<ul><li><p>The <code>IQuery</code> interface is the equivalent to the <code>ICommand</code> interface in the Commands branch in a CQRS architecture. This is used to mark value objects as query objects</p></li>
<li><p>The <code>IQueryID</code> 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.</p></li>
</ul><br />
<p>I created three interfaces in order to represent the queries in an application <b>This is the core of the Query Engine</b>:</p><br />
<pre class="prettyprint cs"><code>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);
}
</code></pre><br />
<ul><li><p>The <code>IQueryHandler</code> overload using the <code>IQuery</code> interface will be used to define explicitly the queries in your application</p></li>
<li><p>The <code>IQueryHandler</code> overload without the <code>IQuery</code> interface will be used to query all the records from the table</p></li>
<li><p>The <code>IQueryByIDHandler</code> will be used to query an entity/table/view by ID</p></li>
</ul><br />
<p>This is a graphical representation:</p><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiJkVuryxWrq_xtbYj-8qbuFS6YWDR_9rEjpPYvSq37PUISvBx7nAD85iQmiDrLyI8HE7TedGm3Zx23h0o-97pDmnwH3lbH_SILQiTLtfr-1g7iQqJ7rfMHJWt-LzKW6gw-3kYrwsf_GM/s1600/queryengine+01.PNG" imageanchor="1" style=""><img border="0" height="116" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiJkVuryxWrq_xtbYj-8qbuFS6YWDR_9rEjpPYvSq37PUISvBx7nAD85iQmiDrLyI8HE7TedGm3Zx23h0o-97pDmnwH3lbH_SILQiTLtfr-1g7iQqJ7rfMHJWt-LzKW6gw-3kYrwsf_GM/s320/queryengine+01.PNG" /></a><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1tAtB6lwjSr41rbXuZhAq4DRodmkSaRqqK7c0JpYFGLO4-Ax1kAfvKf9jSKVxTnpzPgw7b3RXcv00fgQXVhdcdlmzISolbmz_GanaPaL34qMNLaISwsnySjsK_kxRRre6rNv_Bbq6tGs/s1600/queryengine+02.PNG" imageanchor="1" style=""><img border="0" height="62" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1tAtB6lwjSr41rbXuZhAq4DRodmkSaRqqK7c0JpYFGLO4-Ax1kAfvKf9jSKVxTnpzPgw7b3RXcv00fgQXVhdcdlmzISolbmz_GanaPaL34qMNLaISwsnySjsK_kxRRre6rNv_Bbq6tGs/s320/queryengine+02.PNG" /></a><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi3DGcxfShApHt7hZZpYm8sZgMV02E_s2_Z1Y5cLCeKCZcRkw5k3h5tLJr9zvJdo58I9XtbhDvMJC9Xr_4TZi8b5o0fUwzKe4QmqHMCl4leJjGJDcCp2id6uxZK0NY0mBf2Y3DmjdoCls/s1600/queryengine+03.PNG" imageanchor="1" style=""><img border="0" height="152" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi3DGcxfShApHt7hZZpYm8sZgMV02E_s2_Z1Y5cLCeKCZcRkw5k3h5tLJr9zvJdo58I9XtbhDvMJC9Xr_4TZi8b5o0fUwzKe4QmqHMCl4leJjGJDcCp2id6uxZK0NY0mBf2Y3DmjdoCls/s320/queryengine+03.PNG" /></a><br />
<br />
<br />
<br />
<p>Stay in touch, in the next post I will create base classes to encapsulate common behavior</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com1Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-54993257600979738002012-10-29T05:01:00.001-07:002012-11-13T19:00:18.639-08:00Unit Testing your Repository Query Logic<ul><li><p>Have you ever tried to unit test your Query Logic using repositories??</p></li>
<li><p>If you do, have you ended writing integration tests instead of unit tests??</p></li>
</ul><br />
<p>Even if you have not tried, you might find this post useful.</p><br />
<p>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 <code>IQueryable</code> object.</p><br />
<p>In order to do it, we need to write the code in a test-friendly way.</p><br />
<p>Let´s begin with some concepts and principles related to this problem.</p><br />
<ul><li><p><a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">SRP. Single Responsibility Principle</a>. 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 <a href="http://en.wikipedia.org/wiki/Responsibility-driven_design#Controller">Responsibility Driven Design</a> as a <a href="http://msdn.microsoft.com/en-us/magazine/cc721605.aspx">Role Stereotype</a></p></li>
<li><p><a href="http://en.wikipedia.org/wiki/Dependency_injection">DI. Dependency Injection</a></p><br />
<blockquote><p>Dependency injection is a software design pattern that allows a choice of component to be made at run-time rather than compile time</p></blockquote><br />
<p>Dependency Injection as specified before is a Design Pattern and DI by itself <strong>does not require the use of a IoC container</strong> although, it is used with one most of the time but this is not required.</p></li>
<li><p><a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a></p><br />
<blockquote><p>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</p><br />
<ul><li>Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.</li>
<li>Each unit should only talk to its friends; don't talk to strangers.</li>
<li>Only talk to your immediate friends.</li>
</ul></blockquote></li>
</ul><br />
<blockquote><p><a href="http://www.youtube.com/watch?v=RlfLCWKxHJ0">For more info watch this Misko Hevery video</a></p></blockquote><br />
<p>So let’s see how a typical Query repository looks like:</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre><br />
<p>Looks familiar? If you write a repository like this, you won't be able to test your <em>query logic</em> in isolation.</p><br />
<p>There are basically four problems with this implementation that prevent our code to be unit tested:</p><br />
<ul><li><p>We are using the evil anti-test keyword <strong>new</strong> inside our repository to create the EF context</p></li>
<li><p>Using the EF context directly, to retrieve the <code>IQueryable<Movie></code> collection to perform the query on it instead of just <em>recieve the collection itself</em></p></li>
<li><p>Even when the <code>GetMovies</code> method looks extremely simple, it is violating the SRP. This method is doing too much work.</p><br />
<ul><li><p>It is creating the EF context</p></li>
<li><p>It is getting the <code>Movies</code> collection</p></li>
<li><p>It implements the query logic</p></li>
</ul></li>
<li><p>The <code>GetMovies</code> 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 <strong>movies collection instead</strong></p></li>
</ul><br />
<p>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.</p><br />
<h2>Refactoring the ugly code</h2><br />
<p>Now let’s refactor this simple code to make it test-friendly.</p><br />
<h3>Removing the <code>new</code> operator</h3><br />
<p>In order to remove the <code>new</code> operator we need to use DI.</p><br />
<p>First we need to write a custom factory in charge to create the EF context for us. (<a href="http://jupaol.blogspot.mx/2012/10/entityframework-context-per-request.html">I wrote a blog about a thread-safe implementation</a>)</p><br />
<p>This is a simplified version</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre><br />
<p>This class is simply acting as a generic factory to instantiate EF Contexts using the <em>Context Per Request pattern</em></p><br />
<h3>Isolate the EF Context from our repository</h3><br />
<p>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</p><br />
<p>So let’s start by identifying what needs to be separated.</p><br />
<p>The problem in the last code sample is that the repository communicates directly with the EF context to retrieve the <code>IQueryable</code> collection of objects in order to create the query.</p><br />
<p><strong>What we really need is the collection of objects to work on</strong></p><br />
<p>Since the <code>IQueryable</code> interface is capable of execute deferred queries, it’s perfect to expose the initial collection of objects to perform the query.</p><br />
<p>So let’s add the following objects</p><br />
<pre class="prettyprint cs"><code>public interface IMoviesDataProvider
{
IQueryable<Movie> GetMoviess();
}
</code></pre><br />
<p>This simple interface will be in charge to provide the initial objects as an <code>IQueryable</code> collection to perform the query</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre><br />
<p>Notice how the implementation has become really simple. This implementation <strong>will be in charge to communicate directly to the backend system to expose the data as an <code>IQueryable</code> collection</strong>. Since this object will talk directly with the database using EF, we use DI to pass a reference to the <code>IContextResolver</code> object (remember, this object will be in charge to get the correct instance of the EF context using the <em>Context per Request Pattern</em>)</p><br />
<h3>Implement the Query Logic</h3><br />
<p>The next step is to implement your query logic in your repository object.</p><br />
<p>This is quite simple since now we have identified and isolated single responsibilities in several objects.</p><br />
<p>So let’s refactor our repository code:</p><br />
<pre class="prettyprint cs"><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<movie> FilterMoviesByTitle(string title, PagingInfo pagingInfo = null);
}
</code></pre><br />
<p>There are several things to note on this simple code:</p><br />
<ul><li><p>The repository no longer depends on the EF Context, now it depends on the <code>IMoviesDataProvider</code> interface which can now be easily mocked to return a dummy in-memory collection to work on when unit testing.</p></li>
<li><p>The Query Logic is being encapsulated in this layer</p></li>
<li><p>The result of the query is an in-memory object <code>IList</code> (which is wrapped in the <code>QueryResults</code> object) which means that at this point the query is being executed on the server.</p></li>
<li><p>Since the query has been executed at this point, we can safely return in-memory objects represented by the <code>IList</code> collection</p></li>
</ul><br />
<p>Some people would argue about the use of the <code>IList</code> instead of returning an <code>IQueryable</code>.</p><br />
<p>With an <code>IQueryable</code> 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.</p><br />
<p><a href="http://blog.ploeh.dk/2012/03/26/IQueryableIsTightCoupling.aspx">For more info about <code>IQueryable</code></a><br />
</p><br />
<p>Here is the code of the <code>QueryResults</code> and <code>PagingInfo</code> objects:</p><br />
<pre class="prettyprint cs"><code>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; }
}
</code></pre><br />
<p>These objects are simple DTO’s</p><br />
<h3>Writing the Unit Tests</h3><br />
<p>Finally we can have fun writing our unit tests:</p><br />
<pre class="prettyprint cs"><code>[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);
}
}
}
</code></pre><br />
<p>Have fun!</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com0Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-59771853788763498792012-10-25T00:54:00.001-07:002012-11-07T11:56:46.162-08:00EntityFramework context per request-lifetime thread-safe with Unit Tests<p>When using <strong>EntityFramework</strong>, you need a consistent way to manage the context object lifecycle. The most accepted way to do this is creating a <em>context per HTTP Request</em></p><br />
<p>I´m going to show you a basic thread-safe implementation.</p><br />
<h2>Building the component</h2><br />
<h3>Context Resolver Contract</h3><br />
<pre class="prettyprint cs"><code>public interface IContextResolver
{
TContext GetCurrentContext<TContext>() where TContext : DbContext;
void ReleaseContext();
}
</code></pre><br />
<p>This interface is really simple, it just defines two methods. </p><br />
<ul><li><p>The <code>GetCurrentContext</code> method will be used to get or create the EntityFramework context object.</p></li>
<li><p>The <code>ReleaseContext</code> method will be in charge to call <code>Dispose</code> in your context in order to release resources.</p></li>
</ul><br />
<h3>Context Resolver implementation</h3><br />
<pre class="prettyprint cs"><code>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();
}
}
}
</code></pre><br />
<p>The implementation is straightforward, the only tricky part is the addition of <code>lock</code> statements when <strong>reading and writing</strong> the EntityFramework context.</p><br />
<blockquote><p>The C# specification clearly defines what operations are "atomic" in section 5.5. The atomic operations are <strong>reads and writes</strong> of variables of any reference type, or, effectively, any built-in value type that takes up four bytes or less</p></blockquote><br />
<p><a href="http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-one.aspx">Source</a></p><br />
<p>In order to implement the <em>context per HTTP request</em> pattern, we use <a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.items.aspx">HttpContext.Items</a>. The objects we store in this dictionary, will be accessible only during the current HTTP request.</p><br />
<blockquote><p>Gets a key/value collection that can be used to organize and share data between an IHttpModule interface and an IHttpHandler interface <strong>during an HTTP request.</strong></p></blockquote><br />
<h2>Usage</h2><br />
<p>You just have to configure your DI container (if any) to inject the correct instance of <code>IContextResolver</code>.</p><br />
<h3>Injecting</h3><br />
<p>For simplicity I will inject it in my MVC controller</p><br />
<pre class="prettyprint cs"><code>private IContextResolver contextResolver;
public HomeController(IContextResolver contextResolver)
{
this.contextResolver = contextResolver;
}
public ActionResult SimpleData()
{
var ctx = this.contextResolver.GetCurrentContext<pubsEntities>();
return View(ctx.jobs);
}
</code></pre><br />
<h3>In Global.asax</h3><br />
<p>During the whole request, all the calls to <code>IContextResolver.GetCurrentContext</code> 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 <code>PostRequestHandlerExecute</code> application event in the Global.asax file.</p><br />
<pre class="prettyprint cs"><code>public MvcApplication()
{
this.PostRequestHandlerExecute += MvcApplication_PostRequestHandlerExecute;
}
void MvcApplication_PostRequestHandlerExecute(object sender, EventArgs e)
{
var resolver = ServiceLocator.Current.GetInstance<IContextResolver>();
resolver.ReleaseContext();
}
</code></pre><br />
<p>Notice the use of the <code>ServiceLocator</code>... your first impression might be: “hey dude, that’s an anti-pattern”...</p><br />
<p>Most of the time it is an anti-pattern, but in this case, <strong>we are using it inside the <a href="http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx">Composition Root Object of the Web Application</a></strong>, 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.</p><br />
<h2>Unit Testing</h2><br />
<p>It’s time to show you the unit tests I created for this small but useful component</p><br />
<h3>Builder</h3><br />
<p>I tend to use builders to create my SUT objects, it seems like a consistent way to create testing objects</p><br />
<pre class="prettyprint cs"><code>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();
}
}
</code></pre><br />
<p>I´m implementing <a href="http://msdn.microsoft.com/en-us/library/ff650316.aspx">a singleton pattern</a> just because I want to mock an <code>HttpContextBase</code> object to simulate a real HTTP request</p><br />
<p>I´m also configuring the <code>HttpContextBase.Items</code> properties with Moq to return a <code>Dictionary</code> object</p><br />
<p>Note that since my intention is to simulate concurrent threads, I'm marking my <code>HttpContextBase</code> and <code>Dictionary</code> members as <code>volatile</code></p><br />
<h3>The Tests</h3><br />
<pre class="prettyprint cs"><code>[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();
}
}
}
}
</code></pre><br />
<ul><li><p>The first test is really simple, it just ensures that we can create a context</p></li>
<li><p>The second test is more interesting, this is where I’m actually testing the concurrency of my implementation.</p><br />
<ul><li><p>I keep track of the first context created to compare all subsequent contexts with this one.</p><br />
<pre class="prettyprint cs"><code>var firstResolvedContext = sut.GetCurrentContext<PubsContext>();
</code></pre></li>
<li><p>I set the number of concurrent operations</p><br />
<pre class="prettyprint cs"><code>var numberOfConcurrentProcess = 10000;
</code></pre></li>
<li><p>Now I create a list to store all the created contexts. Note that I’m using the <code>BlockingCollection</code> object which is thread-safe</p><br />
<pre class="prettyprint cs"><code>var contextResolverInstances = new BlockingCollection<DbContext>();
</code></pre></li>
<li><p>I’m storing all the parallel tasks in an array</p><br />
<pre class="prettyprint cs"><code>var tasks = new Task[numberOfConcurrentProcess];
</code></pre></li>
<li><p>I create and start all the tasks. On each task, I’m creating a <strong>new instance of my SUT (my concrete implementation of: <code>IContextResolver</code>)</strong> and adding to <code>contextResolverInstances</code> the result of <code>IContextResolver.GetCurrentContext</code>. Also note that I'm using: <code>TaskCreationOptions.LongRunning</code> to force the TPL to run my tasks in background threads</p><br />
<pre class="prettyprint cs"><code>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);
}
</code></pre></li>
<li><p>I wait for all the tasks to complete by calling:</p><br />
<pre class="prettyprint cs"><code>Task.WaitAll(tasks);
</code></pre></li>
<li><p>The rest of the code are assertions, to confirm that just one instance was created among all threads</p></li>
</ul></li>
</ul><br />
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMrwpuxLKZV7zqMn-a6MH-KCoMZgqpuJh2T4H9tpgljAKrDWIJT4ajubxvdDxqfY6O0lU0cRFdsP0OREQfMN62YHnjWvTwl_3WKVYa_AAtNNMSsif0lcfwHk1-peOETi4H-KkHT0RFRsA/s1600/ef+context+test+results.PNG" imageanchor="1" style=""><img border="0" height="320" width="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMrwpuxLKZV7zqMn-a6MH-KCoMZgqpuJh2T4H9tpgljAKrDWIJT4ajubxvdDxqfY6O0lU0cRFdsP0OREQfMN62YHnjWvTwl_3WKVYa_AAtNNMSsif0lcfwHk1-peOETi4H-KkHT0RFRsA/s320/ef+context+test+results.PNG" /></a><br />
</p><br />
<p>In the next screenshot you can see how the tasks are being executed on different threads<br />
</p><br />
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitkaaiuhCMh30WqZhkVaBtxBDm32VDwOD6AcDDJK9A_B5GyxTUU2q6qNxsF58QsIbmX_VSpyf3bE9KyLKVTXg58n7q0_G5t4sUxl024tGetgJYPDrvApDMagklHs2JMTqhWg7Flnk0LDw/s1600/different+threads+used.PNG" imageanchor="1" style=""><img border="0" height="152" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitkaaiuhCMh30WqZhkVaBtxBDm32VDwOD6AcDDJK9A_B5GyxTUU2q6qNxsF58QsIbmX_VSpyf3bE9KyLKVTXg58n7q0_G5t4sUxl024tGetgJYPDrvApDMagklHs2JMTqhWg7Flnk0LDw/s320/different+threads+used.PNG" /></a><br />
<br />
<br />
</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com3Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-57277935790411697212012-10-04T21:37:00.000-07:002012-10-04T22:08:01.008-07:00WCF REST Data service in Visual Studio 2012 Express for Web<p>If you are using Visual Studio Express for Web, you might notice that the <em>WCF Data Service</em> template is not available to use.</p><br />
<p>I’m going to explain a step-by-step guide to create a WCF Data Service.</p><br />
<ul><li><p>Create an empty Web project with the name <em>WcfDataServiceInExpressEditions</em>: </p></li>
<li><p>Add the following nuget packages:</p><br />
<ul><li><p><a href="https://nuget.org/packages/Microsoft.Data.OData/5.0.2">Microsoft.Data.OData</a></p></li>
<li><p><a href="https://nuget.org/packages/Microsoft.Data.Services/5.0.2">Microsoft.Data.Services</a></p></li>
<li><p><a href="https://nuget.org/packages/EntityFramework">EntityFramework</a></p></li>
</ul></li>
<li><p>Add the following settings to the web.config right under <code><configuration></code></p><br />
<pre class="prettyprint xml"><code><system.webServer>
<modules runAllManagedModulesForAllRequests="true"></modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</code></pre></li>
<li><p>Create an ADO.NET Entity Data Model and connect to any database you own and drag a couple of tables to the designer</p></li>
<li><p>Add a new WCF Service to your project name it: <em>PubsService</em></p></li>
<li><p>Delete the file containing the interface <em>IPubsService.cs</em></p></li>
<li><p>Change the declaration of your service as follows:</p><br />
<pre class="prettyprint cs"><code>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;
}
}
</code></pre></li>
<li><p>Change the markup of the <em>.svc</em> file to include the correct factory:</p><br />
<pre class="prettyprint xml"><code>Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services"
</code></pre></li>
</ul><br />
<p>That’s it, run the application, and you will see something like this:</p><br />
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifY6B6J-DtgX4c04-HFSO7_V9QRH94h-hEpnOJq81F5rcVjgxQFLvw3G1ZkHbmSh4s_BW8pgVhYT-rD2EcU-dJ2M-30uYLXnH-6qQEUEGWIoMqkqBXigaJ4JcLUOIpdpOzDDhWwhWXlro/s1600/list+of+tables.PNG" imageanchor="1" style=""><img border="0" height="53" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifY6B6J-DtgX4c04-HFSO7_V9QRH94h-hEpnOJq81F5rcVjgxQFLvw3G1ZkHbmSh4s_BW8pgVhYT-rD2EcU-dJ2M-30uYLXnH-6qQEUEGWIoMqkqBXigaJ4JcLUOIpdpOzDDhWwhWXlro/s320/list+of+tables.PNG" /></a></p><br />
<p>This is the list of all the tables configured in the <code>InitializeService</code> method</p><br />
<p>To test the queries try something like this:</p><br />
<p><b>http://localhost:55575/PubsService.svc/jobs/?$filter=min_lvl gt 150</b></p><br />
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVE8hoThTLbvgTViqByOGtmkLmSLct_OWuPh8Qa4lYFbYQ5luBOuPcpHIN6YmnCi_JC7UzX8do-MXSmE06S7gWTN7yrI1DpAS3chDnSIhD6KHNrxnstKLaeekRarhPVRBzUkdyGCFiSb4/s1600/wcfdataservicequery.PNG" imageanchor="1" style=""><img border="0" height="172" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVE8hoThTLbvgTViqByOGtmkLmSLct_OWuPh8Qa4lYFbYQ5luBOuPcpHIN6YmnCi_JC7UzX8do-MXSmE06S7gWTN7yrI1DpAS3chDnSIhD6KHNrxnstKLaeekRarhPVRBzUkdyGCFiSb4/s320/wcfdataservicequery.PNG" /></a></p><br />
<p><a href="http://db.tt/u5Zq6JJ7">Download the code of this article</a></p><br />
<p>Happy coding</p>Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com3Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-7176019094933965772012-09-23T04:00:00.001-07:002012-09-23T04:20:46.291-07:00Custom ASP.NET SiteMapProvider combining a database, the file system and static content<p>Hi, I had some trouble while creating a custom <code>SiteMapProvider</code>, 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.</p><br />
<p>The <code>SiteMapProvider</code> 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.</p><br />
<p>Note: This is not about the <em>Sitemap.xml</em> 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.</p><br />
<p>Let’s begin.</p><br />
<p>First thing first. In ASP.Net there’s a default sitemap provider already registered in the <em>web.config</em> file located in: <em>%windir%\Microsoft.NET\Framework\%version%\Config\web.config</em></p><br />
<p>And looks like:</p><br />
<pre class="prettyprint xml"><code> <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>
</code></pre><br />
<p>The <code>XmlSiteMapProvider</code> inherits from: <code>StaticSiteMapProvider</code></p><br />
<p>Most of the blogs will tell you that you must inherit <code>StaticSiteMapProvider</code> and implement your own provider <em>almost from scratch</em>. But it turns out that you can inherit <code>XmlSiteMapProvider</code> and customize it. I have not found a problem so far, if you know a problem with this approach please let me know.</p><br />
<p>So lets create our solution. (I am working with Visual Studio 2012 Express for Web V.11.0.50727.1 RTMREL)</p><br />
<h3>Adding static content</h3><br />
<ul><li>Create an empty Web Application called <em>MixedSiteMapProvider</em> in Visual Studio</li>
<li>Create a class right under the project root called: <code>CustomSitemapProvider</code> and inherit from <code>XmlSiteMapProvider</code></li>
<li>Register the custom sitemap provider in the web.config file:</li>
</ul><br />
<pre class="prettyprint xml"><code> <system.web>
<siteMap defaultProvider="CustomProvider">
<providers>
<add name="CustomProvider" type="MixedSiteMapProvider.CustomSitemapProvider" siteMapFile="Web.sitemap" />
</providers>
</siteMap>
</system.web>
</code></pre><br />
<ul><li>Create a sitemap file called <em>Web.sitemap</em> right under the root project and add the following content:</li>
</ul><br />
<pre class="prettyprint xml"><code> <?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>
</code></pre><br />
<ul><li>Create a <code>MasterPage</code> called <em>Site.master</em> right under the project root and add the following code:</li>
</ul><br />
<pre class="prettyprint html"><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>
</code></pre><br />
<ul><li><p>Create a content ASPX file called <em>Default.aspx</em> right under the project root and select <em>Site.master</em> as its <code>MasterPage</code></p></li>
<li><p>Create a content ASPX file called <em>Default2.aspx</em> right under the project root and select <em>Site.master</em> as its <code>MasterPage</code></p></li>
<li><p>Run the application and you will see the sitemap provider works as expected reading the content of the <em>Web.sitemap</em> file</p></li>
</ul><br />
<h3>Adding File System content</h3><br />
<p>Now we are going to discover the files under a custom path to add them as part of our <code>SiteMapProvider</code></p><br />
<p>The <code>StaticSiteMapProvider</code> and the <code>XmlSiteMapProvider</code> works similar. There’s a method called <code>BuildSiteMap</code> 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 (<code>AddNode</code> method), when finding a node (<code>FindSiteMapNode</code> and <code>FindSiteMapNodeFromKey</code> method), etc. </p><br />
<p>This is important to keep it in mind because this means that if you do not write taking this consideration you could get a <code>StackOverFlowException</code>. The easiest way to solve this, is creating a flag at instance level (more about this in a minute)</p><br />
<p>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 <code>BuildSiteMap</code> 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 <code>lock</code></p><br />
<p>OK, lets roll and create our custom sitemap nodes from the file system.</p><br />
<ul><li><p>Create a subfolder called <em>Topics</em> right under the project root and add three ASPX files, name them <em>Page1.aspx</em>, <em>Page2.aspx</em> and <em>Page3.aspx</em></p></li>
<li><p>Update our <code>CustomSitemapProvider</code> as follows:</p></li>
</ul><br />
<pre class="prettyprint cs"><code>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;
}
}
}
}
</code></pre><br />
<p>I think the code is self explanatory (along the comments). </p><br />
<p>I just want to emphasize the importance of the lock process <code>lock (LockObject)</code> to make the method thread-safe and the flag condition <code>if (this.BuildingNodes)</code> to prevent the execution of the method more than once.</p><br />
<p>If you run your application you will see something like:</p><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhStTgj0MtO8GU9O0v2KKDM4oxQPBGunTWFbkKH2wbrsyuy7FM2K5wBYdF6KnAJIaZSHEBefvYJ-FJ1noWl3LeujDC0RKSu6vrR1uLRLeNh0MtwdTfrTuUqumHbmAXdVoH0ZnzQTzKHWEA/s1600/dynamicsitemap1.PNG" imageanchor="1" style=""><img border="0" height="198" width="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhStTgj0MtO8GU9O0v2KKDM4oxQPBGunTWFbkKH2wbrsyuy7FM2K5wBYdF6KnAJIaZSHEBefvYJ-FJ1noWl3LeujDC0RKSu6vrR1uLRLeNh0MtwdTfrTuUqumHbmAXdVoH0ZnzQTzKHWEA/s320/dynamicsitemap1.PNG" /></a><br />
<br />
<br />
<br />
<h3>Adding database records</h3><br />
<p>The last step is to complement our dynamic sitemap with records from the database.</p><br />
<p>Since we already created the most difficult part, this should be really simple.</p><br />
<p>I’m going to use the <em>PUBS</em> database, and let say that we want to show in our navigation all the <em>job descriptions</em> that exist in the <code>jobs</code> table and inside each one of these categories we want to list all its employees.</p><br />
<ul><li><p>Get the <em>PUBS</em> database <a href="http://www.microsoft.com/en-us/download/details.aspx?id=23654">from here</a> and install it</p></li>
<li><p>Add the following connection string to your web.config file</p></li>
</ul><br />
<pre class="prettyprint xml"><code> <connectionStrings>
<add name="Pubs" providerName="System.Data.SqlClient" connectionString="Data Source=.\sqlexpress;Initial Catalog=pubs;Integrated Security=True" />
</connectionStrings>
</code></pre><br />
<ul><li><p>Create a new <em>LINQ To SQL</em> class named <em>Pubs</em> right under the root of your project</p></li>
<li><p>Connect to the database and drag and drop the <code>jobs</code> and <code>employee</code> tables to de <code>PubsDataContext</code> designer. Save the file and close it</p></li>
<li><p>Add three content ASPX files choosing the <em>Site.master</em> master page right under the root of your project and name them: <em>JobsList.aspx</em>, <em>JobDetails.aspx</em> and <em>EmployeeDetails.aspx</em></p></li>
<li><p>Add the following markup to the <em>JobsList.aspx</em> file</p></li>
</ul><br />
<pre class="prettyprint html"><code>
<%@ 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>
</code></pre><br />
<ul><li>Add the following markup to <em>JobDetails.aspx</em></li>
</ul><br />
<pre class="prettyprint html"><code>
<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>
</code></pre><br />
<ul><li>Add the following code to <em>EmployeeDetails.aspx</em></li>
</ul><br />
<pre class="prettyprint html"><code>
<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" />
</code></pre><br />
<ul><li>Add the following node to the <em>Web.sitemap</em> file</li>
</ul><br />
<pre class="prettyprint html"><code>
<siteMapNode title="PUBS Jobs">
</siteMapNode>
</code></pre><br />
<ul><li>Add the following code to the <code>CustomSitemapProvider</code> class</li>
</ul><br />
<pre class="prettyprint cs"><code>
private const string PubsContentNodeTitle = "PUBS Jobs";
</code></pre><br />
<ul><li>Add the following code to the end of the <code>BuildSiteMap</code> method in the <code>CustomSitemapProvider</code> class, just before the <code>return this.WorkingNode;</code> line</li>
</ul><br />
<pre class="prettyprint cs"><code>
// 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);
}
}
</code></pre><br />
<p>That’s it.... wow this was a really loong post... sorry about that. There was a lot of code for a simple task =(</p><br />
<p>If you run the application you will something like this: (after applying some style)</p><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBHuQLQRLY43Ywfq2xl0R-ZKQv3rfw_Gpkd2JHnuzsy1EmcBbKiClG2HVs-HzRu6o4eCWn1uhqTQypuO55yhOv0R63kqucHshnYp3j9QGQQ1ugEOD0k-DYVEr2wvFzvh0R5miEdSkvK9s/s1600/dynamicsitemap2.PNG" imageanchor="1" style=""><img border="0" height="111" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBHuQLQRLY43Ywfq2xl0R-ZKQv3rfw_Gpkd2JHnuzsy1EmcBbKiClG2HVs-HzRu6o4eCWn1uhqTQypuO55yhOv0R63kqucHshnYp3j9QGQQ1ugEOD0k-DYVEr2wvFzvh0R5miEdSkvK9s/s320/dynamicsitemap2.PNG" /></a><br />
<br />
<a href="http://db.tt/VsPbUaoD">Download the code of this article</a><br />
<br />
<a href="https://github.com/jupaol/LearningProjects/tree/master/VS%202012/src/Blog/MixedSiteMapProvider">Browse the full code in Github</a><br />
Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com1Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475tag:blogger.com,1999:blog-3219791544874033206.post-69926995601940735102012-09-17T20:05:00.000-07:002012-09-21T15:05:20.499-07:00Enabling unobtrusive validation from scratch in ASP.Net 4.5 webforms<a href="http://db.tt/i3f7PoKr">Download the code of this article</a><br />
<br />
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.<br />
<br />
There are three ways to enable the unobtrusive validation on a Web Application:<br />
<br />
Via the web.config file<br />
<br />
<pre class="source-code prettyprint xml"><code>
<configuration>
<appsettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms">
</add></appsettings>
</configuration>
</code></pre><br />
Via the Global.asax file<br />
<br />
<pre class="prettyprint cs"><code>protected void Application_Start(object sender, EventArgs e)
{
ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None;
}
</code></pre><br />
On each page: <br />
<pre class="prettyprint cs"><code>protected void Page_Load(object sender, EventArgs e)
{
this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.WebForms;
}
</code></pre><br />
To disable the unobtrusive validation set the <code>UnobtrusiveValidationMode</code> property to <code>None</code> <br />
<br />
Unobtrusive validation is actually enabled by default in ASP.Net 4.5. <br />
<br />
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.<br />
<br />
Add the following code to the Default.aspx file:<br />
<br />
<br />
<pre class="source-code prettyprint xml"><code> <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" />
</code></pre><br />
<br />
If you try to run a simple ASPX page using a validator, the following exception will be thrown: <br />
<blockquote class="tr_bq">"WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. Please add a ScriptResourceMapping named jquery(case-sensitive)". </blockquote>Before fixing this, let's disable the unobtrusive validation to see the result.<br />
<br />
On the page:<br />
<br />
<pre class="prettyprint cs"><code>protected void Page_Load(object sender, EventArgs e)
{
this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
}
</code></pre><br class="Apple-interchange-newline" /> Now run the page and the validation will work as it used to work in ASP.Net 4.0<br />
<br />
If you examine the rendered HTML, you will see that the gross inline script is rendered:<br />
<br />
<br />
<pre class="source-code prettyprint js"><code>
<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>
</code></pre><br />
<br />
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.)<br />
<br />
<br />
<br />
<ol><li><a href="https://nuget.org/packages/jQuery">jQuery</a></li>
<li><a href="https://nuget.org/packages/AspNet.ScriptManager.jQuery/1.8.1">ASPNET.ScriptManager.jQuery</a></li>
<li><a href="https://nuget.org/packages/Microsoft.AspNet.ScriptManager.MSAjax/4.5.6">Microsoft.AspNet.ScriptManager.MSAjax</a></li>
<li><a href="https://nuget.org/packages/Microsoft.AspNet.ScriptManager.WebForms/4.5.6">Microsoft.AspNet.ScriptManager.WebForms</a></li>
</ol><br />
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 <code>ScriptManager</code> control. <br />
<br />
Let's examine the code added by these Nuget packages using ILSpy:<br />
<br />
<ul><li>AspNet.ScriptManager.jQuery<br />
<pre class="source-code prettyprint cs"><code>
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"
});
}
}
</code></pre></li>
<li>Microsoft.AspNet.ScriptManager.MSAjax<br />
<pre class="source-code prettyprint cs"><code>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
});
}
</code></pre></li>
<li>Microsoft.AspNet.ScriptManager.WebForms<br />
<pre class="source-code prettyprint cs"><code>
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
});
}
</code></pre></li>
</ul><br />
As you can see these Nuget packages automatically register the scripts using the <code>ScriptManager</code> object (besides installing the required JavaScript files)<br />
<br />
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:<br />
<br />
<pre class="source-code prettyprint html"><code><script src="Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js" type="text/javascript"></script>
<script src="Scripts/jquery-1.8.1.js" type="text/javascript"></script>
</code></pre><br />
Much better right?. Notice how ASP.Net used HTML5 custom attributes:<br />
<br />
<pre class="source-code prettyprint html"><code>
<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))" />
</code></pre><br />
The <code>data-val-*</code> are custom attributes used by the unobtrusive validation engine<br />
<br />
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 =/<br />
<br />
The settings we have applied won't work if you intend to use an <code>UpdatePanel</code> control (yeah the evil <code>UpdatePanel</code> again...). This is because this control requires a <code>ScriptManager</code> control on the page (or <code>MasterPage</code>) and we do not have any yet. So let's add a simple <code>ScriptManager</code> control to the master page and see what happens. Add the following code to the Site.master page right under the <code><form...</code><br />
<br />
<pre class="source-code prettyprint html"><code>
<asp:ScriptManager runat="server" ID="scriptManager">
</asp:ScriptManager>
</code></pre><br />
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 <code>ScriptManager</code> control is overriding our code settings.<br />
<br />
To fix it, change the declaration of the <code>ScriptManager</code> control on the Site.master page to:<br />
<br />
<pre class="source-code prettyprint html"><code>
<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>
</code></pre><br />
Run the application and our little example will work again as expected<br />
<br />
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.<br />
<br />
There's one last thing we need to configure, this is because there's actually a bug with the <code>ValidationSummary</code> control.<br />
<br />
To test it, update the Default.aspx page as follows:<br />
<br />
<pre class="source-code prettyprint html"><code>
<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" />
</code></pre><br />
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<br />
<br />
<pre class="source-code prettyprint js"><code>
<script>
window.scrollTo = function () {
};
</script>
</code></pre><br />
Reference links:<br />
<br />
<ul><li><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.scriptreference.aspx">ScriptReference</a></li>
<li><a href="http://www.asp.net/vnext/overview/whitepapers/whats-new">What's New in ASP.NET 4.5 and Visual Studio 2012</a></li>
<li><a href="http://msdn.microsoft.com/en-us/vs11trainingcourse_aspnetwebforms45_topic3#_Toc318982803">Data Validation</a></li>
</ul><br />
<br />
If you found this post useful please leave your comments, I will be happy to hear from you.Anonymoushttp://www.blogger.com/profile/00329887876785526041noreply@blogger.com12Ciudad de México, D.F., México19.4326077 -99.13320818.9534417 -99.7676685 19.911773699999998 -98.4987475