Marcos Vainer Loeff

ASP.NET Core 2 with PI AF SDK: Part 1 - Introduction

Blog Post created by Marcos Vainer Loeff Employee on Jul 20, 2018

Introduction

 

After almost 4 years, it is time to rewrite/update my old ASP.NET MVC 5 blog post since the recommended Microsoft technology nowadays for web development is ASP.NET Core MVC 2.

 

But what is ASP.NET Core MVC?

 

According to this web page, the ASP.NET Core MVC framework is a lightweight, open source, highly testable presentation framework optimized for use with ASP.NET Core.

ASP.NET Core MVC provides a patterns-based way to build dynamic websites that enables a clean separation of concerns. It gives you full control over markup, supports TDD-friendly development and uses the latest web standards.

 

Can ASP.NET Core MVC be used together with PI AF SDK?

 

Since PI AF SDK is compiled against .NET Framework, one could argue that PI AF SDK is not compatible with ASP.NET Core since it was not compiled against .NET Core. Nevertheless, you can create an ASP.NET Core MVC project against .NET Core or .NET Framework. If you choose the second option, you can add PI AF SDK as a reference to your project.

 

Requirements

 

If you want to follow this blog post along, please make sure the following software are installed on your computer:

  • Visual Studio 2017 Update 3
  • PI AF SDK 2017 R2+

 

 

Source code package

You can have access to the source code package related to this blog post in this GitHub repository.

 

Creating the project

 

Let's see how this works. Open Visual Studio and create a new project from scratch. Select the Web item on the left pane and then "ASP.NET Core Web Application". Then write "ASPNETCoreWithAFSDKPar1"as the name of the project and click on the "Ok" button.

 

 

Figure 1 – Creating a new  ASP.NET Core MVC project in Visual Studio.

 

 

On the next window, make sure that ".NET Framework" and "ASP.NET Core 2.0" are selected. Next, select the Empty template and then click on “OK”. Figure 2 shows the screenshot for selecting the template. We have chosen the empty template instead of the MVC template because the last option not only comes with the MVC binaries but also with some Controllers, Views, Layouts and the ASP.NET Identity responsible for the authentication and authorization from your web site. As we are not going to use many of those default files, the Empty seemed to be a better option for me.

 

 

 

 

Figure 2 – Selecting the ASP.NET Core template.

 

If you don't see those options on this window, make sure you have an updated version of Visual Studio 2017.

 

Right click on Dependencies and then "Add Reference..". Browse to the PI AF SDK binary and add it to your project.

 

Figure 3 – Adding PI AF SDK to your project

 

Before we start coding, make sure the target framework is .NET Framework and not .NET Core. Right click on the project and select properties to verify this information.

 

Figure 4 – VS project properties

 

Add NuGet libraries

 

Open the ASPNETCoreWithAFSDKPart1.csproj file and update it with the following content.

 

<Project Sdk="Microsoft.NET.Sdk.Web">


  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>


  <ItemGroup>
    <Content Remove="bower.json" />
  </ItemGroup>


  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>


  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="2.0.3" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.3" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.3" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.2" />
    <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.2" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.3" />
  </ItemGroup>


  <ItemGroup>
    <Reference Include="OSIsoft.AFSDK">
      <HintPath>..\..\..\..\..\Program Files (x86)\PIPC\AF\PublicAssemblies\4.0\OSIsoft.AFSDK.dll</HintPath>
    </Reference>
  </ItemGroup>


  <ItemGroup>
    <Content Update="Views\Shared\_Layout.cshtml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
  </ItemGroup>


</Project>

 

Save and recompile this project. The missing libraries will be retrieved from the internet and will be added to your project automatically.

 

Configure the HTTP requests pipeline

 

Open the Startup.cs file and edit it according to the content below:

 

 public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();
            app.UseStatusCodePages();
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }
    }

 

This will make sure that:

  • MVC is enabled.
  • Static files are enabled.
  • Developer exception pages are shown if an exception is thrown (Don't use it on production).

 

Setting up Bower and adding Bootstrap

 

We are going to use bootstrap 3 to style our web site. Although there are better options nowaways, we are going to use bower to download bootstrap and jQuery. On the VS project root create two file: .bowerrc and bower.json.

 

.bowerrc

{
  "directory": "wwwroot/lib"
}

 

bower.json

 

{
  "name": "ASPNETCOreWithAFSDKPart1",
  "private": true,
  "dependencies": {
    "bootstrap": "3.3.7"
  }
}

 

The first file tells the system to paste the retrieved libraries on the wwwroot//lib folder. The second file has all the dependencies.

 

Open the command prompt and change directory to the VS project folder. Then run"bower install" to install Bootstrap 3.3.7 and jQuery (both are JavaScript libraries), according to the dependencies listed on the bower.json file.

 

Creating the Home Controller

 

Let's create a new folder called Controllers and our home controller (new file homeController.cs) with folowing code:

 

using System.Collections.Generic;
using System.Linq;
using ASPNETCoreWithAFSDKPart1.Models;
using Microsoft.AspNetCore.Mvc;
using OSIsoft.AF.PI;


namespace ASPNETCoreWithAFSDKPart1.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return this.RedirectToAction("Query");
        }


        public IActionResult Query()
        {
            return View();
        }


        public IActionResult Result(string pointNameQuery, string pointSourceQuery)
        {
            PIServer piServer = new PIServers()["MARC-PI2016"];
            piServer.Connect();


            PIPointQuery query1 = new PIPointQuery(PICommonPointAttributes.Tag, OSIsoft.AF.Search.AFSearchOperator.Equal, pointNameQuery);
            PIPointQuery query2 = new PIPointQuery(PICommonPointAttributes.PointSource, OSIsoft.AF.Search.AFSearchOperator.Equal, pointSourceQuery);
            IEnumerable<PIPoint> foundPoints = PIPoint.FindPIPoints(piServer, new PIPointQuery[] { query1, query2 });
            PIPointList pointList = new PIPointList(foundPoints.Take(1000));


            List<PIPointSnapshotModelView> pointSnapshotValueList = new List<PIPointSnapshotModelView>();
            foreach (PIPoint point in pointList)
            {
                pointSnapshotValueList.Add(new PIPointSnapshotModelView(point.Name.ToString(), point.CurrentValue()));
            }


            return View(pointSnapshotValueList.AsEnumerable());
        }
    }
}

 

When the web site starts, it will load the Index() action, which will be redirected to the Query() action. This action will display a page with a form. When the user submits the form, the Result action will be called. PI AF SDK will search for PI Points matching certain conditions with the help of PIPointQuery class. The results are converted to an IEnumerable<PIPointSnapshotModelView>.

 

 

Creating the Model

 

The model all has the information needed to display to the use (PI Point name, value and attribute). Please create a new file PIPointSnapshotModelView.cs in the Models folder. Create the Models folder if it doesn't exist.

 

using OSIsoft.AF.Asset;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;


namespace ASPNETCoreWithAFSDKPart1.Models
{
    public class PIPointSnapshotModelView
    {
        public string PointName { get; set; }
        public object Value { get; set; }
        public DateTime TimeStamp { get; set; }


        public PIPointSnapshotModelView(string pointName, AFValue afValue)
        {
            PointName = pointName;
            Value = afValue.Value;
            TimeStamp = afValue.Timestamp;
        }
    }
}

 

 

Creating the Shared View

 

Please create a new folder on the root called Views. Then create 3 files with the content below:

 

_ViewStart.cshtml

@{
    Layout = "_Layout";
}

 

 

_ViewImports.cshtml

@using  ASPNETCoreWithAFSDKPart1.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

 

Shared\_Layout.cshtml (don't forget to create the Views\Shared folder first!)

@model IEnumerable<ASPNETCoreWithAFSDKPart1.Models.PIPointSnapshotModelView>
@{
    Layout = null;
}


<!DOCTYPE html>


<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Results</title>
    <link href="~/lib/tether/dist/css/tether.css" rel="stylesheet" />
    <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
    <script src="~/lib/tether/dist/js/tether.js"></script>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

 

Notes:

  • _ViewStart file can be used to define common view code that you want to execute at the start of each View's rendering.
  • _ViewImports.cshtml serves one major purpose: to provide namespaces which can be used by all other views.
  • _Layout: is the master layout that will be used by Query.cshtml and Result.html.

 

Creating the Views

 

Now, we just need to create Query.cshtml and Result.cshtml to finish our application!

 

Query.cshtml


<div class="col-sm-8 col-sm-offset-2">
    <h1>My first ASP.NET Core MVC with PI AF SDK</h1>
    <br /><br />
    <h4>Search for PI Points and check its snapshots.</h4>
    <br /><br />
    <div class="container">
        <div class="row">
            <form asp-controller="Home" asp-action="Result" method="get" class="form-inline">
                <div class="form-group">
                    <label class="sr-only" for="name">Search PI Point: </label>
                    <input id="pointNameQuery" name="pointNameQuery"  placeholder="Point Name" class="form-control" />
                </div>
                <div class="form-group">
                    <label class="sr-only" for="inputfile">With this Point Source: </label>
                    <input id="pointSourceQuery" name="pointSourceQuery" placeholder="Point Source" class="form-control" />
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
        </div>
    </div>
</div>

 

 

Result.cshtml

 

@model IEnumerable<PIPointSnapshotModelView>






<div class="col-sm-8 col-sm-offset-2">
    <h1>My first ASP.NET Core MVC with PI AF SDK</h1>
    <br /><br />
    <table class="table">
        <tr>
            <th>PI Point</th>
            <th>Value</th>
            <th>Timestamp</th>
        </tr>
        @foreach (var pointSnapshotValue in Model)
            {
        <tr>
            <td>@pointSnapshotValue.PointName</td>
            <td>@pointSnapshotValue.Value.ToString()</td>
            <td>@pointSnapshotValue.TimeStamp.ToString()</td>
        </tr>
            }
    </table>
    <br />
    <center>
        <a asp-controller="Home" asp-action="Index" class="btn btn-primary">Make another search</a>
    </center>
</div>



 

 

Testing the web app

 

We have finished writing our ASP.NET Core MVC web application. It is time to test. When you run this web application on Visual Studio, you should see the Query page below.

 

 

Figure 5 – Screenshot of the Query page from our web application

 

Figure 6 shows a screenshot in case we want to find all PI Points which match the “sin*d” from any PI Point Source. After clicking on submit, it will show the table with the PI Points found on the Result page.

 

 

Figure 6 – Screenshot of the Result page from our web application

 

Note that the design of the page has improved using bootstrap adding only a few words to the View. The query string defines the input parameters so you can edit them directly on the uri. If you click on “Make another search” it should go back to the previous page.

 

Conclusions

If you are a PI Developer that needs to develop a web application on top of the PI System., ASP.NET Core MVC with PI AF SDK is a great option. Nevertheless, there are other options as well, which we are going to see on my upcoming blog posts. Stay tuned!

Outcomes