Extending the ASP.NET Core Processing Pipeline

I've done at least a couple of articles on how to support adding custom processing to every request to your ASP.NET MVC site (most recently, an article on HTTP Modules and Handlers). In ASP.NET Core the process is very different (of course) but it's actually much simpler.

Your first step to adding some processing to the ASP.NET pipeline is to create a class whose constructor accepts a RequestDelegate object. You should store that RequestDelegate in a property or field because you'll need it later:

public class CheckPhoto
  private readonly RequestDelegate rd;
  public CheckPhoto(RequestDelegate next)
    rd = next;

Your second step is to add an async method to your class called Invoke and have it accept an HttpContext object and return a Task:

  public async Task Invoke(HttpContext ctxt)

In that method you should call the Invoke method on the RequestDelegate passed to your constructor, passing on that HttpContext object (use the await keyword to get the benefits of asynchronous processing). By calling the Invoke method, you're invoking the next module in the processing chain during request processing -- that HttpContext object includes information about the incoming request. When that Invoke method returns, it means all the processing associated with that request is complete (including running your own code, of course) and the HttpContext object holds everything associated with your application's response.

Anything you want to do in terms of processing the incoming request should be done before calling the Invoke method; anything you want to do with the Response, you should do with the HttpContext after calling the Invoke method.

This means a typical Invoke method looks like this:

  public async Task Invoke(HttpContext ctxt)
    // ... work with HttpContext in handling the incoming request ... 
    await rd.Invoke(ctxt);
    // ... work with HttpContext in handling the outgoing response ... 

To tell your site to use your module, first go to the Configure method in your project's Startup class. In the Configure method, call the UseMiddleware method on the IApplicationBuilder object passed to the method, referencing your class. Since the parameter holding the IApplicationBuilder object is called app, that code looks like this:


Posted by Peter Vogel on 01/11/2019 at 5:05 PM0 comments

Bundling Scripts in ASP.NET Core

In ASP.NET MVC Core the BundleConfig class -- where, in ASP.NET MVC, you used code to create script bundles in ASP.NET MVC -- is gone. Instead, you use a configuration file called bundleconfig.json to name your bundles and assign files to them.

This sample code combines two JavaScript files into a bundle called site.min.js (it also triggers minifying all the files added to the bundle):

    "outputFileName": "wwwroot/js/site.min.js",
       "enabled": true,
       "renameLocals": true

If you don't want to put in every file individually, you can use globbing patterns to gather up the files you want. This example gets every JavaScript file in the wwwroot/js folder that isn't already marked as minified:

"inputFiles": [

Finally you just need put a script tag that refers to your bundle into your page:

<script href="~/js/site.min.js"></script>

Posted by Peter Vogel on 01/10/2019 at 8:05 AM0 comments

When the Watch Window in Visual Studio Doesn't Update

While debugging in Visual Studio, you may notice, when you check some value in the Watch window, one of two icons beside your data. You may get one or the other of a circle with two wavy lines inside of it or the standard refresh icon of two curved arrows chasing each other. Either icon indicates that the data being displayed in the Watch window isn't up to date.

There are two reasons for these icons appearing: Either there's been a problem in fetching the data (e.g. a timeout) or Visual Studio is concerned that evaluating the expression may result in some side-effects that will make debugging more difficult for you.

It's lovely that you get that warning but, if you've noticed the icons then it's probably because you're checking the value and, if you're checking the value then it's probably because you need that value. Clicking the icon will force Visual Studio to make another attempt at giving you the latest version of the data you want.

If you can't get the data you want (or if it turns out that Visual Studio was right and re-evaluating the expression really did make your life more difficult) then your best option is to set a breakpoint a line or two earlier and re-run your test.

Posted by Peter Vogel on 01/09/2019 at 8:34 AM0 comments

Lazy Loading in Entity Framework Core

Microsoft has emphasized that, while LINQ code is "copy and paste" compatible from Entity Framework 6 to Entity Framework Core, you should do a lot of testing to make sure that any code you copy behaves the same way in its new environment as it did in the old (you really get the impression that Microsoft doesn't think you can do enough testing).

Part of the reason for those warnings is Entity Framework 6's quiet support for lazy loading. If you've put the virtual keyword on your navigation properties and omitted an include method in your LINQ query, lazy loading will ensure that rows are downloaded to your code ... and you might not know that's what's happening. When you migrate that code to Entity Framework Core then, in the absence of lazy loading, a whole bunch of formerly working code is going to find a bunch of empty navigation properties.

The good news is that Entity Framework Core's Microsoft.EntityFrameworkCore.Proxies NuGet package provides support for lazy loading. After you add the package to your project, you just need to configure Entity Framework Core to use it. To do that, go to your DbContext object and, in the OnConfiguring method, call the UseLazyLoadingProxies method on the DbContextOptionsBuilder object that's passed to the method.

Typical code for a DbContext class already working with SQL Server would look like this:

protected override void OnConfiguring(
               DbContextOptionsBuilder optionsBuilder)
             Configuration.GetConnectionString(" ... connection string name ... "));

I'm not suggesting that, after making these changes, you still shouldn't do a lot of testing; I am saying that you're less likely to be surprised if you do make these changes.

Posted by Peter Vogel on 01/08/2019 at 8:08 AM0 comments

An Ad Hoc Approach to Passing Elements from Blazor to JavaScript

In a previous column I described an architectural, design-pattern-based approach to integrating JavaScript and Blazor code. However, if you just need to pass one element from your Blazor page to some JavaScript functions, that approach might be overkill.

Instead of adopting my approach, when you declare an HTML element in Blazor, you can add a ref attribute to the element in order to assign a "Blazor-accessible" name to the element. This HTML, for example, assigns the name mytextbox to a textbox:

<input type="text" id="atextbox" ref="mytextbox" value="Peter" />

You can now, in your Blazor code, declare a field as an ElementRef object with the same name you used in the ref attribute -- Blazor will automatically bind that ElementRef field to the HTML element. You can't do much with an ElementRef variable in Blazor ... except pass it to a JavaScript function. This code, for example, passes the textbox to a JavaScript function called SetName:

  ElementRef mytextbox;

  protected override Task OnInitAsync()
    await JSRuntime.Current.InvokeAsync<string>("SetName", mytextbox );

Within the JavaScript function you can treat the element as an HtmlElement and access its properties. As an example, this JavaScript code sets the textbox's value property to "Vogel":

function SetName(textbox) {
  textbox.value = "Vogel";

Once you have the element you can, of course, also use it with jQuery. This code also sets the element's value to "Vogel" but does it using jQuery's val function:

function SetName(textbox) {

Posted by Peter Vogel on 12/06/2018 at 10:56 AM0 comments

Check to See What's Changed in Entity Framework

When you call Entity Framework's SaveChanges method, Entity Framework has to know what entities have changed in order to figure out what SQL Update/Delete/Insert statements to generate. If you also want to find out what entities have changed, then you can access that information through the DbContext object's ChangeTracker property.

The ChangeTracker property holds Entity Framework's DbChangeTracker object, which, in turn, has a collection called Entries that holds all objects being tracked. This code, for example, writes to some kind of log the name of the classes with pending changes, along with their current state (for example, Modified, Added, Deleted and so on):

CustomerEntities db = new CustomerEntities();
// ... make changes to objects in db ... 

//Record pending changes
foreach (DbEntityEntry e in db.ChangeTracker.Entries())
  AuditLog.Write("Name and Status: {0} is {1}", e.Entity.GetType().FullName, e.State);

If you want to get the primary key value for the objects being changed, this code will build a string out of all the values for the properties that make up the primary key:

IObjectContextAdapter oca = (IObjectContextAdapter) db;
ObjectStateManager osm = oca.ObjectContext.ObjectStateManager;
ObjectStateEntry ose = osm.GetObjectStateEntry(e.Entity);

string keys;
keys = string.Empty;
foreach(object key in ose.EntityKey.EntityKeyValues)
  keys = keys + key.ToString() + "/";

I've assumed in this code that it's very unusual to have an entity whose primary key consists of multiple properties. If that's not true for you, then you should probably use the StringBuilder class to hold your concatenated key values rather than a simple string.

If you do go that extra mile, you could incorporate that information into your log entry. It might also make sense to write to your log as comma-delimited values so you can load the log into Excel for analysis. That code would look like this:

AuditLog.Write("{0},{1},{2}", e.Entity.GetType().FullName, keys, e.State);

Posted by Peter Vogel on 11/27/2018 at 9:20 AM0 comments

A Better Way to Test for Exceptions in Visual Studio

I've always argued that the only easier way to test your code than using Visual Studio Test is to not test at all. But that doesn't mean that I think Visual Studio Test is perfect.

For example, the ExpectedException attribute, when placed on a test method, lets you check to make sure that your code throws the appropriate exception when something goes horribly wrong. The problem with ExpectedException is that it applies to the whole test method, not just the "code under test." This means that if your test or production code throws that exception anywhere at all, the ExpectedException attribute will tell you that your test has passed. Unfortunately, that exception may or may not have been thrown where you actually expected it to be thrown. That's not quite what you want to test for.

You have a better alternatives: the Assert object's ThrowsException and ThrowsExceptionAsync methods. With either of those methods, you specify the exception you expect to get from your method and then pass the code you want to test (as a lambda expression) to the method.

This example checks to see if the GetCustomer method throws a NullReferenceException when the GetCustomer method is called with an empty string:

Customer cust;
Assert.ThrowsException<NullReferenceException>(() => cust = CustomerRepository.GetCustomer(""));

This test will now pass if (and only if) this call to the GetCustomer method throws a NullReferenceException. If any other code in my test method throws that exception (or if my code throws any other kind of exception), my test will be flagged as failed. And that's exactly what I want.

Posted by Peter Vogel on 11/16/2018 at 11:34 AM0 comments

Making Breakpoints Useful in Visual Studio

How many times have you done this because you wanted to check how the value of some variable changes over time:

  1. Set a breakpoint
  2. Wait for Visual Studio to stop on the line
  3. Check the value of the variables you're interested in
  4. Press F5 to continue
  5. Wait for Visual to stop on the line again
  6. Check the value of the variables you're interested in
  7. Press F5 to continue
  8. Repeat ...

There's a better way. You can have your breakpoints automatically print a message to your Output Windows and keep right on executing. You'll get a reviewable list of all of the values your variable has had, listed in order (no more "Wait! What was the last value? I've forgotten.").

How you take advantage of this feature depends on what version of Visual Studio you're using. In older versions of Visual Studio, right-click on a breakpoint and select the When Hit option from the popup menu. In more recent versions of Visual Studio, you still right-click on the breakpoint, but then you select the Actions option.

In the resulting dialog box you can put in any text you want displayed, along with the names of the variables whose values you want displayed. The variable names must be enclosed in curly braces ( { } ). This example displays the value of the EditorCount variable with the text "Count:":

Count: {EditorCount}

You'll also find that you have a Continue Execution option in the dialog. That option is checked by default and, if you leave it checked, then Visual Studio won't stop executing when it reaches your breakpoint. Instead, when Visual Studio reaches your breakpoint, you'll get your message logged to the Output window and Visual Studio will keep right on going.

Posted by Peter Vogel on 11/13/2018 at 9:03 AM0 comments

Updating Request Messages in ASP.NET Handlers and Modules

In an earlier column I showed how to add custom processing to every request or response that your ASP.NET MVC or ASP.NET Web API site receives or produces. In that column, I offhandedly remarked about the kinds of things you can do to those incoming and outgoing requests. I didn't, however, actually provide the code (just as well, probably, because the column was getting into tl;dr territory). My conscience has caught up with me: Here's the kind of code you can put in a handler or module.

In an ASP.NET MVC module, you're effectively limited to adding headers to the incoming request or outgoing response. You can also work with headers in ASP.NET Web API handlers. This code, applied to the incoming request in either enviroment, removes the Accept handler and adds a replacement (assuming that the variable r points to a request or response, of course):

r.Headers.Add("Accept", "text/html");

In an ASP.NET Web API handler, you can also replace the content of the incoming request message, like this:

request.Content = new System.Net.Http.StringContent("{'custid':'A123'}", Encoding.UTF8, "application/json");

If you use this technique, the default model binding process won't load the parameters in your Action method with the content you've just inserted into the message. You'll need to write code like this in your Action method to retrieve that content:

public async Task Get(string Id)
  string result = await Request.Content.ReadAsStringAsync();

The code to replace the outgoing request message in a Web API message handler is similar to the code to replace the incoming request:

resp.Content = new System.Net.Http.StringContent("{'custid':'A124'}", Encoding.UTF8, "application/json");

Posted by Peter Vogel on 11/05/2018 at 10:21 AM0 comments

Skipping Through Definitions and References in Visual Studio

In Visual Studio, if you want to find out what that xCt_1 variable really is or see the definition for that TranX class, the easiest way is to click on the variable or class name and press F12. You'll be taken straight to the statement that declares that variable or defines that class.

Once you get to the definition, if you want to see where that variable or object is used, press Shift_F12 and you'll open a window showing all the statements that use your selected name. Clicking on any one of those lines in the window will take you to the statement in the editor.

In the latest version of Visual Studio 2017, getting to a name's definition is even easier: hover your mouse over the variable or class name, press and hold the Control key, and then click on the name. You're taken straight to the definition.

Posted by Peter Vogel on 10/29/2018 at 11:46 AM0 comments

Returning Status Codes from ASP.NET Core Controllers

Short, short tip: If you're working in an ASP.NET Core controller you may not have noticed that you have some new methods for generating a response to go back to the client: Ok, Created, NotFound and others. Each of these methods returns a standard HTTP status code. All these methods accept parameters that also let you pass in some content to be formatted into your return message's body.

Saying "Everything went swell" or "Sorry about that" has never been easier.

Posted by Peter Vogel on 10/26/2018 at 1:31 PM0 comments

Leveraging and Testing Script Bundles with Content Delivery Networks

You can significantly reduce the time your users wait to see your ASP.NET pages by bundling your site's JavaScript files into a single zip file. You're not limited to downloading just your script files, however: There's nothing stopping you from including files from the Content Delivery Network of your choice. All you have to do is pass the URL to the CDN as the second parameter when you create a ScriptBundle, like this:

bundles.UseCdn = true;
bundles.Add(new ScriptBundle("~/bundles/jquery", 
.Include( ... local script files ... ));

Microsoft recommends you provide a fallback when you use a CDN, in case the CDN isn't available. Microsoft suggests a script tag like that shown below to follow the script elements that fetch your script files. This code checks to see if the objects in the CDN file have been downloaded (jQuery, in my example) then goes and gets a local copy of the file if they're not:

<script type="text/javascript">
  if (typeof jQuery == 'undefined') {
    var e = document.createElement('script');
    e.src = '@Url.Content("~/Scripts/jquery-1.7.1.js")';
    e.type = 'text/javascript';

Personally, I think it's more likely that your scripts won't be available.

You'll want to test this, of course, but ASP.NET will steadfastly refuse to bundle your scripts when running in debug mode. If you want, you can add this line of code to your BundleConfig file in your project's App_Start folder to enable bundling even in debug mode:

BundleTable.EnableOptimization = true;

Posted by Peter Vogel on 10/25/2018 at 8:57 AM0 comments

Most   Popular
Upcoming Events

.NET Insight

Sign up for our newsletter.

Terms and Privacy Policy consent

I agree to this site's Privacy Policy.