Cycling Through All of the Object References in Visual Studio

You're thinking about making a change to that Transaction class but you're not sure how big an impact that change will have. One way to answer that question is to find all the places that the class is used.

Your first step is to click on the class name (and click on it in any place you find it, by the way). Then press Shift-F12 or right-click on it and pick Find All References. That opens a References window showing the statements that refer to your object (that window typically opens below your editor window).

As useful as that list of references is, I bet you really want to see the context of each of those lines to see how your object is used. Pressing F8 or Shift-F8 will take you to the "next" or "previous" reference; Double-clicking on any of the statements in the References list will take you directly to that statement.

Ctrl-Shift-Up Arrow and Ctrl-Shift-Down Arrow will also move you from one reference to another but, sadly, only within the current file.

Posted by Peter Vogel on 03/12/20190 comments


Initializing a Project with an Existing Database

Eight-five percent of all application development is spent on existing systems, with existing databases. If you want to use Entity Framework's code-first development (where the database schema is an "implementation detail" generated from your object design) and migrations (which modifies your existing schema as your object model evolves), how do you do that with an existing database?

I'd suggest that you first step is to generate the object code that represents your existing tables (I use a tool for that). Once you've done that, and assuming you've used NuGet Manager to add Entity Framework to your project, you just need three commands to initialize your .NET Framework project for code-first migrations. Just enter these commands into Tools | NuGet Package Manager | Package Manager Console:

Enable-Migrations  -ContextTypeName  
Add-Migration  InitialCreate  -IgnoreChanges
Update-Database

If you're working in .NET Core, you can skip the first command (Enable-Migrations). In .NET Core, migrations are enabled by default.

Posted by Peter Vogel on 03/11/20190 comments


Designing with the Dependency Inversion Principle

The Dependency Inversion Principle says "the interface belongs to the client." As I've said elsewhere, adopting this principle means a reversing of the way applications used to be built: Design the database, build the objects to maintain the tables, wrap a UI around those objects and then bring the users in for training because they'd never figure the application out on their own.

The Dependency Inversion Principle says: Build the UIs that your users will understand (the interface belongs to them), design the objects that will make those UIs easy to build, build those classes, design the objects that make those classes easy to build and carry on until code-first Entity Framework generates the database you need.

You know this, already: the Dependency Inversion Principle is what drives the essential difference between ADO.NET and Entity Framework. With ADO.NET, it was your responsibility to create a connection (because you need a connection to the database), create a correctly configured command object (because you have to issue commands), call the appropriate execute method (because different SQL commands work differently) and then manage fetching rows and turning them into objects (because ... well, you get the picture). In other words, ADO.NET's API was driven by how the ADO.NET objects worked -- the reverse of the Dependency Inversion Principle.

On the other hand, essentially what Entity Framework says is, "Tell me what objects you want and I'll get them for you." Entity Framework provides the API that the application wants: An object-oriented way of retrieving, adding, updating and deleting data.

There are real cost-savings associated with the Dependency Inversion Principle. Because the principle requires that objects deliver the functionality that the client wants, interfaces tend to be more stable. Following the principle, APIs only change because the client program wants to do something differently (which, when you think about it, is the only reason we should be changing our code). You're welcome to upgrade how your objects work, of course ... but you're not allowed to change the API.

Of course, this level of abstraction isn't free: Entity Framework doesn't have the performance that pure ADO.NET has, even for the scenarios it targets: online, transactional applications. However, it does improve the productivity of developers who, let's face it (and given the current cost of hardware), are the most expensive part of an application -- just ask my client. And, when you do need "bare metal" levels of performance, there's always Dapper.

And, quite frankly, if you wanted the fastest performance, you'd be writing your code in assembler and running it on MS-DOS. Let's not be silly about performance.

Posted by Peter Vogel on 02/27/20190 comments


Redirect Code in .NET Core

There are four Redirect help methods built into your .NET Core Controllers that you can use to tell a client that a resource exists ... but not at this URL. For all these cases, you should also be setting your response's Location header to tell the client where to find the result the client originally requested.

The helper methods and when to use them are:

  • Redirect: This returns an HTTP 302 status code. This status code tells the client that what they requested can be found at the URL specified in the Location header of the response. However, that resource might be at this URL at some time in the future. If the original request was a POST, it's OK for the client to change that to a GET Request before using the new URL.
  • RedirectPermanent: HTTP 301 status code. This code tells the client that the resource won't ever exist at this URL. The Location header should contain a URL that will give the client something like what they requested if a new request is made to that URL. For anything but GET requests, the user should be informed before a request is made to the new URL. As with Redirect, if the original request was a POST, it's OK for the client to change that to a GET Request before using the new URL.
  • RedirectPermanentPreserveMethod: HTTP 308 status. This says that the requested resource won't ever exist at this URL. However, this code also says that, if this was a POST request, the new request to to the URL specified in the Location header must also be a POST request.
  • RedirectPerserveMethod: HTTP 307 status. As with the original Redirect, this tells client that this redirect is temporary. As with the RedirectPermanentPreservice, this code also says that, if the original request was a POST request, the new request to the URL specified in the Location header must also be a POST request.

Posted by Peter Vogel on 02/25/20190 comments


Returning Files from .NET Core or ASP.NET MVC Controllers

In ASP.NET MVC, the File helper method built into your controller gives you multiple options for retrieving the file you want to send to the client. You can pass the File helper method an array of bytes, a FileStream or the path name to a file depending on whether you want to return something in memory (the array of bytes), an open file (FileStream) or a file on your server's hard disk (a path).

In .NET Core, you still have the File helper method, but it has one limitation: It assumes that any file path you pass it is a virtual path (a relative path within your Web site). To compensate, this new version of the File method simplifies two common operations that require additional code in ASP.NET MVC: checking for new content and returning part of the file when the client includes a Range header in its request.

To handle physical path names in .NET Core, you'll want to switch to using the PhysicalFile helper method. Other than assuming any file name is a physical path to somewhere on your server, this method works just like the new File helper method.

Posted by Peter Vogel on 02/22/20190 comments


Enabling Docker Support

If you've got Visual Studio 2017, you can run your application in Docker (even with the Community Edition).

First, you'll need to download Docker for Windows. You'll need to decide what operating system will be used inside your containers (Windows or Linux). For .NET MVC Core applications and Web services, it doesn't matter which you pick, though generally speaking, I'd say there are more resources available if you choose Linux.

After Docker for Windows is installed, you'll find the Docker icon sitting in the Notifications popup on your taskbar. Right-click on that and pick Settings to display the Settings dialog. From left side of the dialog select Shared Drives. That will give you a list of drives available from your computer. Check off the drives you'll use when running your application and click the Apply button (you'll be asked for your password). Once you've shared your drives, you can close the Settings dialog.

With all that done, starting your Web application in Docker requires just four steps:

  1. Right-click on your project and select Add | Docker Support. You'll get a dialog asking you to pick what operating system your container should use -- pick the same one you chose when installing Docker for Windows. When the dialog closes, you'll find that a Dockerfile file has been added to your project. That file specifies the container image to be used and the instructions for loading and starting your application.
  2. In Visual Studio's toolbar, find the dropdown list for the F5/Play button. From the list, select Docker (you'll probably find that it's already switched to Docker).
  3. Press <F5>. You may get a warning message from your firewall asking you to grant permission for your application but, once you've given that permission, your application should start.
  4. Brag to your friends about how hip and happening you are.

Posted by Peter Vogel on 02/19/20190 comments


Understanding Docker Vocabulary

The purpose of Docker is to build containers that hold, potentially, all of the components of an application: the application itself, the database engine, any Web services it requires and so on. That container, unlike a virtual machine, doesn't require an operating system so it takes less space than a VM and starts up/shuts down faster.

The good news here is that there are a bunch of prepared containers waiting for you to use on Docker Hub: these are called images. Many of them are Linux based, but for .NET Core applications that's not an issue: Core runs as well on Linux as Windows. Docker Hub is an example of a Docker repository and, if you want, you can create your own repository for your company rather than use Docker Hub.

While you can put all the components of an application in a single container, you can also create individual containers for each component (one for the application, one for the database, one for each Web service). This allows you to upgrade/replace components individually or start multiple copies of one container to improve scalability. When you have multiple containers, you'll want to use Compose to create (and start) an application made up of multiple containers.

In production you'll want to be able to monitor your containers, auto-start the appropriate number of any of containers and automatically restart any container that fails. For that you need an orchestrator -- the elephant in this living room is Kubernetes ... which has its own vocabulary (Kubernetes works with services which are made up of pods, each of which may have one or more containers; servers with pods running on them are called nodes).

Most recently, you have Swarm which allows you to treat all the containers in a group as if it were one service.

It would, of course, help if you knew how all this stuff worked. But, with the right terms (and if you can keep the other person talking), you might be able to get through the interview.

Posted by Peter Vogel on 02/11/20190 comments


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:

app.UseMiddleware<CheckPhoto>();

Posted by Peter Vogel on 01/11/20190 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",
    "inputFiles": 
     [
       "wwwroot/js/jquery.js",
       "wwwroot/js/Customers.js",
     ],
     "minify": 
     {
       "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": [
		"wwwroot/js/*(*.js|!(*.min.js))"]

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/20190 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/20190 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)
{
 optionsBuilder
    .UseLazyLoadingProxies()
    .UseSqlServer(
             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/20190 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:

@functions 
{
  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) {
  $(textbox).val("Vogel");
}

Posted by Peter Vogel on 12/06/20180 comments


Subscribe on YouTube