Introducing Interpose.Core

Update: see this post and this one.

I’m writing this from the 2018 MVP Global Summit!

Some of you may remember a series of posts I wrote about AOP and code interception in .NET. In them I built an AOP framework from scratch that could do custom interception. A few years passed by and I decided to revisit it and turn it into a .NET Core project: I introduce to you Interpose.Core.

Interpose: place or insert between one thing and another.

Interpose is available as an open source project (under Lesser GNU Public License) which you can get from GitHub or NuGet. It can do type and instance interception:

  • Type: virtual methods, the type to intercept cannot be sealed
  • Instance: interface and dynamic interception

Interpose uses Roslyn to generate the proxy types. As it targets .NET Core, you can use it on any supported platform.

At its core, you have an interceptor class (IInstanceInterceptor or ITypeInterceptor) and you ask for an instance or a type to be intercepted using a given handler (instance or type). It then generates a proxy instance (or type, which you must instantiate yourself). When using the generated proxy instance, for the target methods or properties, it will execute the provided handler.

So, what’s an handler like? An handler is just any implementation of the IInterceptionHandler method, that offers a single method, Invoke. This method takes a parameter that describes all of the execution context (target object, target method, parameters). From it, you can run the base implementation before or after performing any actions, or you can skip it altogether, in which case, you must provide a return value yourself.

Two instance interception examples, one for each interceptor, first, interface:

var interceptor = new InterfaceInterceptor();
var instance = new MyType();
var handler = new MyHandler();
var proxy = interceptor.Intercept(instance, typeof(IMyType), handler) as IMyType;

As you can see, you need to explicitly state which interface in the target instance you wish to intercept.

For dynamic, you can do something similar:

var interceptor = new DynamicInterceptor(); var instance = new MyType(); var handler = new MyHandler(); dynamic proxy = interceptor.Intercept(instance, null, handler);

Here you don’t need to specify an interface, but you do need to declare your proxy instance as dynamic.

Types are easy to intercept too, the major difference is that you pass types, not instances:

var interceptor = new VirtualMethodInterceptor();

var proxyType = interceptor.Intercept(typeof(MyType), typeof(MyHandler));

var proxy = Activator.CreateInstance(proxyType) as MyType;

Here the handler must be a public non-abstract class with a public parameterless constructor.

A very simple handler could be:

class MyHandler : IInterceptionHandler

{

public void Invoke(InterceptionArgs args)

{

if (args.Method.ReturnType == typeof(int))

{

//always return 100

args.Result = 100;

}

else

{

Console.Out.WriteLine(“Before base method call”);

args.Proceed();

Console.Out.WriteLine(“After base method call”);

}

}

}

There are a couple of extensions that allow you to use a registry for mapping methods to intercept to handlers or handlers defined as attributes.

You can integrate it with .NET Core’s dependency injection framework:

services.AddInterfaceInterceptor();

services.AddVirtualMethodInterceptor();

services.AddDynamicInterceptor();

Still some features missing, such as caching of generated proxy types, interception of generic types or the ability to maintain custom attributes from the base types or interfaces. Will try to address these when I have the time. Also, might be useful to have a small library of common handlers (logging, exception handling, measuring time, etc), if this ever comes to live, I will do it in a different assembly.

In the meantime, enjoy it and let me know what you think!

ASP.NET Core Pitfalls – Session Storage

Previous versions of ASP.NET featured several ways to persist sessions:

  • InProc: sessions would be stored on the server’s process memory
  • SQL Server: sessions would be serialized and stored in a SQL Server database; other vendors offered similar functionality
  • State Server: sessions would be serialized and stored on an instance of the ASP.NET State Service
  • Custom: we had to implement our own persistence mechanism

InProc was probably the most commonly used; it was the fastest, as the items in the session weren’t serialized, but on the other side they would not survive server crashes. Using this approach things usually worked well, because the session object merely provided a reference to the items stored in memory, so manipulating these items didn’t mandate that the session be explicitly saved.

In ASP.NET Core, all of this is gone. By default, sessions are still stored in memory but one can also use one of the available distributed cache mechanisms. The main difference, however, is that even when the session objects are stored in memory, they still need to be serialized and deserialized prior to persisting or retrieving them. It is no longer possible to just store a pointer to a memory object and keep manipulating it transparently; the object to be stored needs to be converted into a byte array first. You can use any serializer you want.

If we think about it seriously, it was probably a good decision: I’ve seen applications where a lot of data was being stored on the session using InProc mode, but then there was a need to switch to another mode to improve scalability, and the application would just stop working, as the objects being stored weren’t serializable. This time, we need to carefully think about it beforehand.

ASP.NET Core Pitfalls – Redirect to Action Keeps Route Parameters

When you redirect after a POST – following the famous Post-Redirect-Get pattern – but your previous view was constructed using a route parameter, then it will be sent to the redirect action as well.

For example, say you are responding to a request for /Filter/Smartphone, where Smartphone is a route parameter, you POST it to some controller action and at the end you redirect to the Index action using the RedirectToAction method:

return this.RedirectToAction(nameof(Index));

The browser will issue the GET request for Index but keeps the Smartphone route parameter, which is not good.

The solution is to pass a routeValues parameter to RedirectToAction that doesn’t contain any of the possible route parameters. One way to do it would be to create a dictionay with all action parameters nullified:

return this.RedirectToAction(nameof(Index), MethodBase.GetCurrentMethod().GetParameters().ToDictionary(x => x.Name, x => (object) null));

The solution to have this done automatically lies in the MethodBase.GetCurrentMethod() method. This way, you are sure to avoid any unwanted route parameters on your next request.

In case you are wondering, passing null, a dictionary without entries or object won’t work, the only other way is to pass an anonymous value with the parameters explicitly set to null.

Entity Framework Core Succinctly Released

My latest (and fifth) ebook for Syncfusion’s Succinctly collection is out: Entity Framework Core Succinctly! It covers Entity Framework Core 2.0 and you can download it for free – need to register first, though.

This book is inspired by my previous one on Entity Framework Code First, but quite a lot has changed.

Huge thanks to Jeff Boenig for the technical review and to Hillary Bowling, Tres Watkins and Jacqueline Bieringer of Syncfusion for all their support.

Entity Framework Core Pitfalls: No TransactionScope Support

Entity Framework Core, as of version 2.0, does not support enlisting in ambient transactions, like those provided by TransactionScope. It is being tracked by issue #9561. This is by design and is related to a limitation of System.Data.SqlClient, which will be fixed when .NET Core 2.1 comes out. The ticket for SqlClient is #3114.

I already talked about the hard relation between Entity Framework and TransactionScope before. This time, however, with EF Core 2.1, it seems that it will be fixed, and this is a good thing. For now, however, you will have to roll out your own transaction management strategy which includes starting your own transactions explicitly and either committing them or rolling them back at the end. Please refer to the Microsoft documentation available at https://docs.microsoft.com/en-us/ef/core/saving/transactions.

Soft Deletes with Entity Framework Core 2 – Part 2

My previous post explained how to setup soft deletes for queries automatically. This time, I’m going to talk about the other part: actually replacing a delete for an update that sets the is deleted column.

The key here is to intercept the SaveChanges method, find out all entities that are ISoftDeletable and are marked for deletion and then set their IsDeleted property and change their state to be modified instead of deleted:

public override int SaveChanges()
{
foreach (var entry in this.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted))
{
if (entry.Entity is ISoftDeletable)
{
entry.Property(_isDeletedProperty).CurrentValue = true;
entry.State = EntityState.Modified;
}
}

return base.SaveChanges();
}
This way Entity Framework will know what to do and just update them instead of deleting them. Next time, they won’t be loaded as they have been marked as deleted.

Soft Deletes with Entity Framework Core 2 – Part 1

Entity Framework Core 2, already covered here, includes a cool feature called global filters. By leveraging global filters, we can apply restrictions automatically to entities, either loaded directly or through a collection reference. If we add this to shadow properties (in the case of relational databases, columns that exist in a table but not on the POCO model), we can do pretty cool stuff.

In this example, I am going to create a soft delete global filter to all entities in the model that implement a marker interface ISoftDeletable.

public interface ISoftDeletable
{
}
We just need to override the DbContext’s OnModelCreating method to automatically scan all known entities to see which implement this interface and then create the restriction automatically:
private const string _isDeletedProperty = "IsDeleted";
private static readonly MethodInfo _propertyMethod = typeof(EF).GetMethod(nameof(EF.Property), BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(typeof(bool));

private static LambdaExpression GetIsDeletedRestriction(Type type)
{
var parm = Expression.Parameter(type, "it");
var prop = Expression.Call(_propertyMethod, parm, Expression.Constant(_isDeletedProperty));
var condition = Expression.MakeBinary(ExpressionType.Equal, prop, Expression.Constant(false));
var lambda = Expression.Lambda(condition, parm);
return lambda;
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
if (typeof(ISoftDeletable).IsAssignableFrom(entity.ClrType) == true)
{
entity.AddProperty(_isDeletedProperty, typeof(bool));

modelBuilder
.Entity(entity.ClrType)
.HasQueryFilter(GetIsDeletedRestriction(entity.ClrType));
}
}

base.OnModelCreating(modelBuilder);
}
So, for each entity known from the context we add a shadow property called IsDeleted of type bool. Of course, needless to say, it must also exist on the database. The reason I’m making it a shadow property is to avoid people tampering with the entities, by setting or unsetting its value. This way, the restriction is always performed and it is invisible to us. After we create the property, we add a restriction to the entity’s type.
Simple, don’t you think? This way, if you want to enable or disable it for a number of entities, just have them implement the ISoftDeletable interface.

Mastering ASP.NET Core 2.0

Mastering ASP.NET Core 2.0 Book Cover

My new book is out! It is called Mastering ASP.NET Core 2.0 and was edited by Packt Publishing, as my previous one, Entity Framework Core Cookbook – Second Edition.

It was big challenge – the book has over 480 pages – and it spanned multiple .NET Core versions – 1.1 and 2.0. I tried to cover the most important things, even with some detail. The chapters are:

  1. Getting Started with ASP.NET Core: .NET Core, ASP.NET Core, platforms, DI & IoC, MVC pattern, OWIN, hosting, environments
  2. Configuration: providers
  3. Routing: templates, handlers, constraints, areas, error handling
  4. Controllers and Actions: controller lifecycle, API controllers, versioning, documentation, globalization, binding
  5. Views: areas, layouts, Razor pages, globalization
  6. Using Forms and Models: metadata, templates, binding, validation
  7. Security: authentication, authorization, anti-forgery, CORS, HTTPS
  8. Reusable Components: partial views, view components, tag helpers and tag helper components
  9. Filters: authorization, resource, action, result, exception, Razor page
  10. Logging, Tracing and Diagnostics: custom middleware, logging, DiagnosticSource, ELM, AppInsights, HealthCheck
  11. Testing: xUnit, integration tests, UI tests with Selenium
  12. Client-Side Development: Bower, Node.js/NPM, Gulp, Grunt, TypeScript, LESS
  13. Improving the Performance and Scalability: asynchronous methods, profiling, bundling and minification, caching, response compression
  14. Real-Time Communication: SignalR
  15. Other Topics: areas, static files, application lifetime events, conventions, embedded resources, hosting extensions, URL rewriting
  16. Deployment: Visual Studio, IIS, Azure, AWS, Nginx, Apache, Docker, Windows Service

Whenever there are important differences, I mention the differences between ASP.NET Core 1.x and 2.x, although I think this will be less important over time.

Overall, it was an exciting task, but not one without obstacles. I must thank the team at Packt Publishing, namely, Siddhi Chavan and Abhishek Sharma for all their patience and support.

Do have a look and share your feedback! It is available from the Packt Publishing site, Amazon and others, either in hardcopy or ebook format. The source code is available at https://github.com/PacktPublishing/Mastering-ASP.NET-Core-2.0.

Entity Framework Core Extensions: Getting Primary Keys and Dirty Properties

Two simple hacks: finding the primary key values:

public static IDictionary<string, object> GetKeys(this DbContext ctx, object entity)
{
if (ctx == null)
{
throw new ArgumentNullException(nameof(ctx));
}

if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}

var entry = ctx.Entry(entity);
var primaryKey = entry.Metadata.FindPrimaryKey();
var keys = primaryKey.Properties.ToDictionary(x => x.Name, x => x.PropertyInfo.GetValue(entity));

return keys;
}

This returns a dictionary because some entities may have composite primary keys.

As for getting the dirty (modified) properties’ names for an entity:

public static IEnumerable<string> GetDirtyProperties(this DbContext ctx, object entity)
{
if (ctx == null)
{
throw new ArgumentNullException(nameof(ctx));
}

if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}

var entry = ctx.Entry(entity);
var originalValues = entry.OriginalValues;
var currentValues = entry.CurrentValues;

foreach (var prop in originalValues.Properties)
{
if (object.Equals(originalValues[prop.Name], currentValues[prop.Name]) == false)
{
yield return prop.Name;
}
}
}
Picking on the last one, if we wish to reset an entity to it’s original values:
public static void Reset(this DbContext ctx, object entity)
{
if (ctx == null)
{
throw new ArgumentNullException(nameof(ctx));
}

if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}

var entry = ctx.Entry(entity);
var originalValues = entry.OriginalValues;
var currentValues = entry.CurrentValues;

foreach (var prop in originalValues.Properties)
{
currentValues[prop.Name] = originalValues[prop.Name];
}

entry.State = EntityState.Unchanged;
}

Mind you, this one will not reset collections or references, just plain properties.

Hope it helps!

Getting the HTML for a ViewResult in ASP.NET Core

This is another post tagged “hack”: this time, how to get the HTML for a rendered view, in code. This is a standard solution that does not use any kind of reflection (or other) magic.

So, the idea is to pick up a ViewResult (it will also work for a PartialViewResult, but, alas, they do not share a common class – see #6984) and call some method, say, ToHtml, to get the rendered output. This method can look like this:

public static class ViewResultExtensions
{
public static string ToHtml(this ViewResult result, HttpContext httpContext)
{
var feature = httpContext.Features.Get<IRoutingFeature>();
var routeData = feature.RouteData;
var viewName = result.ViewName ?? routeData.Values["action"] as string;
var actionContext = new ActionContext(httpContext, routeData, new ControllerActionDescriptor());
var options = httpContext.RequestServices.GetRequiredService<IOptions<MvcViewOptions>>();
var htmlHelperOptions = options.Value.HtmlHelperOptions;
var viewEngineResult = result.ViewEngine?.FindView(actionContext, viewName, true) ?? options.Value.ViewEngines.Select(x => x.FindView(actionContext, viewName, true)).FirstOrDefault(x => x != null);
var view = viewEngineResult.View;
var builder = new StringBuilder();

using (var output = new StringWriter(builder))
{
var viewContext = new ViewContext(actionContext, view, result.ViewData, result.TempData, output, htmlHelperOptions);

view
.RenderAsync(viewContext)
.GetAwaiter()
.GetResult();
}

return builder.ToString();
}
}
To use it, just do:
var view = this.View(“ViewName”);
var html = view.ToHtml();

Have fun! Winking smile