ASP.NET Core: Injecting your DB Context into your Controllers

What is Dependancy Injection?

The type of Dependency Injection ill be looking at today can be categorized as “Constructor Injection”.  The idea is that we will inject the needed classes into the constructor, rather than creating or instantiating new objects, thus achieving loose coupling between objects.

When classes are designed with DI in mind, they are more loosely coupled because they do not have direct, hard-coded dependencies on their collaborators. This follows the Dependency Inversion Principle, which states that “high level modules should not depend on low level modules; both should depend on abstractions.” Instead of referencing specific implementations, classes request abstractions (typically interfaces) which are provided to them when the class is constructed. Extracting dependencies into interfaces and providing implementations of these interfaces as parameters is also an example of the Strategy design pattern.
– MS Docs

Dependency Injection is setup in the ConfigureServices method of Startup.cs
This ConfigureServices method is responsible for setting the things that can be injected into our constructors.

Each services.Add extension method adds (and potentially configures) services. For example, services.AddMvc() adds the services MVC requires.
– MS Docs

In this example I will focus on setting up DB Contexts. To learn more about registering your own services check out Microsoft’s docs here.


Creating a New ASP.NET Core Web Application

When you create a new ASP.NET Core Web Application with Authentication your ConfigureServices method and appsetting.json are set up automatically for you. This is a good place to start. You will see that AddDBContext() is in ConfigureServices and the connection string is stored in appsettings.json.  It should look something like this…

        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            .................
        }
appsettings.json

{
 "ConnectionStrings": {
 "DefaultConnection": "Server=XXXXXX,1433;Initial Catalog=XXXXXX;Persist Security Info=False;User ID=XXXXXXX;Password=XXXXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
 }
}

This is great, and if it is a part of a new web application, then migrations is auto setup for you.  But what if you have another database that you want to build a model for, set up its context, then inject into your controllers…

Injecting an existing DB and DB Context

If you would like to learn how to “reverse engineer” your database tables into a c# model, check out this post.

If you ran the linked above “scaffold” command to create your model and context, you will see that the  connection string is set in the OnConfiguring() method or you new context.


        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
            optionsBuilder.UseSqlServer(@"XXXXXt;Database=XXXXX;user id=XXXXX;password=XXXXX;");
        }

Delete the entire above OnConfiguring() method. Replace it with a constructor for your context (below) and pass it the DB  options that we will setup next, in our Startup.cs class

        public SunstackContext(DbContextOptions<MyNewContext> options) : base(options)
        {
            //any changes to the context options can now be done here
        }

Next, we want to add the database’s connection string to appsettings.json

  "ConnectionStrings": {
    "DefaultConnection": "Server=XXXXX,1433;Initial Catalog=XXXXX;Persist Security Info=False;User ID=XXXXXX;Password=XXXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;",
    "MyNewConnection": "XXXXXX,1433;Initial Catalog=XXXXX;Persist Security Info=False;User ID=XXXXX;Password=XXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
  },

And then we hook up this DBContext to your services in ConfigureServices()

        public void ConfigureServices(IServiceCollection services)
        {

            // Add User DB connection
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            //Add My New DB connection
            services.AddDbContext<MyNewContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("MyNewConnection")
                ));

            ..........

        }

At this point everything should build!!
We now have the new context setup and ready to inject into a controller.  The last step is very easy, just add our new service to ANY controller’s constructor, here is  simple example.

    public class FileManagerController : Controller
    {
        MyNewContext _myNewContext;

        public FileManagerController(MyNewContext context)
        {
            _myNewContext = context;
        }

    }

 

Angular, Kendo-UI, ASP.NET, and Server Side Paging

It was hard to find a good Angular and ASP.NET example of server side grouping, sorting, and filtering.  Kendo does have good documentation, and examples, but filtering through all the noise can be exhausting.  So here I will show how to setup some basic kendo grid page sorting and filtering.

First you will need to add the following to your app

  • Kendo.Mvc
  • kendo.aspnetmvc.min.js

Setting Up Your Server Side Code

Here is an example in the Kendo docs.

We will use a kendo object called “DataSourceRequest” which will hold information about sorting, grouping, filtering, and ordering.  When used with “ToDataSourceResult()” the list we are returning will automatically be filter down to the parameters that are defined in “DataSourceRequest”. Its pretty slick.

using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;

namespace Test.Example
{

    public class ExampleController : Controller
    {
        // GET api/Example/Get
        [HttpGet]
        public DataSourceResult Get([DataSourceRequest]DataSourceRequest request)
        {
            IList <item> myListToReturn = [Your array of object to return here];
            return myListToReturn.ToDataSourceResult(request);
        }

    }

}

Setting Up Your HTML

I will keep the grid’s “data source” and the grid’s “options” separate just to make things slightly easier to understand. In practiced, they can easily be combined.

<div class="container-fluid" ng-controller="exampleController">
    <div kendo-grid k-options="kendoGridOptions" k-data-source="kendoGridDataSource"></div>
</div>

 

Setting Up Your Angular Conroller

In you angular controller, set up “kendoGridOptions” and “kendoGridDataSource”.


angular.module('myApp', ['kendo.directives']);

angular
    .module('myApp')
    .controller('exampleController', exampleController) 

exampleController.$inject = ['$scope', "$http"];
function exampleController($scope, $http) {

    //Set the grid's options
    $scope.kendoGridOptions = {
        sortable: true,
        groupable: true,
        selectable: true,
        resizable: true,
        pageable: {
            pageSizes: [15, 25, 50, 100, 500]
        }
    };

    //set the data source
    $scope.kendoGridDataSource = {
        transport: {
            read: function (options) {
                var webapi = new kendo.data.transports.webapi({ prefix: "" });
                var params = webapi.parameterMap(options.data);
                $http.get("/api/Example", { params: params })
                    .success(function (data) {
                        options.success(data);
                    })
                    .error(function (data) {
                        options.error();
                    });
            }
        },
        serverPaging: true,
        serverSorting: true,
        serverFiltering: true,
        serverGrouping: true,
        serverAggregates: true,
        pageSize: 15,
        schema: $.extend({}, kendo.data.schemas.webapi, { data: "Data", total: "Total", errors: "Errors" })
    };
};

 

Other Kendo Links

Here are a couple other posts that I have done about Kendo-UI’s Grid tools

Power BI – Connect to your secure API

Power BI’s web portal and desktop application are slightly different, but this tutorial will work for both.

Getting API Data

  1. Open up Power BI and select “Edit Queries”.
  2. Click “New Source” and select “Blank Query”.
  3. Next, select “Advanced Editor”.

    Capture.PNG

  4. In the editor, enter the API’s address and any header information needed for that api.
    let
         apiUrl = "https://xxxxxxx/api/info",
         options = [Headers =[#"Subscription-Key"="xxxxxxxxxxxxxxxxxxxxx"]],
         result = Web.Contents(apiUrl , options)
    in
         result
    

    Capture.PNG

  5. After you add the Query, you will then need to “Connect”. In Power BI Desktop, a warning message pops up letting you know this. Click “Edit Credentials”

    Capture.PNG

  6.  The Access Web content pop-up will show a few different ways to set up you API credentials.  For this example, we just needed to include a “Key” in the header. Since we already did that, all we have to do is press “Connect”.

 

Thats it! You should now be connected and see the results of the api call.  You can “drill” into the results and select what information and object are important to you.  As you do this, check out “Advanced Editor” again.  You will see that slight changes are made to it as you configure the data you want.

Publish existing .Net Application to GitHub: Visual Studio 2015

I just went the past year without using GitHub 😦  The projects I have been working on since then have relied only on TFS.  This blog post is an attempt to re-remember how to publish and existing project (In my case, an ASP.NET Web App) and now that its written I wont have to re-remember it next time!

Getting Set Up

  • Set up a GitHub account here.
  • Download GitHub Extension for Visual Studio here.
  • Connect Visual Studio to your GitHub account by clicking on the green plugin. Then selecting “Manage Connections”.
    Capture.PNG
  • After you’re connected, navigate back to the Team Explorer’s Home page. Select “Settings”.

    1.PNG

  • Next, enter your GitHub Username and Email.  Also, set your default repository location.  This is where your projects should be in order to publish them up to GitHub.

    2.PNG

Publish a Project or Solution to GitHub

  • Create any project or solution you like, or open up and existing one.  Either move or save your new project to the Default Repository Location that you entered above.   For this example I’m going to create a new ASP.NET Web Application and I will save it to C:\WorkSpace\GitHub
  • Right click the Solution and select “Add Solution to Source Control”.

    3.PNG
    You should see this in the output window
  • Next, reopen Team Explorer and select “Sync”. You should see a few different option, since we are publishing to GitHub choose that option.

    4.PNG

  • Enter some comments and then click “Publish”!

    5.PNG

  • After you click “publish”, log into GitHub and you should see your project there!

    6.PNG

 

Commit and Push changes

  • Open up your solution and make any change you want to it or any projects within it. Save those changes > Right-Click solution > select “Commit”
    You should see the changes dialog, similar to below.
    If you don’t see this, then go back to the Team Explorer and click “Changes”.

    7.PNG

  • After entering some comments,  select “Commit All”. You can also select “Commit All and Push”, but I’m going to split this up into two separate steps for this tutorial.

 

Next, let’s push this commit to our GitHub repository.  To do this go to the Team Explorer and click “Sync”.

8.PNG

  • Check it out above, its your commit!  Now just click “Push” to publish it to GitHub!  That’s the last step. If you go to your GitHub page you should see your commit and its comments.

9.PNG

Entity Framework Core 1.0 – Speed up the retrieval of large data sets with .AsNoTracking()

If you are experiencing performance issues with Entity Framework Core 1.0 when you try to include related objects in your LINQ and lambda expressions on record sets of just a few thousand records, (More about Lazy and Eager Loading here) then check out these examples on how to improve it. Of the many ways, the best way that I have found to negate those performance problems and to optimize your requests is by using .AsNoTracking()

What is AsNoTracking()
When you use .AsNoTracking() you are basically telling the context not to track the retrieved information. Sure, this turns off a useful EF feature, but in many cases (like building an api in my case) this feature is unneeded.

In summary, Tracking is turned on by default and is great if you want to retrieve and save objects all within the same context. But if this is not required, you should use AsNewTracking(). AsNoTracking() decouples the returned records from the context, making your queries much faster!

Example

IList<Player> playerList = db.Player.AsNoTracking().ToList()

Example with Joins

IList<Player> playerList = (from p in db.Player
                        select p)
                        .Include(p => p.Team)
                        .ThenInclude(t => t.League)
                        .AsNoTracking()
                        .ToList();

 

It is also worth noting that there is another way to decouple your objects from EF.  This other way can be done by adding .AsEnumerable().  That would look like this:

var decoupledList = from x in TableA<strong>.AsEnumerable()</strong>

Using Different Frameworks in your ASP.Net Core 1.0 App

This was written for the RC1 version of ASP.Net Core, but the idea of using multiple frameworks is still a core concept of ASP.Net Core 1.0. 
Also, Microsoft has recently stated that project.json will go away around the time the new version of Visual Studio is released. The idea is that settings will move back to the .csproj file to enable better integration with MSBuild in that time frame.

ASP.NET Core 1.0 can run on top of both ASP.NET 4.x and ASP.NET Core 1.0 frameworks.

This is REALY cool.  It can also be very confusing. Why would you want to use both?  Currently the Core 1.0 is limited and there are tools that we just dont have available to us yet.  Also you may be porting over old code or referencing a old class library that depends on specific resources built around ASP.NET 4.x and you dont want to go through the hassle of upgrading and rewriting everything.  Check out your project.json file to configure these options.

what is project.json?

New to ASP.Net Core 1.0! The project.json file defines your package metadata, your project dependencies and which frameworks you want to build for.  (relatively similar to ASP.NET 4x’s package.config).  You can remove or add a dependency from this file. When you do, you’re solution will automatically be updated to reflect those changes. You can also set what frameworks you want to app to compile across here!

what is DNX (.Net Execution Enviroment)

The DNX is a runtime environment that has everything you need to create a .Net application.  Next time you create a new core 1.0 project, what your essentially creating is a DNX project, whether its a web app or api.  From the ASP.Net Docs…

The RC1 release of .NET Core and ASP.NET Core 1.0 introduced DNX tooling. The RC2 release of .NET Core and ASP.NET Core 1.0 moved from DNX to the .NET Core CLI.

The majority of this post was written using .Net Core RC1.  BIG changes were made between versions RC 1 and RC 2.  Those are documented here.  The details in the following example are obsolete but the idea of incorporating multiple frameworks still exists.

Here is how project.json would look in an app relying on multiple frameworks

Capture.PNG

So as you can see, this give you a lot of flexibility.

  • Targeting older frameworks like dnx451 will be great porting over existing code and ensuring compatibility with other existing code or class libraries you may have build in the past.
  • Targeting the new dotnet5 or net core frameworks will let you take advantage of the new Core CLR. Thus setting you up with many new features as well as the ability to develop and run your apps on Windows, Linux, and OS/X!

Good luck!

Kendo UI Grid and AngularJS

Lets walk through some ways to set up a basic Kendo UI Grid with AngularJS. For a run down of more advanced Kend UI Grid properties, check out this post.

Ive been using Kendo UI on one of my more recent ASP.NET with AngularJS projects and I have been very happy with it.  They offer a wide variety of customizable controls, styles, and support, but the Control that I found most useful in their toolbox, and the one that makes this product worth it for me, is the Kendo Grid control.

There are alot of examples and documentation out there for this control, but I found it difficult to find a good example of how I envisioned utilizing it within our application.
– I wanted the grid to be reusable by different objects,for example a grid of teams and a grid of players.
– I needed it to have customizable rows and columns so that I can add buttons, checkboxes, images, and whatever else to the grid.
– I needed the grid to be de-coupled from any html elements. Mainly to be more DRY and to avoid the error message I describe below.

Many of the examples online do not meet those needs. Instead they direct you to create one similar to this

$("#gridName").kendoGrid({
              dataSource: exampleData,
              height: 550,
              groupable: true,
              sortable: true
          });

The problem: $(“#gridName”)
To us, this line is a design problem because it limits how this chunk of code can be re-used.
It also gives the browser a problem because the browser will throw an error if there is not a element with the name “gridName”.
So why not just name you grid or any other element? Well, what if i want to put 2 grids on one page? They both cannot have the same name, and with that, I loose the re-usability. Because of this I make it a point to never reference Element IDs and Element Names in my javascript, this ensures that there will be no “element does not exist” errors in my browser.

There are a few ways to solve this, but I will go over two of them here. In the end I ended up using example 2 in our application.

Example 1:

-Set your options and row template in the HTML
-Set your datasource in your angular controller

<kendo-grid k-data-source='kendoGridData'               
k-columns='[    
{ field: "Team_Name", title: "Team Name" },    
{ field: "Team_City", title: "City" },    
{ field: "Team_State", title: "State" }   ]'               
k-selectable="true"               
k-sortable="true"               
k-pageable="true"               
k-filterable="true">

<!--Row Template-->
<div k-row-template data-uid="#: Team_ID #">
<table>
<tr data-uid="#: uid #">
<td><a href="../teams/details/#: Team_Name #">#: Team_Name #</a></td>
<td>#: Team_City #</td>
<td>#: Team_State #</td>
</tr>
</table>
</div>

</kendo-grid>

And then you set kendoGridData in your AngularJS code like this

$scope.kendoGridData = [example data here.......]

Example 2:

-Minimize what you put in the html.
-Set your options, rows, and datasource in your angular controller.

The minimal HTML

<div kendo-grid k-options="kendoGridOptions" ></div>

Setting everything else using AngularJS

$scope.kendoGridOptions= {
    dataSource: [Example Data Source....],
    sortable: true,
    groupable: true,
    selectable: true,
    pageable: true,
    filterable: true,
    columnMenu: true,
    columns: [
                         {
                             field: "Team_Name",
                             title: "Name",
                             filterable: true,
                             template: "&amp;amp;lt;a href='#'&amp;amp;gt; #: Team_Name # &amp;amp;lt;/a&amp;amp;gt;",
                         },
                         { field: "Team_City", title: "City" },
                         { field: "Team_State", title: "State" }
    ]
};