TargetFramework update,

reference updates and added tests for Viewer
This commit is contained in:
Mike Phares 2023-01-06 21:17:30 -07:00
parent 791724fdd4
commit f0c2140f93
82 changed files with 10187 additions and 1052 deletions

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System;
using System.IO;
@ -8,13 +8,13 @@ using System.IO;
namespace OI.Metrology.Archive.ApiControllers;
public class AttachmentsController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly IAttachmentsService _AttachmentsService;
private readonly IMetrologyRepository _MetrologyRepository;
public AttachmentsController(IMetrologyRepo repo, IAttachmentsService attachmentsService)
public AttachmentsController(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService)
{
_Repo = repo;
_AttachmentsService = attachmentsService;
_MetrologyRepository = metrologyRepository;
}
// this endpoint was created in hope that it would make retrieving attachments to display in OpenInsight easier
@ -27,7 +27,7 @@ public class AttachmentsController : Controller
string title,
string filename)
{
ToolType tt = _Repo.GetToolTypeByName(toolTypeName);
ToolType tt = _MetrologyRepository.GetToolTypeByName(toolTypeName);
bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);

View File

@ -1,17 +1,17 @@
using Microsoft.AspNetCore.Mvc;
namespace OI.Metrology.Archive.ApiContollers;
namespace OI.Metrology.Archive.ApiControllers;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using System.Text.Json;
// this controller is for the Awaiting Dispo functionality
public class AwaitingDispoController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly IMetrologyRepository _MetrologyRepository;
public AwaitingDispoController(IMetrologyRepo repo) => _Repo = repo;
public AwaitingDispoController(IMetrologyRepository metrologyRepository) => _MetrologyRepository = metrologyRepository;
// returns the data to show in the Awaiting Dispo grid
// marked no-cache, just-in-case since igniteUI automatically adds a query string parameter to prevent caching
@ -21,7 +21,7 @@ public class AwaitingDispoController : Controller
{
var r = new
{
Results = _Repo.GetAwaitingDispo()
Results = _MetrologyRepository.GetAwaitingDispo()
};
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
}
@ -30,7 +30,7 @@ public class AwaitingDispoController : Controller
[HttpPost("/api/awaitingdispo/markasreviewed")]
public IActionResult MarkAsReviewed([FromQuery] long headerid, [FromQuery] int tooltypeid)
{
_ = _Repo.UpdateReviewDate(tooltypeid, headerid, false);
_ = _MetrologyRepository.UpdateReviewDate(tooltypeid, headerid, false);
return Ok();
}
@ -38,7 +38,7 @@ public class AwaitingDispoController : Controller
[HttpPost("/api/awaitingdispo/markasawaiting")]
public IActionResult MarkAsAwaiting([FromQuery] long headerid, [FromQuery] int tooltypeid)
{
if (_Repo.UpdateReviewDate(tooltypeid, headerid, true) <= 1)
if (_MetrologyRepository.UpdateReviewDate(tooltypeid, headerid, true) <= 1)
return Ok();
else
return StatusCode(444);

View File

@ -4,30 +4,30 @@ using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OI.Metrology.Archive.ApiContollers;
namespace OI.Metrology.Archive.ApiControllers;
[ApiController]
public class InboundController : ControllerBase
{
private readonly ILogger _Logger;
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IAttachmentsService _AttachmentService;
private readonly IInboundDataService _InboundDataService;
private readonly IMetrologyRepository _MetrologyRepository;
public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepo repo, IInboundDataService inboundDataService, IAttachmentsService attachmentService)
public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepository metrologyRepository, IInboundDataService inboundDataService, IAttachmentsService attachmentService)
{
_Repo = repo;
_Logger = logger;
_AppSettings = appSettings;
_AttachmentService = attachmentService;
_InboundDataService = inboundDataService;
_MetrologyRepository = metrologyRepository;
}
// this class represents the API response back to the client
@ -61,9 +61,9 @@ public class InboundController : ControllerBase
return Unauthorized(r);
}
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
ToolType toolType = _MetrologyRepository.GetToolTypeByName(tooltype);
if (toolType == null)
if (toolType is null)
{
r.Errors.Add("Invalid tool type: " + tooltype);
return BadRequest(r);
@ -71,9 +71,9 @@ public class InboundController : ControllerBase
// get metadata
List<ToolTypeMetadata> metaData = _Repo.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
List<ToolTypeMetadata> metaData = _MetrologyRepository.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
if (metaData == null)
if (metaData is null)
{
r.Errors.Add("Invalid metadata for tool type: " + tooltype);
return BadRequest(r);
@ -81,7 +81,7 @@ public class InboundController : ControllerBase
// validate fields
if (jsonbody != null)
if (jsonbody is not null)
_InboundDataService.ValidateJSONFields(jsonbody, 0, metaData, r.Errors, r.Warnings);
else
r.Errors.Add("Invalid json");
@ -118,12 +118,12 @@ public class InboundController : ControllerBase
return Unauthorized("Remote IP is not on allowed list");
}
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
ToolType toolType = _MetrologyRepository.GetToolTypeByName(tooltype);
if (toolType == null)
if (toolType is null)
return BadRequest($"Invalid tool type: {tooltype}");
if (Request.Form == null)
if (Request.Form is null)
return BadRequest($"Invalid form");
if (Request.Form.Files.Count != 1)

View File

@ -1,22 +1,22 @@
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace OI.Metrology.Archive.ApiContollers;
namespace OI.Metrology.Archive.ApiControllers;
using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using System.Text.Json;
public class ReactorsController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IMetrologyRepository _MetrologyRepository;
public ReactorsController(AppSettings appSettings, IMetrologyRepo repo)
public ReactorsController(AppSettings appSettings, IMetrologyRepository metrologyRepository)
{
_Repo = repo;
_AppSettings = appSettings;
_MetrologyRepository = metrologyRepository;
}
private static int[] EvenReactors()

View File

@ -4,11 +4,11 @@ using System;
using System.IO;
using System.Linq;
namespace OI.Metrology.Archive.ApiContollers;
namespace OI.Metrology.Archive.ApiControllers;
using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System.Collections.Generic;
using System.Text.Json;
@ -21,15 +21,15 @@ public class ToolTypesController : Controller
// it is named after the /api/tooltypes prefix
// the URL pattern is RESTful and the tool type is the root of every request
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IAttachmentsService _AttachmentsService;
private readonly IMetrologyRepository _MetrologyRepository;
public ToolTypesController(AppSettings appSettings, IMetrologyRepo repo, IAttachmentsService attachmentsService)
public ToolTypesController(AppSettings appSettings, IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService)
{
_Repo = repo;
_AppSettings = appSettings;
_AttachmentsService = attachmentsService;
_MetrologyRepository = metrologyRepository;
}
// Get a list of tooltypes, returns just Name and ID
@ -38,7 +38,7 @@ public class ToolTypesController : Controller
{
var r = new
{
Results = _Repo.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID })
Results = _MetrologyRepository.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID })
};
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
}
@ -48,8 +48,8 @@ public class ToolTypesController : Controller
[HttpGet("/api/tooltypes/{id}")]
public IActionResult GetToolTypeMetadata(int id, string sortby = "")
{
ToolType tt = _Repo.GetToolTypeByID(id);
IEnumerable<ToolTypeMetadata> md = _Repo.GetToolTypeMetadataByToolTypeID(id);
ToolType tt = _MetrologyRepository.GetToolTypeByID(id);
IEnumerable<ToolTypeMetadata> md = _MetrologyRepository.GetToolTypeMetadataByToolTypeID(id);
if (string.Equals(sortby, "grid", StringComparison.OrdinalIgnoreCase))
md = md.OrderBy(f => f.GridDisplayOrder).ToList();
@ -80,7 +80,7 @@ public class ToolTypesController : Controller
{
long totalRecs;
System.Data.DataTable dt = _Repo.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs);
System.Data.DataTable dt = _MetrologyRepository.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs);
var r = new
{
@ -101,7 +101,7 @@ public class ToolTypesController : Controller
{
long totalRecs;
IEnumerable<HeaderCommon> dt = _Repo.GetHeaderTitles(id, page, pagesize, out totalRecs);
IEnumerable<HeaderCommon> dt = _MetrologyRepository.GetHeaderTitles(id, page, pagesize, out totalRecs);
var r = new
{
@ -121,7 +121,7 @@ public class ToolTypesController : Controller
{
var r = new
{
Results = _Repo.GetHeaderFields(id, headerid).Select(x => new { Column = x.Key, x.Value }).ToList()
Results = _MetrologyRepository.GetHeaderFields(id, headerid).Select(x => new { Column = x.Key, x.Value }).ToList()
};
string json = JsonConvert.SerializeObject(r);
@ -137,7 +137,7 @@ public class ToolTypesController : Controller
var r = new
{
Results = _Repo.GetDataSharePoint(id, title)
Results = _MetrologyRepository.GetDataSharePoint(id, title)
};
string json = JsonConvert.SerializeObject(r);
@ -152,7 +152,7 @@ public class ToolTypesController : Controller
var r = new
{
Results = _Repo.GetData(id, headerid)
Results = _MetrologyRepository.GetData(id, headerid)
};
string json = JsonConvert.SerializeObject(r);
@ -168,7 +168,7 @@ public class ToolTypesController : Controller
string filename)
{
ToolType tt = _Repo.GetToolTypeByID(toolTypeId);
ToolType tt = _MetrologyRepository.GetToolTypeByID(toolTypeId);
bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);
@ -191,7 +191,7 @@ public class ToolTypesController : Controller
public IActionResult OIExport(int toolTypeId, long headerid)
{
// Call the export stored procedure
System.Data.DataSet ds = _Repo.GetOIExportData(toolTypeId, headerid);
System.Data.DataSet ds = _MetrologyRepository.GetOIExportData(toolTypeId, headerid);
try
{
@ -213,7 +213,7 @@ public class ToolTypesController : Controller
foreach (object o in ds.Tables[1].Rows[0].ItemArray)
{
if ((o != null) && (!Convert.IsDBNull(o)))
if ((o is not null) && (!Convert.IsDBNull(o)))
_ = sb.Append(Convert.ToString(o));
_ = sb.Append('\t');
}
@ -223,7 +223,7 @@ public class ToolTypesController : Controller
{
foreach (object o in dr.ItemArray)
{
if ((o != null) && (!Convert.IsDBNull(o)))
if ((o is not null) && (!Convert.IsDBNull(o)))
_ = sb.Append(Convert.ToString(o));
_ = sb.Append('\t');
}

View File

@ -15,7 +15,7 @@ public class ErrorHandlerController : Controller
public IActionResult Index()
{
IExceptionHandlerFeature error = HttpContext.Features.Get<IExceptionHandlerFeature>();
if (error == null)
if (error is null)
{
return Redirect("~/");
}
@ -24,7 +24,7 @@ public class ErrorHandlerController : Controller
_Logger.LogError("Unhandled exception: " + error.Error.ToString());
dynamic r = new
{
Message = error.Error == null ? "Error" : error.Error.Message
Message = error.Error is null ? "Error" : error.Error.Message
};
return StatusCode(StatusCodes.Status500InternalServerError, r);
}

View File

@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.ViewModels;
using System;
using System.Collections.Generic;
@ -17,14 +17,14 @@ public class ExportController : Controller
{
private readonly ILogger _Logger;
private readonly bool _IsTestDatabase;
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IMetrologyRepository _MetrologyRepository;
public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepo repo)
public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepository metrologyRepository)
{
_Repo = repo;
_Logger = logger;
_AppSettings = appSettings;
_MetrologyRepository = metrologyRepository;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -60,7 +60,7 @@ public class ExportController : Controller
{
if (model.StartTime > model.EndTime)
ModelState.AddModelError("EndTime", "End time must be after start time");
IEnumerable<ToolType> toolTypes = _Repo.GetToolTypes();
IEnumerable<ToolType> toolTypes = _MetrologyRepository.GetToolTypes();
toolType = toolTypes.Where(tt => tt.ID.ToString() == model.ToolType).SingleOrDefault();
if (toolType is null)
ModelState.AddModelError("ToolType", "Invalid selection");
@ -94,7 +94,7 @@ public class ExportController : Controller
string fileName = string.Format("Export_{0}_{1:yyyyMMddHHmm}_to_{2:yyyyMMddHHmm}.csv", toolTypeName, startTime, endTime);
StringBuilder sb = new();
System.Data.DataTable dt = _Repo.ExportData(spName, startTime, endTime);
System.Data.DataTable dt = _MetrologyRepository.ExportData(spName, startTime, endTime);
_ = sb.AppendLine(GetColumnHeaders(dt));

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.ViewModels;
using System;
@ -13,12 +14,12 @@ public class PagesController : Controller
{
private readonly bool _IsTestDatabase;
private readonly IRdsMaxRepo _RdsMaxRepo;
private readonly IMetrologyRepo _MetrologyRepo;
private readonly IMetrologyRepository _MetrologyRepo;
public PagesController(AppSettings appSettings, IMetrologyRepo metrologyRepo, IRdsMaxRepo rdsMaxRepo)
public PagesController(AppSettings appSettings, IMetrologyRepository metrologyRepository, IRdsMaxRepo rdsMaxRepo)
{
_RdsMaxRepo = rdsMaxRepo;
_MetrologyRepo = metrologyRepo;
_MetrologyRepo = metrologyRepository;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}

View File

@ -1,61 +1,24 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace OI.Metrology.Archive.Models;
public class AppSettings
public record AppSettings(string ApiLoggingContentTypes,
string ApiLoggingPathPrefixes,
string ApiLogPath,
string AttachmentPath,
string BuildNumber,
string Company,
string ConnectionString,
string GitCommitSeven,
string InboundApiAllowedIPList,
string MonAResource,
string MonASite,
string Oi2SqlConnectionString,
string OIExportPath,
string URLs,
string WorkingDirectoryName)
{
public string ApiLoggingContentTypes { init; get; }
public string ApiLoggingPathPrefixes { init; get; }
public string ApiLogPath { init; get; }
public string AttachmentPath { init; get; }
public string BuildNumber { init; get; }
public string Company { init; get; }
public string ConnectionString { init; get; }
public string GitCommitSeven { init; get; }
public string InboundApiAllowedIPList { init; get; }
public string MonAResource { init; get; }
public string MonASite { init; get; }
public string OIExportPath { init; get; }
public string Oi2SqlConnectionString { init; get; }
public string URLs { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string apiLoggingContentTypes,
string apiLoggingPathPrefixes,
string apiLogPath,
string attachmentPath,
string buildNumber,
string company,
string connectionString,
string gitCommitSeven,
string inboundApiAllowedIPList,
string monAResource,
string monASite,
string oi2SqlConnectionString,
string oiExportPath,
string urls,
string workingDirectoryName)
{
ApiLoggingContentTypes = apiLoggingContentTypes;
ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
ApiLogPath = apiLogPath;
AttachmentPath = attachmentPath;
BuildNumber = buildNumber;
Company = company;
ConnectionString = connectionString;
GitCommitSeven = gitCommitSeven;
InboundApiAllowedIPList = inboundApiAllowedIPList;
MonAResource = monAResource;
MonASite = monASite;
Oi2SqlConnectionString = oi2SqlConnectionString;
OIExportPath = oiExportPath;
URLs = urls;
WorkingDirectoryName = workingDirectoryName;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });

View File

@ -37,6 +37,8 @@ public class AppSettings
private static Models.AppSettings Get(AppSettings appSettings)
{
Models.AppSettings result;
if (appSettings is null)
throw new NullReferenceException(nameof(appSettings));
if (appSettings.ApiLoggingContentTypes is null)
throw new NullReferenceException(nameof(ApiLoggingContentTypes));
if (appSettings.ApiLoggingPathPrefixes is null)

View File

@ -12,7 +12,7 @@
<Nullable>disable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="Tests" />
@ -29,22 +29,22 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="jQuery" Version="3.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="jQuery" Version="3.6.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="Serilog.AspNetCore.Ingestion" Version="1.0.0-dev-00032" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.4" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj" />
<ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="moves\" />

View File

@ -9,6 +9,7 @@ using OI.Metrology.Archive.Models;
using OI.Metrology.Archive.Repositories;
using OI.Metrology.Archive.Services;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Services;
using Serilog;
@ -65,13 +66,13 @@ public class Program
{
_ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
_ = webApplicationBuilder.Services.AddControllersWithViews();
_ = new MetrologyRepo(new SQLDbConnectionFactory(_AppSettings), null);
_ = new MetrologyRepository(new SQLDbConnectionFactory(_AppSettings), null);
_ = webApplicationBuilder.Services.AddDistributedMemoryCache();
_ = webApplicationBuilder.Services.AddMemoryCache();
_ = webApplicationBuilder.Services.AddSingleton<AppSettings, AppSettings>(_ => _AppSettings);
_ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
_ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
_ = webApplicationBuilder.Services.AddScoped<IMetrologyRepo, MetrologyRepo>();
_ = webApplicationBuilder.Services.AddScoped<IMetrologyRepository, MetrologyRepository>();
_ = webApplicationBuilder.Services.AddScoped<IRdsMaxRepo, RdsMaxRepo>();
_ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>();
_ = webApplicationBuilder.Services.AddSwaggerGen();
@ -87,8 +88,10 @@ public class Program
_ = webApplicationBuilder.Services.AddSingleton<IHostLifetime, WindowsServiceLifetime>();
_ = webApplicationBuilder.Logging.AddEventLog(settings =>
{
#pragma warning disable CA1416
if (string.IsNullOrEmpty(settings.SourceName))
settings.SourceName = webApplicationBuilder.Environment.ApplicationName;
#pragma warning restore
});
}
WebApplication webApplication = webApplicationBuilder.Build();

View File

@ -2,6 +2,7 @@
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using System;
using System.Collections.Generic;
@ -12,12 +13,12 @@ using System.Transactions;
namespace OI.Metrology.Archive.Repositories;
public class MetrologyRepo : IMetrologyRepo
public class MetrologyRepository : IMetrologyRepository
{
private readonly IDbConnectionFactory _DBConnectionFactory;
private readonly IMemoryCache _Cache;
public MetrologyRepo(IDbConnectionFactory dbConnectionFactory, IMemoryCache memoryCache)
public MetrologyRepository(IDbConnectionFactory dbConnectionFactory, IMemoryCache memoryCache)
{
_DBConnectionFactory = dbConnectionFactory;
_Cache = memoryCache;
@ -136,10 +137,10 @@ public class MetrologyRepo : IMetrologyRepo
// build field map
foreach (ToolTypeMetadata f in fields)
{
if ((f.ApiName != null) && f.ApiName.Contains('\\'))
if ((f.ApiName is not null) && f.ApiName.Contains('\\'))
{
string n = f.ApiName.Split('\\')[0].Trim().ToUpper();
if (containerField == null)
if (containerField is null)
containerField = n;
else if (!string.Equals(containerField, n))
throw new Exception("Only one container field is allowed");
@ -153,7 +154,7 @@ public class MetrologyRepo : IMetrologyRepo
}
}
if (containerField == null)
if (containerField is null)
{
// No container field, just insert a single row
@ -164,7 +165,7 @@ public class MetrologyRepo : IMetrologyRepo
// Find the container field in the json
JProperty contJP = jsonrow.Children<JProperty>().Where(c => string.Equals(c.Name.Trim(), containerField, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
if ((contJP != null) && (contJP.Value is JArray array))
if ((contJP is not null) && (contJP.Value is JArray array))
{
JArray contRows = array;
@ -233,7 +234,7 @@ public class MetrologyRepo : IMetrologyRepo
}
}
if ((containerrow != null) && (containerFieldmap != null))
if ((containerrow is not null) && (containerFieldmap is not null))
{
foreach (JProperty jp in containerrow.Children<JProperty>())
@ -264,7 +265,7 @@ public class MetrologyRepo : IMetrologyRepo
cmd.CommandText = columns.TrimEnd(',') + parms.TrimEnd(',') + ";SELECT SCOPE_IDENTITY();";
object o = cmd.ExecuteScalar();
if ((o == null) || Convert.IsDBNull(o))
if ((o is null) || Convert.IsDBNull(o))
throw new Exception("Unexpected query result");
return Convert.ToInt64(o);
}
@ -304,7 +305,7 @@ public class MetrologyRepo : IMetrologyRepo
{
if (!firstField)
_ = sb.Append(',');
if (f.GridAttributes != null && f.GridAttributes.Contains("isNull"))
if (f.GridAttributes is not null && f.GridAttributes.Contains("isNull"))
{
_ = sb.AppendFormat("{0}", "ISNULL(" + f.ColumnName + ", '')[" + f.ColumnName + "]");
}
@ -322,11 +323,11 @@ public class MetrologyRepo : IMetrologyRepo
public DataTable GetHeaders(int toolTypeId, DateTime? startTime, DateTime? endTime, int? pageNo, int? pageSize, long? headerId, out long totalRecords)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
DataTable dt = new();
@ -418,11 +419,11 @@ public class MetrologyRepo : IMetrologyRepo
public DataTable GetData(int toolTypeId, long headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
DataTable dt = new();
@ -529,11 +530,11 @@ public class MetrologyRepo : IMetrologyRepo
public DataTable GetDataSharePoint(int toolTypeId, string headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
DataTable dt = new();
@ -624,7 +625,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetHeaderAttachmentID(int toolTypeId, long headerId)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -637,7 +638,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetDataAttachmentID(int toolTypeId, long headerId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -656,7 +657,7 @@ public class MetrologyRepo : IMetrologyRepo
public DataSet GetOIExportData(int toolTypeId, long headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
if (string.IsNullOrWhiteSpace(tt.OIExportSPName))
@ -685,7 +686,7 @@ public class MetrologyRepo : IMetrologyRepo
public IEnumerable<HeaderCommon> GetHeaderTitles(int toolTypeId, int? pageNo, int? pageSize, out long totalRecords)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
DbConnection conn = GetDbConnection();
@ -717,11 +718,11 @@ public class MetrologyRepo : IMetrologyRepo
public IEnumerable<KeyValuePair<string, string>> GetHeaderFields(int toolTypeId, long headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
List<KeyValuePair<string, string>> r = new();
@ -749,10 +750,10 @@ public class MetrologyRepo : IMetrologyRepo
foreach (ToolTypeMetadata m in md.Where(m => m.Header == true && m.TableDisplayOrder > 0).OrderBy(m => m.TableDisplayOrder))
{
string v = "";
if (dr != null)
if (dr is not null)
{
object o = dr[m.ColumnName];
if (o != null && !Convert.IsDBNull(o))
if (o is not null && !Convert.IsDBNull(o))
v = Convert.ToString(o);
}
KeyValuePair<string, string> kvp = new(m.DisplayTitle, v);
@ -771,7 +772,7 @@ public class MetrologyRepo : IMetrologyRepo
public int UpdateReviewDate(int toolTypeId, long headerId, bool clearDate)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -792,7 +793,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetHeaderAttachmentIDByTitle(int toolTypeId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -804,7 +805,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetDataAttachmentIDByTitle(int toolTypeId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -813,8 +814,8 @@ public class MetrologyRepo : IMetrologyRepo
return conn.ExecuteScalar<Guid>(sql, param: new { Title = title });
}
string IMetrologyRepo.GetHeaderInsertDate(int toolTypeId, long headerId) => throw new NotImplementedException();
void IMetrologyRepo.SetHeaderDirName(string tableName, long headerId, string dateDir) => throw new NotImplementedException();
string IMetrologyRepo.GetDataInsertDate(int toolTypeId, long headerId, string title) => throw new NotImplementedException();
void IMetrologyRepo.SetDataDirName(string tableName, long headerId, string title, string dateDir) => throw new NotImplementedException();
string IMetrologyRepository.GetHeaderInsertDate(int toolTypeId, long headerId) => throw new NotImplementedException();
void IMetrologyRepository.SetHeaderDirName(string tableName, long headerId, string dateDir) => throw new NotImplementedException();
string IMetrologyRepository.GetDataInsertDate(int toolTypeId, long headerId, string title) => throw new NotImplementedException();
void IMetrologyRepository.SetDataDirName(string tableName, long headerId, string title, string dateDir) => throw new NotImplementedException();
}

View File

@ -6,27 +6,27 @@ namespace OI.Metrology.Archive.Services;
using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System.Data.SqlClient;
public class AttachmentsService : IAttachmentsService
{
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IMetrologyRepository _MetrologyRepository;
public AttachmentsService(AppSettings appSettings, IMetrologyRepo repo)
public AttachmentsService(AppSettings appSettings, IMetrologyRepository metrologyRepository)
{
_Repo = repo;
_AppSettings = appSettings;
_MetrologyRepository = metrologyRepository;
}
protected Stream GetAttachmentStream(string tableName, Guid attachmentId, string filename)
{
if (attachmentId.Equals(Guid.Empty))
throw new Exception("No attachments found");
DateTime insertDate = Convert.ToDateTime(_Repo.GetAttachmentInsertDateByGUID(tableName, attachmentId));
DateTime insertDate = Convert.ToDateTime(_MetrologyRepository.GetAttachmentInsertDateByGUID(tableName, attachmentId));
int year = insertDate.Year;
DateTime d = insertDate;
CultureInfo cul = CultureInfo.CurrentCulture;
@ -63,7 +63,7 @@ public class AttachmentsService : IAttachmentsService
public Stream GetAttachmentStreamByTitle(ToolType toolType, bool header, string title, string filename)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
string queryString = "SELECT * FROM " + toolType.DataTableName + " WHERE AttachmentId = @attachmentId";
@ -103,19 +103,19 @@ public class AttachmentsService : IAttachmentsService
if (header)
{
tableName = toolType.HeaderTableName;
attachmentId = _Repo.GetHeaderAttachmentIDByTitle(toolType.ID, title);
attachmentId = _MetrologyRepository.GetHeaderAttachmentIDByTitle(toolType.ID, title);
}
else
{
tableName = toolType.DataTableName;
attachmentId = _Repo.GetDataAttachmentIDByTitle(toolType.ID, title);
attachmentId = _MetrologyRepository.GetDataAttachmentIDByTitle(toolType.ID, title);
}
return GetAttachmentStream(tableName, attachmentId, filename);
}
public Stream GetAttachmentStreamByAttachmentId(ToolType toolType, bool header, Guid attachmentId, string filename)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
string tableName;
if (header)
@ -126,7 +126,7 @@ public class AttachmentsService : IAttachmentsService
}
public Stream GetAttachmentStreamByAttachmentIdArchive(ToolType toolType, bool header, Guid attachmentId, string filename)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
string tableName;
if (header)
@ -139,21 +139,21 @@ public class AttachmentsService : IAttachmentsService
private void SaveAttachment(ToolType toolType, long headerId, string dataUniqueId, string filename, Microsoft.AspNetCore.Http.IFormFile uploadedFile)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
using System.Transactions.TransactionScope trans = _Repo.StartTransaction();
using System.Transactions.TransactionScope trans = _MetrologyRepository.StartTransaction();
Guid attachmentId = Guid.Empty;
string tableName = "";
if (string.IsNullOrWhiteSpace(dataUniqueId))
{
attachmentId = _Repo.GetHeaderAttachmentID(toolType.ID, headerId);
attachmentId = _MetrologyRepository.GetHeaderAttachmentID(toolType.ID, headerId);
tableName = toolType.HeaderTableName;
}
else
{
attachmentId = _Repo.GetDataAttachmentID(toolType.ID, headerId, dataUniqueId);
attachmentId = _MetrologyRepository.GetDataAttachmentID(toolType.ID, headerId, dataUniqueId);
tableName = toolType.DataTableName;
}
if (Equals(attachmentId, Guid.Empty))

View File

@ -1,6 +1,6 @@
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System;
using System.Collections.Generic;
@ -10,9 +10,9 @@ namespace OI.Metrology.Archive.Services;
public class InboundDataService : IInboundDataService
{
private readonly IMetrologyRepo _Repo;
private readonly IMetrologyRepository _MetrologyRepository;
public InboundDataService(IMetrologyRepo repo) => _Repo = repo;
public InboundDataService(IMetrologyRepository metrologyRepository) => _MetrologyRepository = metrologyRepository;
public long DoSQLInsert(JToken jsonbody, ToolType toolType, List<ToolTypeMetadata> metaData)
{
@ -37,11 +37,11 @@ public class InboundDataService : IInboundDataService
long headerId = 0;
using (System.Transactions.TransactionScope transScope = _Repo.StartTransaction())
using (System.Transactions.TransactionScope transScope = _MetrologyRepository.StartTransaction())
{
try
{
_Repo.PurgeExistingData(toolType.ID, uniqueId);
_MetrologyRepository.PurgeExistingData(toolType.ID, uniqueId);
}
catch (Exception ex)
{
@ -50,7 +50,7 @@ public class InboundDataService : IInboundDataService
try
{
headerId = _Repo.InsertToolDataJSON(jsonbody, -1, metaData, toolType.HeaderTableName);
headerId = _MetrologyRepository.InsertToolDataJSON(jsonbody, -1, metaData, toolType.HeaderTableName);
}
catch (Exception ex)
{
@ -60,11 +60,11 @@ public class InboundDataService : IInboundDataService
int detailrow = 1;
try
{
if (detailsArray != null)
if (detailsArray is not null)
{
foreach (JToken detail in detailsArray)
{
_ = _Repo.InsertToolDataJSON(detail, headerId, metaData, toolType.DataTableName);
_ = _MetrologyRepository.InsertToolDataJSON(detail, headerId, metaData, toolType.DataTableName);
detailrow += 1;
}
}
@ -133,7 +133,7 @@ public class InboundDataService : IInboundDataService
if (jp.First is JArray array)
detailsArray = array;
else if ((jp.First is JValue value) && (value.Value == null))
else if ((jp.First is JValue value) && (value.Value is null))
detailsArray = null;
else
errors.Add("Invalid details field");
@ -169,7 +169,7 @@ public class InboundDataService : IInboundDataService
}
// if a Details container if found, process it by recursion
if (detailsArray != null)
if (detailsArray is not null)
{
int i = 1;
foreach (JToken detail in detailsArray)
@ -189,7 +189,7 @@ public class InboundDataService : IInboundDataService
{
// get the json data for this container field, ex: Points
JProperty contJP = jsonbody.Children<JProperty>().Where(jp => string.Equals(jp.Name, containerField, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
if ((contJP != null) && (contJP.Value is JArray array))
if ((contJP is not null) && (contJP.Value is JArray array))
{
JArray contJPArray = array;

View File

@ -3,13 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archive", "Archive\Archive.csproj", "{D02BA20E-0ACE-4D1C-9132-90773AF3CF5A}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archive", "Archive\OI.Metrology.Archive.csproj", "{D02BA20E-0ACE-4D1C-9132-90773AF3CF5A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{A807EAE3-7DCB-4E5E-BE54-0D7410D18B3E}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\OI.Metrology.Shared.csproj", "{A807EAE3-7DCB-4E5E-BE54-0D7410D18B3E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Viewer", "Viewer\Viewer.csproj", "{25C86DF8-EC1A-4D4B-AD4E-6561174824B9}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Viewer", "Viewer\OI.Metrology.Viewer.csproj", "{25C86DF8-EC1A-4D4B-AD4E-6561174824B9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{B67FB8C4-402E-4D53-90A6-90F6FDB9D082}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\OI.Metrology.Tests.csproj", "{B67FB8C4-402E-4D53-90A6-90F6FDB9D082}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -10,7 +10,7 @@ public class ExtWebClient : WebClient
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest webRequest = base.GetWebRequest(address);
if (webRequest != null)
if (webRequest is not null)
webRequest.PreAuthenticate = PreAuthenticate;
return webRequest;
}

View File

@ -0,0 +1,7 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record AdditionalData(
[property: JsonPropertyName("ServiceId")] string ServiceId
);

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record AllowedActions(
[property: JsonPropertyName("Incident")] bool Incident,
[property: JsonPropertyName("Accept")] bool Accept,
[property: JsonPropertyName("Reorder")] bool Reorder
);

18
Shared/Models/Booking.cs Normal file
View File

@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record Booking(
[property: JsonPropertyName("Catalog")] Catalog Catalog,
[property: JsonPropertyName("Name")] string Name,
[property: JsonPropertyName("Description")] string Description,
[property: JsonPropertyName("PaymentMethod")] int PaymentMethod,
[property: JsonPropertyName("Service")] Service Service,
[property: JsonPropertyName("Order")] Order Order,
[property: JsonPropertyName("ApprovalStatus")] int ApprovalStatus,
[property: JsonPropertyName("AllowedActions")] AllowedActions AllowedActions,
[property: JsonPropertyName("ObjectId")] string ObjectId,
[property: JsonPropertyName("Id")] string Id,
[property: JsonPropertyName("Quantity")] int Quantity,
[property: JsonPropertyName("AdditionalData")] AdditionalData AdditionalData
);

9
Shared/Models/Catalog.cs Normal file
View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record Catalog(
[property: JsonPropertyName("Id")] string Id,
[property: JsonPropertyName("Name")] string Name,
[property: JsonPropertyName("CurrencyCode")] string CurrencyCode
);

View File

@ -0,0 +1,19 @@
namespace OI.Metrology.Shared.Models;
public class DataResponse
{
public bool Success { get; set; }
public long HeaderID { get; set; }
public List<string> Errors { get; set; }
public List<string> Warnings { get; set; }
public DataResponse()
{
HeaderID = -1;
Success = false;
Errors = new List<string>();
Warnings = new List<string>();
}
}

26
Shared/Models/Order.cs Normal file
View File

@ -0,0 +1,26 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record Order(
[property: JsonPropertyName("Bookings")] IReadOnlyList<Booking> Bookings,
[property: JsonPropertyName("AllowedActions")] AllowedActions AllowedActions,
[property: JsonPropertyName("Id")] string Id,
[property: JsonPropertyName("ObjectId")] string ObjectId,
[property: JsonPropertyName("Name")] string Name,
[property: JsonPropertyName("Type")] string Type,
[property: JsonPropertyName("TypeId")] int TypeId,
[property: JsonPropertyName("State")] string State,
[property: JsonPropertyName("StateId")] int StateId,
[property: JsonPropertyName("StateIcon")] string StateIcon,
[property: JsonPropertyName("StateColor")] string StateColor,
[property: JsonPropertyName("ItemNumber")] string ItemNumber,
[property: JsonPropertyName("CreatedDate")] DateTime CreatedDate,
[property: JsonPropertyName("DecidedDate")] DateTime DecidedDate,
[property: JsonPropertyName("CostCenterId")] string CostCenterId,
[property: JsonPropertyName("CostCenterName")] string CostCenterName,
[property: JsonPropertyName("Recipient")] string Recipient,
[property: JsonPropertyName("RecipientId")] string RecipientId,
[property: JsonPropertyName("Requestor")] string Requestor,
[property: JsonPropertyName("RequestorId")] string RequestorId
);

7
Shared/Models/Price.cs Normal file
View File

@ -0,0 +1,7 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record Price(
[property: JsonPropertyName("CC")] string CC
);

20
Shared/Models/Service.cs Normal file
View File

@ -0,0 +1,20 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record Service(
[property: JsonPropertyName("Id")] string Id,
[property: JsonPropertyName("Quantity")] int Quantity,
[property: JsonPropertyName("PaymentMethod")] int PaymentMethod,
[property: JsonPropertyName("Price")] Price Price,
[property: JsonPropertyName("ObjectId")] string ObjectId,
[property: JsonPropertyName("ConfigurationItemType")] int ConfigurationItemType,
[property: JsonPropertyName("ConfigurationItemTypeName")] string ConfigurationItemTypeName,
[property: JsonPropertyName("ServiceType")] int ServiceType,
[property: JsonPropertyName("CustomFormEntityId")] string CustomFormEntityId,
[property: JsonPropertyName("CustomFormEntityName")] string CustomFormEntityName,
[property: JsonPropertyName("CreateMultipleBookings")] bool CreateMultipleBookings,
[property: JsonPropertyName("AllowIdenticalInstances")] bool AllowIdenticalInstances,
[property: JsonPropertyName("Catalog")] Catalog Catalog,
[property: JsonPropertyName("UninstallationMode")] int? UninstallationMode
);

View File

@ -0,0 +1,8 @@
using System.Text.Json.Serialization;
namespace OI.Metrology.Shared.Models;
public record ServiceShop(
[property: JsonPropertyName("Orders")] IReadOnlyList<Order> Orders,
[property: JsonPropertyName("Total")] int Total
);

View File

@ -0,0 +1,15 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IAppSettingsController<T>
{
enum Action : int
{
App = 0,
DevOps = 1
}
static string GetRouteName() => nameof(IAppSettingsController<T>)[1..^10];
T GetAppSettings();
}

View File

@ -0,0 +1,9 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IAppSettingsRepository
{
List<string> GetAppSettings();
string GetBuildNumberAndGitCommitSeven();
}

View File

@ -0,0 +1,16 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IClientSettingsController<T>
{
enum Action : int
{
Client = 0,
IP = 1
}
static string GetRouteName() => nameof(IClientSettingsController<T>)[1..^10];
T GetClientSettings();
T GetIpAddress();
}

View File

@ -0,0 +1,11 @@
using System.Net;
namespace OI.Metrology.Shared.Models.Stateless;
public interface IClientSettingsRepository
{
List<string> GetClientSettings(IPAddress? remoteIpAddress);
string GetIpAddress(IPAddress? remoteIpAddress);
}

View File

@ -0,0 +1,17 @@
using Newtonsoft.Json.Linq;
namespace OI.Metrology.Shared.Models.Stateless;
public interface IInboundController<T>
{
enum Action : int
{
Index = 0
}
static string GetRouteName() => nameof(IInboundController<T>)[1..^10];
T Data(string tooltype, JToken jsonbody);
T AttachFile(string tooltype, long headerid, string datauniqueid = "");
}

View File

@ -0,0 +1,14 @@
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.Services;
using System.Net;
namespace OI.Metrology.Shared.Models.Stateless;
public interface IInboundRepository
{
bool IsIPAddressAllowed(string inboundApiAllowedIPList, IPAddress? remoteIP);
DataResponse Data(IMetrologyRepository metrologyRepository, IInboundDataService inboundDataService, string tooltype, JToken jsonbody);
string? AttachFile(IMetrologyRepository metrologyRepository, IAttachmentsService _AttachmentsService, string tooltype, long headerid, string datauniqueid, string fileName, object uploadedFile);
}

View File

@ -0,0 +1,10 @@
using System.Runtime.CompilerServices;
namespace OI.Metrology.Shared.Models.Stateless;
public interface IMethodName
{
static string? GetActualAsyncMethodName([CallerMemberName] string? name = null) => name;
}

View File

@ -1,13 +1,13 @@
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using System.Data;
using System.Transactions;
namespace OI.Metrology.Shared.Repositories;
namespace OI.Metrology.Shared.Models.Stateless;
using DataModels;
public interface IMetrologyRepo
public interface IMetrologyRepository
{
bool IsTestDatabase();
IEnumerable<ToolType> GetToolTypes();
@ -47,4 +47,5 @@ public interface IMetrologyRepo
IEnumerable<AwaitingDispo> GetAwaitingDispo();
int UpdateReviewDate(int toolTypeId, long headerId, bool clearDate);
}

View File

@ -0,0 +1,11 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IServiceShopOrder
{
ViewModels.ServiceShopOrder[] TestStatic_GetServiceShopOrders(ServiceShop? serviceShop) =>
GetServiceShopOrders(serviceShop);
static ViewModels.ServiceShopOrder[] GetServiceShopOrders(ServiceShop? serviceShop) =>
ServiceShopOrder.GetServiceShopOrders(serviceShop);
}

View File

@ -0,0 +1,15 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IServiceShopOrderController<T>
{
enum Action : int
{
All = 0
}
static string GetRouteName() => nameof(IServiceShopOrderController<T>)[1..^10];
Task<T> GetAllServiceShopOrders();
Task<T> GetServiceShopOrders(string id);
}

View File

@ -0,0 +1,9 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IServiceShopOrderRepository
{
Task<ViewModels.ServiceShopOrder[]> GetAllServiceShopOrders();
Task<ViewModels.ServiceShopOrder[]> GetServiceShopOrders(string id);
}

View File

@ -0,0 +1,21 @@
namespace OI.Metrology.Shared.Models.Stateless;
public interface IToolTypesController<T>
{
enum Action : int
{
Index = 0
}
static string GetRouteName() => nameof(IToolTypesController<T>)[1..^10];
T Index();
T GetToolTypeMetadata(int id, string sortby = "");
T GetHeaders(int id, DateTime? datebegin, DateTime? dateend, int? page, int? pagesize, long? headerid);
T GetHeaderTitles(int id, int? page, int? pagesize);
T GetHeaderFields(int id, long headerid);
T GetData(int id, long headerid);
T GetAttachment(int toolTypeId, string tabletype, string attachmentId, string filename);
T OIExport(int toolTypeId, long headerid);
}

View File

@ -0,0 +1,17 @@
using OI.Metrology.Shared.Services;
namespace OI.Metrology.Shared.Models.Stateless;
public interface IToolTypesRepository
{
object Index(IMetrologyRepository metrologyRepository);
object GetToolTypeMetadata(IMetrologyRepository metrologyRepository, int id, string sortby = "");
string GetHeaders(IMetrologyRepository metrologyRepository, int id, DateTime? datebegin, DateTime? dateend, int? page, int? pagesize, long? headerid);
string GetHeaderTitles(IMetrologyRepository metrologyRepository, int id, int? page, int? pagesize);
string GetHeaderFields(IMetrologyRepository metrologyRepository, int id, long headerid);
string GetData(IMetrologyRepository metrologyRepository, int id, long headerid);
(string?, string?, Stream?) GetAttachment(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, int toolTypeId, string tabletype, string attachmentId, string filename);
Exception? OIExport(IMetrologyRepository metrologyRepository, string oiExportPath, int toolTypeId, long headerid);
}

View File

@ -0,0 +1,16 @@
namespace OI.Metrology.Shared.Models.Stateless;
internal abstract class ServiceShopOrder
{
internal static ViewModels.ServiceShopOrder[] GetServiceShopOrders(ServiceShop? serviceShop)
{
ViewModels.ServiceShopOrder[] results;
if (serviceShop is null || !serviceShop.Orders.Any())
results = Array.Empty<ViewModels.ServiceShopOrder>();
else
results = serviceShop.Orders.Select(l => new ViewModels.ServiceShopOrder(l)).ToArray();
return results;
}
}

View File

@ -1,5 +0,0 @@
namespace OI.Metrology.Shared.Models;
public class TencorRunHeaders
{
}

View File

@ -4,7 +4,7 @@
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageId>OI.Metrology.Shared</PackageId>
@ -30,7 +30,7 @@
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Text.Json" Version="7.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,37 @@
using System.Text.Json;
namespace OI.Metrology.Shared.ViewModels;
// [JsonConstructor]
public record ServiceShopOrder(string Id,
string Name,
string[] BookingNames,
string Type,
string State,
string ItemNumber,
DateTime CreatedDate,
DateTime DecidedDate,
string Recipient,
string Requestor)
{
internal ServiceShopOrder(Models.Order order) :
this(order.Id,
order.Name,
order.Bookings is null || !order.Bookings.Any() ? Array.Empty<string>() : order.Bookings.Select(l => l.Name).ToArray(),
order.Type,
order.State,
order.ItemNumber,
order.CreatedDate,
order.DecidedDate,
order.Recipient,
order.Requestor)
{ }
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
return result;
}
}

View File

@ -58,7 +58,9 @@ public class AppSettings
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
AppSettings appSettings = configurationRoot.Get<AppSettings>();
AppSettings? appSettings = configurationRoot.Get<AppSettings>();
if (appSettings is null)
throw new NullReferenceException(nameof(appSettings));
result = Get(appSettings);
return result;
}

View File

@ -5,7 +5,7 @@
<LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<VSTestLogger>trx</VSTestLogger>
@ -27,29 +27,29 @@
<DefineConstants>Linux</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj" />
<ProjectReference Include="..\Archive\Archive.csproj" />
<ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" />
<ProjectReference Include="..\Viewer\OI.Metrology.Viewer.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="..\Archive\appsettings.json">
<None Include="..\Viewer\appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\Archive\appsettings.Development.json">
<None Include="..\Viewer\appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\.Data\RdsMaxRepo.json">

View File

@ -0,0 +1,99 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using Serilog;
using System.Net.Http.Json;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitAwaitingDispoController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Viewer.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitAwaitingDispoController>();
_WebApplicationFactory = new WebApplicationFactory<Viewer.Program>();
_ControllerName = nameof(Viewer.ApiControllers.ToolTypesController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IToolTypesController<string>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void Index()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IEnumerable<AwaitingDispo> awaitingDispos = metrologyRepository.GetAwaitingDispo();
Assert.IsTrue(awaitingDispos is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task IndexApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.PostAsync($"api/{_ControllerName}", null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void MarkAsReviewed()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
_ = metrologyRepository.UpdateReviewDate(toolTypeId: 0, headerId: 0, clearDate: false);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task MarkAsReviewedApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/markasreviewed");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void MarkAsAwaiting()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
int dateCleared = metrologyRepository.UpdateReviewDate(toolTypeId: 0, headerId: 0, clearDate: true);
Assert.IsTrue(dateCleared <= 1);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task MarkAsAwaitingApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.PostAsync($"api/{_ControllerName}/markasawaiting", null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -0,0 +1,55 @@
using Microsoft.AspNetCore.Mvc.Testing;
using OI.Metrology.Shared.Models.Stateless;
using Serilog;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitInboundController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Viewer.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitInboundController>();
_WebApplicationFactory = new WebApplicationFactory<Viewer.Program>();
_ControllerName = nameof(Viewer.ApiControllers.ToolTypesController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IToolTypesController<string>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task DataApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.PostAsync($"api/{_ControllerName}/a", null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task AttachFileApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.PostAsync($"api/{_ControllerName}/a/attachment", null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -0,0 +1,102 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Shared.Models.Stateless;
using Serilog;
using System.Net;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestAppSettingsController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Viewer.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitTestAppSettingsController>();
_WebApplicationFactory = new WebApplicationFactory<Viewer.Program>();
_ControllerName = nameof(Viewer.ApiControllers.AppSettingsController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IAppSettingsController<object>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void AppSettings()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
Viewer.Models.AppSettings appSettings = serviceProvider.GetRequiredService<Viewer.Models.AppSettings>();
Assert.IsNotNull(appSettings);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetAppSettings()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IAppSettingsRepository appSettingsRepository = serviceProvider.GetRequiredService<IAppSettingsRepository>();
List<string> collection = appSettingsRepository.GetAppSettings();
Assert.IsTrue(collection is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetAppSettingsApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
string actionName = nameof(IAppSettingsController<object>.Action.App);
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync($"api/{_ControllerName}/{actionName}");
Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
Assert.AreEqual("application/json; charset=utf-8", httpResponseMessage.Content.Headers.ContentType?.ToString());
string result = await httpResponseMessage.Content.ReadAsStringAsync();
httpClient.Dispose();
Assert.IsNotNull(result);
Assert.IsTrue(result != "[]");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetBuildNumberAndGitCommitSeven()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IAppSettingsRepository appSettingsRepository = serviceProvider.GetRequiredService<IAppSettingsRepository>();
string result = appSettingsRepository.GetBuildNumberAndGitCommitSeven();
Assert.IsTrue(result is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetBuildNumberAndGitCommitSevenApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
string actionName = nameof(IAppSettingsController<object>.Action.DevOps);
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync($"api/{_ControllerName}/{actionName}");
Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
Assert.AreEqual("text/plain; charset=utf-8", httpResponseMessage.Content.Headers.ContentType?.ToString());
string result = await httpResponseMessage.Content.ReadAsStringAsync();
httpClient.Dispose();
Assert.IsNotNull(result);
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -1,87 +1,87 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Archive.Repositories;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Tests.Models;
using Serilog;
using System.Reflection;
using System.Text.Json;
// using Microsoft.Extensions.Caching.Memory;
// using Microsoft.Extensions.Configuration;
// using Microsoft.Extensions.DependencyInjection;
// using OI.Metrology.Archive.Repositories;
// using OI.Metrology.Shared.Models;
// using OI.Metrology.Shared.Repositories;
// using OI.Metrology.Tests.Models;
// using Serilog;
// using System.Reflection;
// using System.Text.Json;
namespace OI.Metrology.Tests;
// namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestArchive
{
// [TestClass]
// public class UnitTestArchive
// {
private readonly ILogger _Logger;
private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory;
private readonly IMemoryCache? _MemoryCache;
private readonly IConfigurationRoot _ConfigurationRoot;
// private readonly ILogger _Logger;
// private readonly AppSettings _AppSettings;
// private readonly string _WorkingDirectory;
// private readonly IMemoryCache? _MemoryCache;
// private readonly IConfigurationRoot _ConfigurationRoot;
public UnitTestArchive()
{
ILogger logger;
AppSettings appSettings;
string workingDirectory;
IConfigurationRoot configurationRoot;
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile("appsettings.Development.json");
configurationRoot = configurationBuilder.Build();
appSettings = Models.Binder.AppSettings.Get(configurationRoot);
workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
logger = Log.ForContext<UnitTestArchive>();
logger.Information("Complete");
ServiceCollection services = new();
ServiceProvider serviceProvider = services.BuildServiceProvider();
_ = services.AddMemoryCache();
_MemoryCache = serviceProvider.GetService<IMemoryCache>();
_Logger = logger;
_AppSettings = appSettings;
_WorkingDirectory = workingDirectory;
_ConfigurationRoot = configurationRoot;
}
// public UnitTestArchive()
// {
// ILogger logger;
// AppSettings appSettings;
// string workingDirectory;
// IConfigurationRoot configurationRoot;
// LoggerConfiguration loggerConfiguration = new();
// Assembly assembly = Assembly.GetExecutingAssembly();
// IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
// .AddEnvironmentVariables()
// .AddJsonFile("appsettings.Development.json");
// configurationRoot = configurationBuilder.Build();
// appSettings = Models.Binder.AppSettings.Get(configurationRoot);
// workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
// Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
// _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
// Log.Logger = loggerConfiguration.CreateLogger();
// logger = Log.ForContext<UnitTestArchive>();
// logger.Information("Complete");
// ServiceCollection services = new();
// ServiceProvider serviceProvider = services.BuildServiceProvider();
// _ = services.AddMemoryCache();
// _MemoryCache = serviceProvider.GetService<IMemoryCache>();
// _Logger = logger;
// _AppSettings = appSettings;
// _WorkingDirectory = workingDirectory;
// _ConfigurationRoot = configurationRoot;
// }
[TestMethod]
public void TestMethodNull()
{
Assert.IsFalse(_Logger is null);
Assert.IsFalse(_AppSettings is null);
Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null);
}
// [TestMethod]
// public void TestMethodNull()
// {
// Assert.IsFalse(_Logger is null);
// Assert.IsFalse(_AppSettings is null);
// Assert.IsFalse(_WorkingDirectory is null);
// Assert.IsFalse(_ConfigurationRoot is null);
// }
[TestMethod]
public void TestMethodArchive()
{
Assert.IsFalse(_Logger is null);
Assert.IsFalse(_AppSettings is null);
Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null);
}
// [TestMethod]
// public void TestMethodArchive()
// {
// Assert.IsFalse(_Logger is null);
// Assert.IsFalse(_AppSettings is null);
// Assert.IsFalse(_WorkingDirectory is null);
// Assert.IsFalse(_ConfigurationRoot is null);
// }
[TestMethod]
public void TestMethodArchiveJson()
{
string json;
string jsonFile = Path.Combine(AppContext.BaseDirectory, "RdsMaxRepo.json");
Assert.IsTrue(File.Exists(jsonFile));
json = JsonSerializer.Serialize(_AppSettings);
IRdsMaxRepo rdsMaxRepo = new RdsMaxRepo(json, _MemoryCache);
json = File.ReadAllText(jsonFile);
Shared.DataModels.RDS.Max[]? collection = JsonSerializer.Deserialize<Shared.DataModels.RDS.Max[]>(json);
if (collection is null)
throw new NullReferenceException(nameof(collection));
List<string[]> data = rdsMaxRepo.Convert(collection);
Assert.IsTrue(data.Any());
}
// [TestMethod]
// public void TestMethodArchiveJson()
// {
// string json;
// string jsonFile = Path.Combine(AppContext.BaseDirectory, "RdsMaxRepo.json");
// Assert.IsTrue(File.Exists(jsonFile));
// json = JsonSerializer.Serialize(_AppSettings);
// IRdsMaxRepo rdsMaxRepo = new RdsMaxRepo(json, _MemoryCache);
// json = File.ReadAllText(jsonFile);
// Shared.DataModels.RDS.Max[]? collection = JsonSerializer.Deserialize<Shared.DataModels.RDS.Max[]>(json);
// if (collection is null)
// throw new NullReferenceException(nameof(collection));
// List<string[]> data = rdsMaxRepo.Convert(collection);
// Assert.IsTrue(data.Any());
// }
}
// }

View File

@ -0,0 +1,92 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Shared.Models.Stateless;
using Serilog;
using System.Net;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestClientSettingsController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Viewer.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitTestClientSettingsController>();
_WebApplicationFactory = new WebApplicationFactory<Viewer.Program>();
_ControllerName = nameof(Viewer.ApiControllers.ClientSettingsController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IClientSettingsController<object>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetClientSettings()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IClientSettingsRepository clientSettingsRepository = serviceProvider.GetRequiredService<IClientSettingsRepository>();
List<string> clientSettings = clientSettingsRepository.GetClientSettings(null);
Assert.IsTrue(clientSettings is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetClientSettingsApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
string actionName = nameof(IClientSettingsController<object>.Action.Client);
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync($"api/{_ControllerName}/{actionName}");
Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
Assert.AreEqual("application/json; charset=utf-8", httpResponseMessage.Content.Headers.ContentType?.ToString());
string result = await httpResponseMessage.Content.ReadAsStringAsync();
httpClient.Dispose();
Assert.IsNotNull(result);
Assert.IsTrue(result != "[]");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetIpAddress()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IClientSettingsRepository clientSettingsRepository = serviceProvider.GetRequiredService<IClientSettingsRepository>();
string? ipAddress = clientSettingsRepository.GetIpAddress(null);
Assert.IsTrue(ipAddress is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetIpAddressApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
string actionName = nameof(IClientSettingsController<object>.Action.IP);
HttpResponseMessage httpResponseMessage = await httpClient.GetAsync($"api/{_ControllerName}/{actionName}");
Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
Assert.AreEqual("text/plain; charset=utf-8", httpResponseMessage.Content.Headers.ContentType?.ToString());
string result = await httpResponseMessage.Content.ReadAsStringAsync();
httpClient.Dispose();
Assert.IsNotNull(result);
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -1,52 +0,0 @@
using Microsoft.Extensions.Configuration;
using OI.Metrology.Shared.Models;
using OI.Metrology.Tests.Models;
using Serilog;
using System.Reflection;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestExample
{
private readonly ILogger _Logger;
private readonly AppSettings _AppSettings;
private readonly string _WorkingDirectory;
private readonly IConfigurationRoot _ConfigurationRoot;
public UnitTestExample()
{
ILogger logger;
AppSettings appSettings;
string workingDirectory;
IConfigurationRoot configurationRoot;
LoggerConfiguration loggerConfiguration = new();
Assembly assembly = Assembly.GetExecutingAssembly();
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile("appsettings.Development.json");
configurationRoot = configurationBuilder.Build();
appSettings = Models.Binder.AppSettings.Get(configurationRoot);
workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName);
Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
_ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot);
Log.Logger = loggerConfiguration.CreateLogger();
logger = Log.ForContext<UnitTestExample>();
logger.Information("Complete");
_Logger = logger;
_AppSettings = appSettings;
_WorkingDirectory = workingDirectory;
_ConfigurationRoot = configurationRoot;
}
[TestMethod]
public void TestMethodNull()
{
Assert.IsFalse(_Logger is null);
Assert.IsFalse(_AppSettings is null);
Assert.IsFalse(_WorkingDirectory is null);
Assert.IsFalse(_ConfigurationRoot is null);
}
}

View File

@ -1,109 +1,109 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using System.Net;
// using Microsoft.AspNetCore.Mvc.Testing;
// using Microsoft.Extensions.DependencyInjection;
// using Serilog;
// using System.Net;
namespace OI.Metrology.Tests;
// namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestReactorController
{
private static TestContext? _TestContext;
private static WebApplicationFactory<Archive.Program>? _WebApplicationFactory;
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_WebApplicationFactory = new WebApplicationFactory<Archive.Program>();
}
[TestMethod]
public async Task GetReactors_ShouldReturnAllReactorsAsync()
{
HttpResponseMessage httpResponseMessage;
if (_WebApplicationFactory is null)
throw new NullReferenceException(nameof(_WebApplicationFactory));
HttpClient httpClient = _WebApplicationFactory.CreateClient();
ILogger log = Log.ForContext<UnitTestReactorController>();
log.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
Archive.Models.AppSettings appSettings = serviceProvider.GetRequiredService<Archive.Models.AppSettings>();
httpResponseMessage = await httpClient.GetAsync($"api/{nameof(Archive.ApiContollers.ReactorsController)[..^10]}/true");
Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
Assert.AreEqual("application/json; charset=utf-8", httpResponseMessage.Content.Headers.ContentType?.ToString());
httpResponseMessage = await httpClient.GetAsync($"api/{nameof(Archive.ApiContollers.ReactorsController)[..^10]}/false");
Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
// string result = await httpResponseMessage.Content.ReadAsStringAsync();
// Assert.AreEqual("\"Sample Name 1\"", result);
httpClient.Dispose();
log.Information($"{_TestContext?.TestName} completed");
}
// [TestMethod]
// public void GetAllProducts_ShouldReturnAllProducts()
// [TestClass]
// public class UnitTestReactorController
// {
// var testProducts = GetTestProducts();
// var controller = new OI.Metrology.Archive.ApiContollers.ReactorsController(testProducts);
// var result = controller.GetAllProducts() as List<Product>;
// Assert.AreEqual(testProducts.Count, result.Count);
// private static TestContext? _TestContext;
// private static WebApplicationFactory<Archive.Program>? _WebApplicationFactory;
// [ClassInitialize]
// public static void ClassInitAsync(TestContext testContext)
// {
// _TestContext = testContext;
// _WebApplicationFactory = new WebApplicationFactory<Archive.Program>();
// }
// [TestMethod]
// public async Task GetAllProductsAsync_ShouldReturnAllProducts()
// public async Task GetReactors_ShouldReturnAllReactorsAsync()
// {
// var testProducts = GetTestProducts();
// var controller = new OI.Metrology.Archive.ApiContollers.ReactorsController(testProducts);
// var result = await controller.GetAllProductsAsync() as List<Product>;
// Assert.AreEqual(testProducts.Count, result.Count);
// HttpResponseMessage httpResponseMessage;
// if (_WebApplicationFactory is null)
// throw new NullReferenceException(nameof(_WebApplicationFactory));
// HttpClient httpClient = _WebApplicationFactory.CreateClient();
// ILogger log = Log.ForContext<UnitTestReactorController>();
// log.Information("Starting Web Application");
// IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
// Archive.Models.AppSettings appSettings = serviceProvider.GetRequiredService<Archive.Models.AppSettings>();
// httpResponseMessage = await httpClient.GetAsync($"api/{nameof(Archive.ApiControllers.ReactorsController)[..^10]}/true");
// Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
// Assert.AreEqual("application/json; charset=utf-8", httpResponseMessage.Content.Headers.ContentType?.ToString());
// httpResponseMessage = await httpClient.GetAsync($"api/{nameof(Archive.ApiControllers.ReactorsController)[..^10]}/false");
// Assert.AreEqual(HttpStatusCode.OK, httpResponseMessage.StatusCode);
// // string result = await httpResponseMessage.Content.ReadAsStringAsync();
// // Assert.AreEqual("\"Sample Name 1\"", result);
// httpClient.Dispose();
// log.Information($"{_TestContext?.TestName} completed");
// }
// [TestMethod]
// public void GetProduct_ShouldReturnCorrectProduct()
// {
// var testProducts = GetTestProducts();
// var controller = new OI.Metrology.Archive.ApiContollers.ReactorsController(testProducts);
// // [TestMethod]
// // public void GetAllProducts_ShouldReturnAllProducts()
// // {
// // var testProducts = GetTestProducts();
// // var controller = new OI.Metrology.Archive.ApiControllers.ReactorsController(testProducts);
// // var result = controller.GetAllProducts() as List<Product>;
// // Assert.AreEqual(testProducts.Count, result.Count);
// // }
// // [TestMethod]
// // public async Task GetAllProductsAsync_ShouldReturnAllProducts()
// // {
// // var testProducts = GetTestProducts();
// // var controller = new OI.Metrology.Archive.ApiControllers.ReactorsController(testProducts);
// // var result = await controller.GetAllProductsAsync() as List<Product>;
// // Assert.AreEqual(testProducts.Count, result.Count);
// // }
// // [TestMethod]
// // public void GetProduct_ShouldReturnCorrectProduct()
// // {
// // var testProducts = GetTestProducts();
// // var controller = new OI.Metrology.Archive.ApiControllers.ReactorsController(testProducts);
// // var result = controller.GetProduct(4) as OkNegotiatedContentResult<Product>;
// // Assert.IsNotNull(result);
// // Assert.AreEqual(testProducts[3].Name, result.Content.Name);
// // }
// // [TestMethod]
// // public async Task GetProductAsync_ShouldReturnCorrectProduct()
// // {
// // var testProducts = GetTestProducts();
// // var controller = new OI.Metrology.Archive.ApiControllers.ReactorsController(testProducts);
// // var result = await controller.GetProductAsync(4) as OkNegotiatedContentResult<Product>;
// // Assert.IsNotNull(result);
// // Assert.AreEqual(testProducts[3].Name, result.Content.Name);
// // }
// // [TestMethod]
// // public void GetProduct_ShouldNotFindProduct()
// // {
// // var controller = new OI.Metrology.Archive.ApiControllers.ReactorsController(GetTestProducts());
// // var result = controller.GetProduct(999);
// // Assert.IsInstanceOfType(result, typeof(NotFoundResult));
// // }
// // private List<Product> GetTestProducts()
// // {
// // var testProducts = new List<Product>();
// // testProducts.Add(new Product { Id = 1, Name = "Demo1", Price = 1 });
// // testProducts.Add(new Product { Id = 2, Name = "Demo2", Price = 3.75M });
// // testProducts.Add(new Product { Id = 3, Name = "Demo3", Price = 16.99M });
// // testProducts.Add(new Product { Id = 4, Name = "Demo4", Price = 11.00M });
// // return testProducts;
// // }
// [ClassCleanup]
// public static void ClassCleanup() => _WebApplicationFactory?.Dispose();
// var result = controller.GetProduct(4) as OkNegotiatedContentResult<Product>;
// Assert.IsNotNull(result);
// Assert.AreEqual(testProducts[3].Name, result.Content.Name);
// }
// [TestMethod]
// public async Task GetProductAsync_ShouldReturnCorrectProduct()
// {
// var testProducts = GetTestProducts();
// var controller = new OI.Metrology.Archive.ApiContollers.ReactorsController(testProducts);
// var result = await controller.GetProductAsync(4) as OkNegotiatedContentResult<Product>;
// Assert.IsNotNull(result);
// Assert.AreEqual(testProducts[3].Name, result.Content.Name);
// }
// [TestMethod]
// public void GetProduct_ShouldNotFindProduct()
// {
// var controller = new OI.Metrology.Archive.ApiContollers.ReactorsController(GetTestProducts());
// var result = controller.GetProduct(999);
// Assert.IsInstanceOfType(result, typeof(NotFoundResult));
// }
// private List<Product> GetTestProducts()
// {
// var testProducts = new List<Product>();
// testProducts.Add(new Product { Id = 1, Name = "Demo1", Price = 1 });
// testProducts.Add(new Product { Id = 2, Name = "Demo2", Price = 3.75M });
// testProducts.Add(new Product { Id = 3, Name = "Demo3", Price = 16.99M });
// testProducts.Add(new Product { Id = 4, Name = "Demo4", Price = 11.00M });
// return testProducts;
// }
[ClassCleanup]
public static void ClassCleanup() => _WebApplicationFactory?.Dispose();
}

View File

@ -0,0 +1,77 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.ViewModels;
using Serilog;
using System.Net.Http.Json;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestServiceShopOrderController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Viewer.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitTestServiceShopOrderController>();
_WebApplicationFactory = new WebApplicationFactory<Viewer.Program>();
_ControllerName = nameof(Viewer.ApiControllers.ServiceShopOrderController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IServiceShopOrderController<string>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetServiceShopOrders()
{
if (_Logger is null)
throw new NullReferenceException(nameof(_Logger));
ServiceShopOrder[] serviceShopOrders = IServiceShopOrder.GetServiceShopOrders(null);
Assert.IsNotNull(serviceShopOrders);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetAllServiceShopOrders()
{
_Logger.Information("Starting Web Application");
ServiceShopOrder[] serviceShopOrders;
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IServiceShopOrderRepository serviceShopOrderRepository = serviceProvider.GetRequiredService<IServiceShopOrderRepository>();
serviceShopOrders = await serviceShopOrderRepository.GetAllServiceShopOrders();
Assert.IsTrue(serviceShopOrders is not null);
serviceShopOrders = await serviceShopOrderRepository.GetServiceShopOrders("23188d3d-9b75-ed11-ab8b-0050568f2fc3");
Assert.IsTrue(serviceShopOrders is not null && serviceShopOrders.Any());
Assert.IsNotNull(serviceShopOrders[0].ToString());
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetAllServiceShopOrdersApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
string actionName = nameof(IServiceShopOrderController<object>.Action.All);
ServiceShopOrder[]? serviceShopOrders = await httpClient.GetFromJsonAsync<ServiceShopOrder[]>($"api/{_ControllerName}/{actionName}");
Assert.IsNotNull(serviceShopOrders);
Assert.IsTrue(serviceShopOrders.Any());
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -0,0 +1,210 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using Serilog;
using System.Net.Http.Json;
namespace OI.Metrology.Tests;
[TestClass]
public class UnitTestToolTypesController
{
#pragma warning disable CS8618
private static ILogger _Logger;
private static string _ControllerName;
private static TestContext _TestContext;
private static WebApplicationFactory<Viewer.Program> _WebApplicationFactory;
#pragma warning restore
[ClassInitialize]
public static void ClassInitAsync(TestContext testContext)
{
_TestContext = testContext;
_Logger = Log.ForContext<UnitTestToolTypesController>();
_WebApplicationFactory = new WebApplicationFactory<Viewer.Program>();
_ControllerName = nameof(Viewer.ApiControllers.ToolTypesController)[..^10];
}
[TestMethod]
public void TestControllerName()
{
_Logger.Information("Starting Web Application");
Assert.AreEqual(IToolTypesController<string>.GetRouteName(), _ControllerName);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void Index()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
object @object = toolTypesRepository.Index(metrologyRepository);
Assert.IsTrue(@object is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task IndexApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetToolTypeMetadata()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
object @object = toolTypesRepository.GetToolTypeMetadata(metrologyRepository, id: 0, sortby: string.Empty);
Assert.IsTrue(@object is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetToolTypeMetadataApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetHeaders()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
string json = toolTypesRepository.GetHeaders(metrologyRepository, id: 0, datebegin: null, dateend: null, page: null, pagesize: null, headerid: null);
Assert.IsTrue(json is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetHeadersApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0/headers");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetHeaderTitles()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
string json = toolTypesRepository.GetHeaderTitles(metrologyRepository, id: 0, page: null, pagesize: null);
Assert.IsTrue(json is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetHeaderTitlesApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0/headertitles");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetHeaderFields()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
string json = toolTypesRepository.GetHeaderFields(metrologyRepository, id: 0, headerid: 0);
Assert.IsTrue(json is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetHeaderFieldsApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0/headers/0/fields");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetData()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
string json = toolTypesRepository.GetData(metrologyRepository, id: 0, headerid: 0);
Assert.IsTrue(json is not null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetDataApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0/headers/data");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void GetAttachment()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IAttachmentsService attachmentsService = serviceProvider.GetRequiredService<IAttachmentsService>();
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
(string? message, string? _, Stream? _) = toolTypesRepository.GetAttachment(metrologyRepository, attachmentsService, toolTypeId: 0, string.Empty, string.Empty, string.Empty);
Assert.IsTrue(message is null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task GetAttachmentApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0/0/files/0/a.txt");
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public void OIExport()
{
_Logger.Information("Starting Web Application");
IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider;
IMetrologyRepository metrologyRepository = serviceProvider.GetRequiredService<IMetrologyRepository>();
IToolTypesRepository toolTypesRepository = serviceProvider.GetRequiredService<IToolTypesRepository>();
Viewer.Models.AppSettings appSettings = serviceProvider.GetRequiredService<Viewer.Models.AppSettings>();
Exception? exception = toolTypesRepository.OIExport(metrologyRepository, appSettings.OIExportPath, toolTypeId: 0, headerid: 0);
Assert.IsTrue(exception is null);
_Logger.Information($"{_TestContext?.TestName} completed");
}
[TestMethod]
public async Task OIExportApi()
{
HttpClient httpClient = _WebApplicationFactory.CreateClient();
_Logger.Information("Starting Web Application");
_ = await httpClient.GetFromJsonAsync<object>($"api/{_ControllerName}/0/headers/0/oiexport");
_Logger.Information($"{_TestContext?.TestName} completed");
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Viewer.ApiControllers;
[ApiController]
[Route("api/[controller]")]
public class AppSettingsController : ControllerBase, IAppSettingsController<ActionResult>
{
private readonly IAppSettingsRepository _AppSettingsRepository;
public AppSettingsController(IAppSettingsRepository AppSettingsRepository) => _AppSettingsRepository = AppSettingsRepository;
[HttpGet(nameof(IAppSettingsController<ActionResult>.Action.App))]
public ActionResult GetAppSettings()
{
List<string> results = _AppSettingsRepository.GetAppSettings();
return Ok(results);
}
[HttpGet(nameof(IAppSettingsController<ActionResult>.Action.DevOps))]
public ActionResult GetBuildNumberAndGitCommitSeven()
{
string result = _AppSettingsRepository.GetBuildNumberAndGitCommitSeven();
return Ok(result);
}
}

View File

@ -1,50 +1,39 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System;
using System.IO;
namespace OI.Metrology.Viewer.ApiControllers;
public class AttachmentsController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly IAttachmentsService _AttachmentsService;
public AttachmentsController(IMetrologyRepo repo, IAttachmentsService attachmentsService)
private readonly IAttachmentsService _AttachmentsService;
private readonly IMetrologyRepository _MetrologyRepository;
public AttachmentsController(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService)
{
_Repo = repo;
_AttachmentsService = attachmentsService;
_MetrologyRepository = metrologyRepository;
}
// this endpoint was created in hope that it would make retrieving attachments to display in OpenInsight easier
// url would be like /api/attachments/mercuryprobe/header/HgProbe_66-232268-4329_20180620052640032/data.pdf
[HttpGet("/api/attachments/{toolTypeName}/{tabletype}/{title}/{filename}")]
public IActionResult GetAttachment(
string toolTypeName,
string tabletype,
string title,
string filename)
public IActionResult GetAttachment(string toolTypeName, string tabletype, string title, string filename)
{
ToolType tt = _Repo.GetToolTypeByName(toolTypeName);
ToolType tt = _MetrologyRepository.GetToolTypeByName(toolTypeName);
bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);
try
{
string contenttype = "application/pdf";
if (filename.ToLower().TrimEnd().EndsWith(".txt"))
contenttype = "text/plain";
Stream fs = _AttachmentsService.GetAttachmentStreamByTitle(tt, header, title, filename);
return File(fs, contenttype);
}
catch (Exception ex)
{
return Content(ex.Message);
}
catch (Exception ex) { return Content(ex.Message); }
}
}

View File

@ -1,37 +1,31 @@
using Microsoft.AspNetCore.Mvc;
namespace OI.Metrology.Viewer.ApiContollers;
namespace OI.Metrology.Viewer.ApiControllers;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using System.Text.Json;
// this controller is for the Awaiting Dispo functionality
[Route("api/[controller]")]
public class AwaitingDispoController : Controller
{
private readonly IMetrologyRepo _Repo;
public AwaitingDispoController(IMetrologyRepo repo) => _Repo = repo;
private readonly IMetrologyRepository _MetrologyRepository;
public AwaitingDispoController(IMetrologyRepository metrologyRepository) =>
_MetrologyRepository = metrologyRepository;
// returns the data to show in the Awaiting Dispo grid
// marked no-cache, just-in-case since igniteUI automatically adds a query string parameter to prevent caching
[HttpGet("/api/awaitingdispo")]
[HttpGet]
[ResponseCache(NoStore = true)]
public IActionResult Index()
{
var r = new
{
Results = _Repo.GetAwaitingDispo()
};
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
}
public IActionResult Index() =>
Json(_MetrologyRepository.GetAwaitingDispo(), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
// this endpoint is used to set the ReviewDate column, causing the header to no longer show in Awaiting Dispo
[HttpPost("/api/awaitingdispo/markasreviewed")]
public IActionResult MarkAsReviewed([FromQuery] long headerid, [FromQuery] int tooltypeid)
{
_ = _Repo.UpdateReviewDate(tooltypeid, headerid, false);
_ = _MetrologyRepository.UpdateReviewDate(tooltypeid, headerid, false);
return Ok();
}
@ -39,7 +33,7 @@ public class AwaitingDispoController : Controller
[HttpPost("/api/awaitingdispo/markasawaiting")]
public IActionResult MarkAsAwaiting([FromQuery] long headerid, [FromQuery] int tooltypeid)
{
if (_Repo.UpdateReviewDate(tooltypeid, headerid, true) <= 1)
if (_MetrologyRepository.UpdateReviewDate(tooltypeid, headerid, true) <= 1)
return Ok();
else
return StatusCode(444);

View File

@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Viewer.ApiControllers;
[ApiController]
[Route("api/[controller]")]
public class ClientSettingsController : ControllerBase, IClientSettingsController<ActionResult>
{
private readonly IClientSettingsRepository _ClientSettingsRepository;
public ClientSettingsController(IClientSettingsRepository clientSettingsRepository) => _ClientSettingsRepository = clientSettingsRepository;
[HttpGet(nameof(IClientSettingsController<ActionResult>.Action.Client))]
public ActionResult GetClientSettings()
{
List<string> results = _ClientSettingsRepository.GetClientSettings(Request.HttpContext.Connection?.RemoteIpAddress);
return Ok(results);
}
[HttpGet(nameof(IClientSettingsController<ActionResult>.Action.IP))]
public ActionResult GetIpAddress()
{
string result = _ClientSettingsRepository.GetIpAddress(Request.HttpContext.Connection?.RemoteIpAddress);
return Ok(result);
}
}

View File

@ -1,168 +1,78 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using OI.Metrology.Viewer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace OI.Metrology.Viewer.ApiContollers;
namespace OI.Metrology.Viewer.ApiControllers;
[ApiController]
public class InboundController : ControllerBase
[Route("api/[controller]")]
public partial class InboundController : ControllerBase, IInboundController<IActionResult>
{
private readonly ILogger _Logger;
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IAttachmentsService _AttachmentService;
private readonly IInboundRepository _InboundRepository;
private readonly IAttachmentsService _AttachmentsService;
private readonly IInboundDataService _InboundDataService;
private readonly IMetrologyRepository _MetrologyRepository;
public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepo repo, IInboundDataService inboundDataService, IAttachmentsService attachmentService)
public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepository metrologyRepository, IInboundRepository inboundRepository, IInboundDataService inboundDataService, IAttachmentsService attachmentsService)
{
_Repo = repo;
_Logger = logger;
_AppSettings = appSettings;
_AttachmentService = attachmentService;
_InboundRepository = inboundRepository;
_AttachmentsService = attachmentsService;
_InboundDataService = inboundDataService;
_MetrologyRepository = metrologyRepository;
}
// this class represents the API response back to the client
public class DataResponse
{
public bool Success { get; set; }
public long HeaderID { get; set; }
public List<string> Errors { get; set; }
public List<string> Warnings { get; set; }
}
// this is the main endpoint, it accepts a JSON message that contains both the header and data records together
// tooltype is the ToolTypeName column from the ToolType table
// JToken is how you can accept a JSON message without deserialization.
// Using "string" doesn't work because ASP.NET Core will expect a json encoded string, not give you the actual string.
[HttpPost("/api/inbound/{tooltype}")]
[HttpPost]
[Route("{tooltype}")]
public IActionResult Data(string tooltype, [FromBody] JToken jsonbody)
{
DataResponse r = new()
IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress;
if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP))
{
Success = false,
HeaderID = -1,
Errors = new List<string>(),
Warnings = new List<string>()
};
if (!IsIPAddressAllowed())
{
_Logger.LogInformation($"Rejected remote IP: {HttpContext.Connection.RemoteIpAddress}");
r.Errors.Add("Remote IP is not on allowed list");
return Unauthorized(r);
}
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
if (toolType == null)
{
r.Errors.Add("Invalid tool type: " + tooltype);
return BadRequest(r);
}
// get metadata
List<ToolTypeMetadata> metaData = _Repo.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
if (metaData == null)
{
r.Errors.Add("Invalid metadata for tool type: " + tooltype);
return BadRequest(r);
}
// validate fields
if (jsonbody != null)
_InboundDataService.ValidateJSONFields(jsonbody, 0, metaData, r.Errors, r.Warnings);
else
r.Errors.Add("Invalid json");
if (r.Errors.Count == 0)
{
try
{
r.HeaderID = _InboundDataService.DoSQLInsert(jsonbody, toolType, metaData);
r.Success = r.HeaderID > 0;
}
catch (Exception ex)
{
r.Errors.Add(ex.Message);
}
return Ok(r);
}
else
{
return BadRequest(r);
}
}
// this is the endpoint for attaching a field. It is not JSON, it is form-data/multipart like an HTML form because that's the normal way.
// header ID is the ID value from the Header table
// datauniqueid is the Title value from the Data/Detail table
[HttpPost("/api/inbound/{tooltype}/attachment")]
public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "")
{
if (!IsIPAddressAllowed())
{
_Logger.LogInformation($"Rejected remote IP: {HttpContext.Connection.RemoteIpAddress}");
_Logger.LogInformation($"Rejected remote IP: {remoteIP}");
return Unauthorized("Remote IP is not on allowed list");
}
else
{
DataResponse dataResponse = _InboundRepository.Data(_MetrologyRepository, _InboundDataService, tooltype, jsonbody);
if (!dataResponse.Errors.Any())
return Ok(dataResponse);
else
return BadRequest(dataResponse);
}
}
ToolType toolType = _Repo.GetToolTypeByName(tooltype);
if (toolType == null)
return BadRequest($"Invalid tool type: {tooltype}");
if (Request.Form == null)
[HttpPost]
[Route("{tooltype}/attachment")]
public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "")
{
IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress;
if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP))
{
_Logger.LogInformation($"Rejected remote IP: {remoteIP}");
return Unauthorized("Remote IP is not on allowed list");
}
else
{
if (Request.Form is null)
return BadRequest($"Invalid form");
if (Request.Form.Files.Count != 1)
return BadRequest($"Invalid file count");
string filename = System.IO.Path.GetFileName(Request.Form.Files[0].FileName);
if (string.IsNullOrWhiteSpace(filename))
return BadRequest("Empty filename");
if (filename.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) >= 0)
return BadRequest("Invalid filename");
_AttachmentService.SaveAttachment(toolType, headerid, datauniqueid, filename, Request.Form.Files[0]);
IFormFile formFile = Request.Form.Files[0];
string? message = _InboundRepository.AttachFile(_MetrologyRepository, _AttachmentsService, tooltype, headerid, datauniqueid, formFile.FileName, formFile);
if (message is null)
return Ok();
}
protected bool IsIPAddressAllowed()
{
if (string.IsNullOrWhiteSpace(_AppSettings.InboundApiAllowedIPList))
return true;
System.Net.IPAddress remoteIP = HttpContext.Connection.RemoteIpAddress;
byte[] remoteIPBytes = remoteIP.GetAddressBytes();
string[] allowedIPs = _AppSettings.InboundApiAllowedIPList.Split(';');
foreach (string ip in allowedIPs)
{
System.Net.IPAddress parsedIP;
if (System.Net.IPAddress.TryParse(ip, out parsedIP))
{
if (parsedIP.GetAddressBytes().SequenceEqual(remoteIPBytes))
return true;
else
return BadRequest(message);
}
}
return false;
}
}

View File

@ -0,0 +1,46 @@
using Microsoft.AspNetCore.Mvc;
using OI.Metrology.Shared.Models.Stateless;
namespace OI.Metrology.Viewer.ApiControllers;
[ApiController]
[Route("api/[controller]")]
public class ServiceShopOrderController : ControllerBase, IServiceShopOrderController<ActionResult>
{
private readonly IServiceShopOrderRepository _ServiceShopOrderRepository;
public ServiceShopOrderController(IServiceShopOrderRepository ServiceShopOrderRepository) => _ServiceShopOrderRepository = ServiceShopOrderRepository;
[HttpGet(nameof(IServiceShopOrderController<ActionResult>.Action.All))]
public async Task<ActionResult> GetAllServiceShopOrders()
{
try
{
Shared.ViewModels.ServiceShopOrder[] results = await _ServiceShopOrderRepository.GetAllServiceShopOrders();
return Ok(results);
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError,
"Error retrieving data from the database");
}
}
[HttpGet]
[Route("{id}")]
public async Task<ActionResult> GetServiceShopOrders(string id)
{
try
{
Shared.ViewModels.ServiceShopOrder[] results = await _ServiceShopOrderRepository.GetServiceShopOrders(id);
return Ok(results);
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError,
"Error retrieving data from the database");
}
}
}

View File

@ -1,249 +1,84 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;
namespace OI.Metrology.Viewer.ApiContollers;
namespace OI.Metrology.Viewer.ApiControllers;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using OI.Metrology.Viewer.Models;
using System.Collections.Generic;
using System.Text.Json;
// using System.Data.Common;
public class ToolTypesController : Controller
[Route("api/[controller]")]
public class ToolTypesController : Controller, IToolTypesController<IActionResult>
{
// this controller powers the bulk of the UI
// it is named after the /api/tooltypes prefix
// the URL pattern is RESTful and the tool type is the root of every request
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IMetrologyRepository _MetrologyRepo;
private readonly IAttachmentsService _AttachmentsService;
private readonly IToolTypesRepository _ToolTypesRepository;
public ToolTypesController(AppSettings appSettings, IMetrologyRepo repo, IAttachmentsService attachmentsService)
public ToolTypesController(AppSettings appSettings, IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, IToolTypesRepository toolTypesRepository)
{
_Repo = repo;
_AppSettings = appSettings;
_MetrologyRepo = metrologyRepository;
_AttachmentsService = attachmentsService;
_ToolTypesRepository = toolTypesRepository;
}
// Get a list of tooltypes, returns just Name and ID
[HttpGet("/api/tooltypes")]
public IActionResult Index()
[HttpGet]
public IActionResult Index() =>
Json(_ToolTypesRepository.Index(_MetrologyRepo), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
[HttpGet]
[Route("{id}")]
public IActionResult GetToolTypeMetadata(int id, string sortby = "") =>
Json(_ToolTypesRepository.GetToolTypeMetadata(_MetrologyRepo, id, sortby), new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
[HttpGet]
[Route("{id}/headers")]
public IActionResult GetHeaders(int id, [FromQuery] DateTime? datebegin, [FromQuery] DateTime? dateend, [FromQuery] int? page, [FromQuery] int? pagesize, [FromQuery] long? headerid) =>
Content(_ToolTypesRepository.GetHeaders(_MetrologyRepo, id, datebegin, dateend, page, pagesize, headerid));
[HttpGet]
[Route("{id}/headertitles")]
public IActionResult GetHeaderTitles(int id, [FromQuery] int? page, [FromQuery] int? pagesize) =>
Content(_ToolTypesRepository.GetHeaderTitles(_MetrologyRepo, id, page, pagesize));
[HttpGet]
[Route("{id}/headers/{headerid}/fields")]
public IActionResult GetHeaderFields(int id, long headerid) =>
Content(_ToolTypesRepository.GetHeaderFields(_MetrologyRepo, id, headerid));
[HttpGet]
[Route("{id}/headers/{headerid}/data")]
public IActionResult GetData(int id, long headerid) =>
Content(_ToolTypesRepository.GetData(_MetrologyRepo, id, headerid));
[HttpGet]
[Route("{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")]
public IActionResult GetAttachment(int toolTypeId, string tabletype, string attachmentId, string filename)
{
var r = new
{
Results = _Repo.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID })
};
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
(string? message, string? contenttype, Stream? stream) = _ToolTypesRepository.GetAttachment(_MetrologyRepo, _AttachmentsService, toolTypeId, tabletype, attachmentId, filename);
if (message is not null)
return Content(message);
else if (contenttype is not null && stream is not null)
return File(stream, contenttype);
else
throw new Exception();
}
// Gets the metadata for a tooltype, accepts a parameter which sorts the results
// This is used to setup the grid displays on the UI
[HttpGet("/api/tooltypes/{id}")]
public IActionResult GetToolTypeMetadata(int id, string sortby = "")
{
ToolType tt = _Repo.GetToolTypeByID(id);
IEnumerable<ToolTypeMetadata> md = _Repo.GetToolTypeMetadataByToolTypeID(id);
if (string.Equals(sortby, "grid", StringComparison.OrdinalIgnoreCase))
md = md.OrderBy(f => f.GridDisplayOrder).ToList();
if (string.Equals(sortby, "table", StringComparison.OrdinalIgnoreCase))
md = md.OrderBy(f => f.GridDisplayOrder).ToList();
var r = new
{
Results = new
{
ToolType = tt,
Metadata = md
}
};
return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
}
// Gets headers, request/response format is to allow paging with igniteUI
// The headerid parameter is used for navigating directly to a header, when the button is clicked in Awaiting Dispo
[HttpGet("/api/tooltypes/{id}/headers")]
public IActionResult GetHeaders(
int id,
[FromQuery] DateTime? datebegin,
[FromQuery] DateTime? dateend,
[FromQuery] int? page,
[FromQuery] int? pagesize,
[FromQuery] long? headerid)
{
long totalRecs;
System.Data.DataTable dt = _Repo.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs);
var r = new
{
Results = dt,
TotalRows = totalRecs,
};
string json = JsonConvert.SerializeObject(r);
return Content(json);
}
// Gets header titles, used in the Run Headers UI
[HttpGet("/api/tooltypes/{id}/headertitles")]
public IActionResult GetHeaderTitles(
int id,
[FromQuery] int? page,
[FromQuery] int? pagesize)
{
long totalRecs;
IEnumerable<HeaderCommon> dt = _Repo.GetHeaderTitles(id, page, pagesize, out totalRecs);
var r = new
{
Results = dt,
TotalRows = totalRecs,
};
string json = JsonConvert.SerializeObject(r);
return Content(json);
}
// Get all of the fields for a header, used with the Run Header UI
[HttpGet("/api/tooltypes/{id}/headers/{headerid}/fields")]
public IActionResult GetHeaderFields(
int id,
long headerid)
{
var r = new
{
Results = _Repo.GetHeaderFields(id, headerid).Select(x => new { Column = x.Key, x.Value }).ToList()
};
string json = JsonConvert.SerializeObject(r);
return Content(json);
}
// Get the data for a header, used with the Run Info UI
[HttpGet("/api/tooltypes/{id}/headers/{headerid}/data")]
public IActionResult GetData(
int id,
long headerid)
{
var r = new
{
Results = _Repo.GetData(id, headerid)
};
string json = JsonConvert.SerializeObject(r);
return Content(json);
}
// Display an attachment, used for Run Info - note it is by tool type ID and attachment GUID, so it is best for internal use
[HttpGet("/api/tooltypes/{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")]
public IActionResult GetAttachment(
int toolTypeId,
string tabletype,
string attachmentId,
string filename)
{
ToolType tt = _Repo.GetToolTypeByID(toolTypeId);
bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);
Guid attachmentIdParsed;
if (!Guid.TryParse(attachmentId, out attachmentIdParsed))
return Content("Invalid attachment id");
try
{
// figure out what content type to use. this is very simple because there are only two types being used
string contenttype = "application/pdf";
if (filename.ToLower().TrimEnd().EndsWith(".txt"))
contenttype = "text/plain";
// Get attachment stream and feed it to the client
Stream fs = _AttachmentsService.GetAttachmentStreamByAttachmentId(tt, header, attachmentIdParsed, filename);
return File(fs, contenttype);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
// This endpoint triggers writing of the OI Export file
[HttpPost("/api/tooltypes/{toolTypeId}/headers/{headerid}/oiexport")]
[HttpPost]
[Route("{toolTypeId}/headers/{headerid}/oiexport")]
public IActionResult OIExport(int toolTypeId, long headerid)
{
// Call the export stored procedure
System.Data.DataSet ds = _Repo.GetOIExportData(toolTypeId, headerid);
try
{
// The SP must return 3 result tables
if (ds.Tables.Count != 3)
throw new Exception("Error exporting, invalid results");
// The first table has just one row, which is the export filename
if (ds.Tables[0].Rows.Count != 1)
throw new Exception("Error exporting, invalid filename");
string filename = Convert.ToString(ds.Tables[0].Rows[0][0]);
// The second table has the header data
if (ds.Tables[1].Rows.Count != 1)
throw new Exception("Error exporting, invalid header data");
System.Text.StringBuilder sb = new();
foreach (object o in ds.Tables[1].Rows[0].ItemArray)
{
if ((o != null) && (!Convert.IsDBNull(o)))
_ = sb.Append(Convert.ToString(o));
_ = sb.Append('\t');
}
// The third table has the detail data
foreach (System.Data.DataRow dr in ds.Tables[2].Rows)
{
foreach (object o in dr.ItemArray)
{
if ((o != null) && (!Convert.IsDBNull(o)))
_ = sb.Append(Convert.ToString(o));
_ = sb.Append('\t');
}
}
_ = sb.AppendLine();
// The output file will only have one line, the header columns are output first
// Then each detail rows has it's columns appended
// H1, H2, H3, D1.1, D1.2, D1.3, D2.1, D2.2, D2.3, etc
// Write the file
System.IO.File.WriteAllText(
Path.Join(_AppSettings.OIExportPath, filename),
sb.ToString());
}
catch (Exception ex)
{
string json = JsonConvert.SerializeObject(new
{
ex.Message,
});
return BadRequest(json);
}
var r = new
{
Message = "OK",
};
return Ok(r);
Exception? exception = _ToolTypesRepository.OIExport(_MetrologyRepo, _AppSettings.OIExportPath, toolTypeId, headerid);
if (exception is null)
return Ok(new { Message = "OK" });
else
return BadRequest(JsonConvert.SerializeObject(new { exception.Message }));
}
}

View File

@ -1,11 +1,5 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using OI.Metrology.Viewer.Models;
using System;
using System.IO;
using System.Linq;
using OI.Metrology.Viewer.Models;
using System.Text;
using System.Threading.Tasks;
namespace OI.Metrology.Viewer;
@ -43,7 +37,8 @@ public class ApiLoggingMiddleware
else
{
// if there are content type filters configured, only log is the request begins with one of them
doLogging = _AppSettings.ApiLoggingContentTypes.Split(';').Any(ct => httpContext.Request.ContentType.StartsWith(ct));
string? contentType = httpContext.Request.ContentType;
doLogging = contentType is not null && _AppSettings.ApiLoggingContentTypes.Split(';').Any(ct => contentType.StartsWith(ct));
}
}
}

View File

@ -1,7 +1,5 @@
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace OI.Metrology.Viewer.Controllers;
@ -14,8 +12,8 @@ public class ErrorHandlerController : Controller
public IActionResult Index()
{
IExceptionHandlerFeature error = HttpContext.Features.Get<IExceptionHandlerFeature>();
if (error == null)
IExceptionHandlerFeature? error = HttpContext.Features.Get<IExceptionHandlerFeature>();
if (error is null)
{
return Redirect("~/");
}
@ -24,7 +22,7 @@ public class ErrorHandlerController : Controller
_Logger.LogError("Unhandled exception: " + error.Error.ToString());
dynamic r = new
{
Message = error.Error == null ? "Error" : error.Error.Message
Message = error.Error is null ? "Error" : error.Error.Message
};
return StatusCode(StatusCodes.Status500InternalServerError, r);
}

View File

@ -1,14 +1,10 @@
using Infineon.Monitoring.MonA;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.ViewModels;
using OI.Metrology.Viewer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OI.Metrology.Viewer.Controllers;
@ -17,14 +13,14 @@ public class ExportController : Controller
{
private readonly ILogger _Logger;
private readonly bool _IsTestDatabase;
private readonly IMetrologyRepo _Repo;
private readonly AppSettings _AppSettings;
private readonly IMetrologyRepository _MetrologyRepository;
public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepo repo)
public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepository metrologyRepository)
{
_Repo = repo;
_Logger = logger;
_AppSettings = appSettings;
_MetrologyRepository = metrologyRepository;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -52,14 +48,14 @@ public class ExportController : Controller
[Route("/ExportData")]
public ActionResult ExportData(Export model)
{
ToolType toolType = null;
ToolType? toolType = null;
if (string.IsNullOrEmpty(model.ToolType))
ModelState.AddModelError("Exception", "Invalid selection");
else
{
if (model.StartTime > model.EndTime)
ModelState.AddModelError("EndTime", "End time must be after start time");
IEnumerable<ToolType> toolTypes = _Repo.GetToolTypes();
IEnumerable<ToolType> toolTypes = _MetrologyRepository.GetToolTypes();
toolType = toolTypes.Where(tt => tt.ID.ToString() == model.ToolType).SingleOrDefault();
if (toolType is null)
ModelState.AddModelError("ToolType", "Invalid selection");
@ -73,7 +69,7 @@ public class ExportController : Controller
DateTime startDT = model.StartDate.Date.Add(model.StartTime.TimeOfDay);
DateTime endDT = model.EndDate.Date.Add(model.EndTime.TimeOfDay);
return DoCSVExport(toolType.ToolTypeName, toolType.ExportSPName, startDT, endDT);
return DoCSVExport(toolType?.ToolTypeName, toolType?.ExportSPName, startDT, endDT);
}
catch (Exception ex)
{
@ -86,22 +82,17 @@ public class ExportController : Controller
return View("Index", model);
}
protected ActionResult DoCSVExport(string toolTypeName, string spName, DateTime startTime, DateTime endTime)
protected ActionResult DoCSVExport(string? toolTypeName, string? spName, DateTime startTime, DateTime endTime)
{
string fileName = string.Format("Export_{0}_{1:yyyyMMddHHmm}_to_{2:yyyyMMddHHmm}.csv", toolTypeName, startTime, endTime);
StringBuilder sb = new();
System.Data.DataTable dt = _Repo.ExportData(spName, startTime, endTime);
if (spName is null)
throw new NullReferenceException(nameof(spName));
System.Data.DataTable dt = _MetrologyRepository.ExportData(spName, startTime, endTime);
_ = sb.AppendLine(GetColumnHeaders(dt));
foreach (System.Data.DataRow dr in dt.Rows)
{
_ = sb.AppendLine(GetRowData(dr));
}
byte[] contents = Encoding.UTF8.GetBytes(sb.ToString());
return File(contents, "application/octet-stream", fileName);
}
@ -112,10 +103,13 @@ public class ExportController : Controller
{
if (i > 0)
_ = r.Append(',');
object v = dr[i];
if (!Convert.IsDBNull(v))
_ = r.Append(FormatForCSV(Convert.ToString(v)));
{
string? c = Convert.ToString(v);
if (c is not null)
_ = r.Append(FormatForCSV(c));
}
}
return r.ToString();
}
@ -135,16 +129,13 @@ public class ExportController : Controller
protected static string FormatForCSV(string v)
{
StringBuilder r = new(v.Length + 2);
bool doubleQuoted = false;
StringBuilder r = new(v.Length + 2);
if (v.StartsWith(' ') || v.EndsWith(' ') || v.Contains(',') || v.Contains('"'))
{
_ = r.Append('"');
doubleQuoted = true;
}
foreach (char c in v)
{
_ = c switch
@ -154,10 +145,8 @@ public class ExportController : Controller
_ => r.Append(c),
};
}
if (doubleQuoted)
_ = r.Append('"');
return r.ToString();
}

View File

@ -1,20 +1,19 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.ViewModels;
using OI.Metrology.Viewer.Models;
using System;
namespace OI.Metrology.Viewer.Controllers;
public class PagesController : Controller
{
private readonly IMetrologyRepo _Repo;
private readonly bool _IsTestDatabase;
private readonly IMetrologyRepository _MetrologyRepository;
public PagesController(AppSettings appSettings, IMetrologyRepo repo)
public PagesController(AppSettings appSettings, IMetrologyRepository metrologyRepository)
{
_Repo = repo;
_MetrologyRepository = metrologyRepository;
_IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase);
}
@ -48,7 +47,7 @@ public class PagesController : Controller
};
if (headerid > 0)
{
m.HeaderAttachmentID = _Repo.GetHeaderAttachmentID(tooltypeid, headerid);
m.HeaderAttachmentID = _MetrologyRepository.GetHeaderAttachmentID(tooltypeid, headerid);
}
return View(m);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +1,26 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace OI.Metrology.Viewer.Models;
public class AppSettings
public record AppSettings(string ApiLoggingContentTypes,
string ApiLoggingPathPrefixes,
string ApiLogPath,
string AttachmentPath,
string BuildNumber,
string Company,
string ConnectionString,
string GitCommitSeven,
string InboundApiAllowedIPList,
bool IsDevelopment,
bool IsStaging,
string MonAResource,
string MonASite,
string OI2SqlConnectionString,
string OIExportPath,
string URLs,
string WorkingDirectoryName)
{
public string ApiLoggingContentTypes { init; get; }
public string ApiLoggingPathPrefixes { init; get; }
public string ApiLogPath { init; get; }
public string AttachmentPath { init; get; }
public string BuildNumber { init; get; }
public string Company { init; get; }
public string ConnectionString { init; get; }
public string GitCommitSeven { init; get; }
public string InboundApiAllowedIPList { init; get; }
public string MonAResource { init; get; }
public string MonASite { init; get; }
public string Oi2SqlConnectionString { init; get; }
public string OIExportPath { init; get; }
public string URLs { init; get; }
public string WorkingDirectoryName { init; get; }
[JsonConstructor]
public AppSettings(string apiLoggingContentTypes,
string apiLoggingPathPrefixes,
string apiLogPath,
string attachmentPath,
string buildNumber,
string company,
string connectionString,
string gitCommitSeven,
string inboundApiAllowedIPList,
string monAResource,
string monASite,
string oi2SqlConnectionString,
string oiExportPath,
string urls,
string workingDirectoryName)
{
ApiLoggingContentTypes = apiLoggingContentTypes;
ApiLoggingPathPrefixes = apiLoggingPathPrefixes;
ApiLogPath = apiLogPath;
AttachmentPath = attachmentPath;
BuildNumber = buildNumber;
Company = company;
ConnectionString = connectionString;
GitCommitSeven = gitCommitSeven;
InboundApiAllowedIPList = inboundApiAllowedIPList;
MonAResource = monAResource;
MonASite = monASite;
Oi2SqlConnectionString = oi2SqlConnectionString;
OIExportPath = oiExportPath;
URLs = urls;
WorkingDirectoryName = workingDirectoryName;
}
public override string ToString()
{
string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });

View File

@ -1,4 +1,3 @@
using Microsoft.Extensions.Configuration;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
@ -18,6 +17,8 @@ public class AppSettings
[Display(Name = "Connection String"), Required] public string ConnectionString { get; set; }
[Display(Name = "Git Commit Seven"), Required] public string GitCommitSeven { get; set; }
[Display(Name = "Inbound Api Allowed IP List"), Required] public string InboundApiAllowedIPList { get; set; }
[Display(Name = "Is Development"), Required] public bool? IsDevelopment { get; set; }
[Display(Name = "Is Staging"), Required] public bool? IsStaging { get; set; }
[Display(Name = "MonA Resource"), Required] public string MonAResource { get; set; }
[Display(Name = "MonA Site"), Required] public string MonASite { get; set; }
[Display(Name = "Oi 2 Sql Connection String"), Required] public string Oi2SqlConnectionString { get; set; }
@ -33,9 +34,45 @@ public class AppSettings
return result;
}
private static Models.AppSettings Get(AppSettings appSettings)
private static Models.AppSettings Get(AppSettings? appSettings)
{
Models.AppSettings result;
if (appSettings is null)
throw new NullReferenceException(nameof(appSettings));
if (appSettings.ApiLoggingContentTypes is null)
throw new NullReferenceException(nameof(ApiLoggingContentTypes));
if (appSettings.ApiLoggingPathPrefixes is null)
throw new NullReferenceException(nameof(ApiLoggingPathPrefixes));
if (appSettings.ApiLogPath is null)
throw new NullReferenceException(nameof(ApiLogPath));
if (appSettings.AttachmentPath is null)
throw new NullReferenceException(nameof(AttachmentPath));
if (appSettings.BuildNumber is null)
throw new NullReferenceException(nameof(BuildNumber));
if (appSettings.Company is null)
throw new NullReferenceException(nameof(Company));
if (appSettings.ConnectionString is null)
throw new NullReferenceException(nameof(ConnectionString));
if (appSettings.GitCommitSeven is null)
throw new NullReferenceException(nameof(GitCommitSeven));
if (appSettings.InboundApiAllowedIPList is null)
throw new NullReferenceException(nameof(InboundApiAllowedIPList));
if (appSettings.IsDevelopment is null)
throw new NullReferenceException(nameof(IsDevelopment));
if (appSettings.IsStaging is null)
throw new NullReferenceException(nameof(IsStaging));
if (appSettings.MonAResource is null)
throw new NullReferenceException(nameof(MonAResource));
if (appSettings.MonASite is null)
throw new NullReferenceException(nameof(MonASite));
if (appSettings.Oi2SqlConnectionString is null)
throw new NullReferenceException(nameof(Oi2SqlConnectionString));
if (appSettings.OIExportPath is null)
throw new NullReferenceException(nameof(OIExportPath));
if (appSettings.URLs is null)
throw new NullReferenceException(nameof(URLs));
if (appSettings.WorkingDirectoryName is null)
throw new NullReferenceException(nameof(WorkingDirectoryName));
result = new(
appSettings.ApiLoggingContentTypes,
appSettings.ApiLoggingPathPrefixes,
@ -46,6 +83,8 @@ public class AppSettings
appSettings.ConnectionString,
appSettings.GitCommitSeven,
appSettings.InboundApiAllowedIPList,
appSettings.IsDevelopment.Value,
appSettings.IsStaging.Value,
appSettings.MonAResource,
appSettings.MonASite,
appSettings.Oi2SqlConnectionString,
@ -58,7 +97,7 @@ public class AppSettings
public static Models.AppSettings Get(IConfigurationRoot configurationRoot)
{
Models.AppSettings result;
AppSettings appSettings = configurationRoot.Get<AppSettings>();
AppSettings? appSettings = configurationRoot.Get<AppSettings>();
result = Get(appSettings);
return result;
}

View File

@ -6,13 +6,13 @@
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<ImplicitUsings>disable</ImplicitUsings>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<LangVersion>10.0</LangVersion>
<Nullable>disable</Nullable>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="logs\**" />
@ -26,22 +26,25 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.123" />
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="jQuery" Version="3.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="jQuery" Version="3.6.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Serilog.AspNetCore.Ingestion" Version="1.0.0-dev-00032" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.4" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj" />
<ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="moves\" />
@ -58,5 +61,8 @@
<None Include="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Data\Mike\service-shop.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,19 +1,14 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting.WindowsServices;
using Microsoft.Extensions.Logging;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Services;
using OI.Metrology.Viewer.Models;
using OI.Metrology.Viewer.Repositories;
using OI.Metrology.Viewer.Repository;
using OI.Metrology.Viewer.Services;
using Serilog;
using System;
using System.IO;
using System.Reflection;
namespace OI.Metrology.Viewer;
@ -25,7 +20,7 @@ public class Program
{
string webRootPath;
Assembly assembly = Assembly.GetExecutingAssembly();
string assemblyName = assembly.GetName()?.Name;
string? assemblyName = assembly.GetName()?.Name;
if (string.IsNullOrEmpty(assemblyName))
throw new Exception();
string baseAssemblyName = assemblyName.Split('.')[0];
@ -63,14 +58,27 @@ public class Program
{
_ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
_ = webApplicationBuilder.Services.AddControllersWithViews();
_ = new MetrologyRepo(new SQLDbConnectionFactory(appSettings), null);
#pragma warning disable CS8600, CS8602, CS8603, CS8604, CS8625
_ = new MetrologyRepository(new SQLDbConnectionFactory(appSettings), null);
#pragma warning restore
_ = webApplicationBuilder.Services.AddDistributedMemoryCache();
_ = webApplicationBuilder.Services.AddMemoryCache();
_ = webApplicationBuilder.Services.AddSingleton<AppSettings, AppSettings>(_ => appSettings);
AppSettingsRepository appSettingsRepository = new(appSettings);
ClientSettingsRepository clientSettingsRepository = new(appSettings);
_ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
_ = webApplicationBuilder.Services.AddSingleton<IInboundRepository, InboundRepository>();
_ = webApplicationBuilder.Services.AddSingleton<IToolTypesRepository, ToolTypesRepository>();
_ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>();
_ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository>(_ => appSettingsRepository);
_ = webApplicationBuilder.Services.AddSingleton<IClientSettingsRepository>(_ => clientSettingsRepository);
_ = webApplicationBuilder.Services.AddSingleton<IServiceShopOrderRepository, ServiceShopOrderRepository>();
_ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
_ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
_ = webApplicationBuilder.Services.AddScoped<IMetrologyRepo, MetrologyRepo>();
_ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>();
_ = webApplicationBuilder.Services.AddScoped<IMetrologyRepository, MetrologyRepository>();
_ = webApplicationBuilder.Services.AddSwaggerGen();
_ = webApplicationBuilder.Services.AddSession(sessionOptions =>
{
@ -84,8 +92,10 @@ public class Program
_ = webApplicationBuilder.Services.AddSingleton<IHostLifetime, WindowsServiceLifetime>();
_ = webApplicationBuilder.Logging.AddEventLog(settings =>
{
#pragma warning disable CA1416
if (string.IsNullOrEmpty(settings.SourceName))
settings.SourceName = webApplicationBuilder.Environment.ApplicationName;
#pragma warning restore
});
}
WebApplication webApplication = webApplicationBuilder.Build();

View File

@ -0,0 +1,37 @@
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Viewer.Models;
using System.Text.Json;
namespace OI.Metrology.Viewer.Repository;
public class AppSettingsRepository : IAppSettingsRepository
{
private readonly AppSettings _AppSettings;
public AppSettingsRepository(AppSettings appSettings) => _AppSettings = appSettings;
public List<string> GetAppSettings()
{
List<string> results = new();
string json = JsonSerializer.Serialize(_AppSettings);
JsonElement jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
JsonProperty[] jsonProperties = jsonElement.EnumerateObject().ToArray();
foreach (JsonProperty jsonProperty in jsonProperties)
results.Add(jsonProperty.Value.ToString());
if (!_AppSettings.IsDevelopment)
throw new Exception("Shouldn't expose!");
return results;
}
List<string> IAppSettingsRepository.GetAppSettings() => GetAppSettings();
public string GetBuildNumberAndGitCommitSeven()
{
string result = string.Concat(_AppSettings.BuildNumber, '-', _AppSettings.GitCommitSeven);
return result;
}
string IAppSettingsRepository.GetBuildNumberAndGitCommitSeven() => GetBuildNumberAndGitCommitSeven();
}

View File

@ -0,0 +1,36 @@
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Viewer.Models;
using System.Net;
namespace OI.Metrology.Viewer.Repository;
public class ClientSettingsRepository : IClientSettingsRepository
{
private readonly AppSettings _AppSettings;
public ClientSettingsRepository(AppSettings appSettings) => _AppSettings = appSettings;
public List<string> GetClientSettings(IPAddress? remoteIpAddress)
{
List<string> results = new();
if (remoteIpAddress is null)
results.Add(nameof(remoteIpAddress));
else
results.Add(remoteIpAddress.ToString());
if (!_AppSettings.IsDevelopment)
throw new Exception("Shouldn't expose!");
return results;
}
List<string> IClientSettingsRepository.GetClientSettings(IPAddress? remoteIpAddress) => GetClientSettings(remoteIpAddress);
public string GetIpAddress(IPAddress? remoteIpAddress)
{
string result = remoteIpAddress is null ? string.Empty : remoteIpAddress.ToString();
return result;
}
string IClientSettingsRepository.GetIpAddress(IPAddress? remoteIpAddress) => GetIpAddress(remoteIpAddress);
}

View File

@ -0,0 +1,88 @@
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System.Net;
namespace OI.Metrology.Viewer.Repository;
public class InboundRepository : IInboundRepository
{
private readonly Serilog.ILogger _Log;
public InboundRepository() => _Log = Serilog.Log.ForContext<InboundRepository>();
bool IInboundRepository.IsIPAddressAllowed(string inboundApiAllowedIPList, IPAddress? remoteIP)
{
if (string.IsNullOrWhiteSpace(inboundApiAllowedIPList))
return true;
if (remoteIP is null)
return false;
byte[] remoteIPBytes = remoteIP.GetAddressBytes();
string[] allowedIPs = inboundApiAllowedIPList.Split(';');
foreach (string ip in allowedIPs)
{
IPAddress? parsedIP;
if (IPAddress.TryParse(ip, out parsedIP))
{
if (parsedIP.GetAddressBytes().SequenceEqual(remoteIPBytes))
return true;
}
}
return false;
}
// this is the main endpoint, it accepts a JSON message that contains both the header and data records together
// tooltype is the ToolTypeName column from the ToolType table
// JToken is how you can accept a JSON message without deserialization.
// Using "string" doesn't work because ASP.NET Core will expect a json encoded string, not give you the actual string.
DataResponse IInboundRepository.Data(IMetrologyRepository metrologyRepository, IInboundDataService inboundDataService, string tooltype, JToken jsonbody)
{
DataResponse result = new();
ToolType? toolType = metrologyRepository.GetToolTypeByName(tooltype);
if (toolType is null)
result.Errors.Add("Invalid tool type: " + tooltype);
else
{
List<ToolTypeMetadata> metaData = metrologyRepository.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
if (metaData is null)
result.Errors.Add("Invalid metadata for tool type: " + tooltype);
else if (jsonbody is null)
result.Errors.Add("Invalid json");
else
inboundDataService.ValidateJSONFields(jsonbody, 0, metaData, result.Errors, result.Warnings);
if (metaData is not null && jsonbody is not null && !result.Errors.Any())
{
try
{
result.HeaderID = inboundDataService.DoSQLInsert(jsonbody, toolType, metaData);
result.Success = result.HeaderID > 0;
}
catch (Exception ex) { result.Errors.Add(ex.Message); }
}
}
return result;
}
// this is the endpoint for attaching a field. It is not JSON, it is form-data/multipart like an HTML form because that's the normal way.
// header ID is the ID value from the Header table
// datauniqueid is the Title value from the Data/Detail table
string? IInboundRepository.AttachFile(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, string tooltype, long headerid, string datauniqueid, string fileName, object uploadedFile)
{
string? result = null;
ToolType toolType = metrologyRepository.GetToolTypeByName(tooltype);
if (toolType is null)
result = $"Invalid tool type: {tooltype}";
string filename = Path.GetFileName(fileName);
if (string.IsNullOrWhiteSpace(filename))
result = "Empty filename";
if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
result = "Invalid filename";
if (result is null && toolType is not null)
attachmentsService.SaveAttachment(toolType, headerid, datauniqueid, filename, uploadedFile);
return result;
}
}

View File

@ -2,22 +2,22 @@
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Transactions;
#pragma warning disable CS8600, CS8602, CS8603, CS8604, CS8625
namespace OI.Metrology.Viewer.Repositories;
public class MetrologyRepo : IMetrologyRepo
public class MetrologyRepository : IMetrologyRepository
{
private readonly IMemoryCache _Cache;
private readonly IDbConnectionFactory _DBConnectionFactory;
public MetrologyRepo(IDbConnectionFactory dbConnectionFactory, IMemoryCache memoryCache)
public MetrologyRepository(IDbConnectionFactory dbConnectionFactory, IMemoryCache memoryCache)
{
_Cache = memoryCache;
_DBConnectionFactory = dbConnectionFactory;
@ -139,10 +139,10 @@ public class MetrologyRepo : IMetrologyRepo
// build field map
foreach (ToolTypeMetadata f in fields)
{
if ((f.ApiName != null) && f.ApiName.Contains('\\'))
if ((f.ApiName is not null) && f.ApiName.Contains('\\'))
{
string n = f.ApiName.Split('\\')[0].Trim().ToUpper();
if (containerField == null)
if (containerField is null)
containerField = n;
else if (!string.Equals(containerField, n))
throw new Exception("Only one container field is allowed");
@ -156,7 +156,7 @@ public class MetrologyRepo : IMetrologyRepo
}
}
if (containerField == null)
if (containerField is null)
{
// No container field, just insert a single row
@ -167,7 +167,7 @@ public class MetrologyRepo : IMetrologyRepo
// Find the container field in the json
JProperty contJP = jsonrow.Children<JProperty>().Where(c => string.Equals(c.Name.Trim(), containerField, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
if ((contJP != null) && (contJP.Value is JArray array))
if ((contJP is not null) && (contJP.Value is JArray array))
{
JArray contRows = array;
@ -220,11 +220,11 @@ public class MetrologyRepo : IMetrologyRepo
{
string apifield = jp.Name.Trim().ToUpper();
if (fieldmap.ContainsKey(apifield))
if (fieldmap.TryGetValue(apifield, out string value))
{
string parmname = string.Format("@p{0}", parmnumber);
columns += string.Format("[{0}],", fieldmap[apifield]);
columns += string.Format("[{0}],", value);
parms += parmname;
parms += ",";
parmnumber += 1;
@ -236,18 +236,18 @@ public class MetrologyRepo : IMetrologyRepo
}
}
if ((containerrow != null) && (containerFieldmap != null))
if ((containerrow is not null) && (containerFieldmap is not null))
{
foreach (JProperty jp in containerrow.Children<JProperty>())
{
string apifield = jp.Name.Trim().ToUpper();
if (containerFieldmap.ContainsKey(apifield))
if (containerFieldmap.TryGetValue(apifield, out string value))
{
string parmname = string.Format("@p{0}", parmnumber);
columns += string.Format("[{0}],", containerFieldmap[apifield]);
columns += string.Format("[{0}],", value);
parms += parmname;
parms += ",";
parmnumber += 1;
@ -267,7 +267,7 @@ public class MetrologyRepo : IMetrologyRepo
cmd.CommandText = columns.TrimEnd(',') + parms.TrimEnd(',') + ";SELECT SCOPE_IDENTITY();";
object o = cmd.ExecuteScalar();
if ((o == null) || Convert.IsDBNull(o))
if ((o is null) || Convert.IsDBNull(o))
throw new Exception("Unexpected query result");
return Convert.ToInt64(o);
}
@ -307,7 +307,7 @@ public class MetrologyRepo : IMetrologyRepo
{
if (!firstField)
_ = sb.Append(',');
if (f.GridAttributes != null && f.GridAttributes.Contains("isNull"))
if (f.GridAttributes is not null && f.GridAttributes.Contains("isNull"))
{
_ = sb.AppendFormat("{0}", "ISNULL(" + f.ColumnName + ", '')[" + f.ColumnName + "]");
}
@ -325,11 +325,11 @@ public class MetrologyRepo : IMetrologyRepo
public DataTable GetHeaders(int toolTypeId, DateTime? startTime, DateTime? endTime, int? pageNo, int? pageSize, long? headerId, out long totalRecords)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
DataTable dt = new();
@ -418,11 +418,11 @@ public class MetrologyRepo : IMetrologyRepo
public DataTable GetData(int toolTypeId, long headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
DataTable dt = new();
@ -513,7 +513,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetHeaderAttachmentID(int toolTypeId, long headerId)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -525,7 +525,7 @@ public class MetrologyRepo : IMetrologyRepo
public string GetHeaderInsertDate(int toolTypeId, long headerId)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -557,7 +557,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetDataAttachmentID(int toolTypeId, long headerId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -570,7 +570,7 @@ public class MetrologyRepo : IMetrologyRepo
public string GetDataInsertDate(int toolTypeId, long headerId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -603,7 +603,7 @@ public class MetrologyRepo : IMetrologyRepo
public DataSet GetOIExportData(int toolTypeId, long headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
if (string.IsNullOrWhiteSpace(tt.OIExportSPName))
@ -632,7 +632,7 @@ public class MetrologyRepo : IMetrologyRepo
public IEnumerable<HeaderCommon> GetHeaderTitles(int toolTypeId, int? pageNo, int? pageSize, out long totalRecords)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -661,11 +661,11 @@ public class MetrologyRepo : IMetrologyRepo
public IEnumerable<KeyValuePair<string, string>> GetHeaderFields(int toolTypeId, long headerid)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
IEnumerable<ToolTypeMetadata> md = GetToolTypeMetadataByToolTypeID(toolTypeId);
if (md == null)
if (md is null)
throw new Exception("Invalid tool type metadata");
List<KeyValuePair<string, string>> r = new();
@ -692,10 +692,10 @@ public class MetrologyRepo : IMetrologyRepo
foreach (ToolTypeMetadata m in md.Where(m => m.Header == true && m.TableDisplayOrder > 0).OrderBy(m => m.TableDisplayOrder))
{
string v = "";
if (dr != null)
if (dr is not null)
{
object o = dr[m.ColumnName];
if (o != null && !Convert.IsDBNull(o))
if (o is not null && !Convert.IsDBNull(o))
v = Convert.ToString(o);
}
KeyValuePair<string, string> kvp = new(m.DisplayTitle, v);
@ -714,7 +714,7 @@ public class MetrologyRepo : IMetrologyRepo
public int UpdateReviewDate(int toolTypeId, long headerId, bool clearDate)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -736,7 +736,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetHeaderAttachmentIDByTitle(int toolTypeId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -748,7 +748,7 @@ public class MetrologyRepo : IMetrologyRepo
public Guid GetDataAttachmentIDByTitle(int toolTypeId, string title)
{
ToolType tt = GetToolTypeByID(toolTypeId);
if (tt == null)
if (tt is null)
throw new Exception("Invalid tool type ID");
using DbConnection conn = GetDbConnection();
@ -757,5 +757,5 @@ public class MetrologyRepo : IMetrologyRepo
return conn.ExecuteScalar<Guid>(sql, param: new { Title = title });
}
DataTable IMetrologyRepo.GetDataSharePoint(int toolTypeId, string headerId) => throw new NotImplementedException();
DataTable IMetrologyRepository.GetDataSharePoint(int toolTypeId, string headerId) => throw new NotImplementedException();
}

View File

@ -0,0 +1,56 @@
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.ViewModels;
using Serilog.Context;
using System.Text.Json;
namespace OI.Metrology.Viewer.Repository;
public class ServiceShopOrderRepository : IServiceShopOrderRepository
{
private readonly Serilog.ILogger _Log;
public ServiceShopOrderRepository() => _Log = Serilog.Log.ForContext<ServiceShopOrderRepository>();
private static ServiceShopOrder[] GetServiceShopOrders(Shared.Models.ServiceShop? serviceShop)
{
ServiceShopOrder[] result = IServiceShopOrder.GetServiceShopOrders(serviceShop);
return result;
}
private static Shared.Models.ServiceShop? GetServiceShopOrders()
{
Shared.Models.ServiceShop? result;
string jsonFile;
string checkDirectory = Path.Combine(AppContext.BaseDirectory, "Data/Mike");
if (Directory.Exists(checkDirectory))
jsonFile = Path.Combine(checkDirectory, "service-shop.json");
else
jsonFile = Path.Combine(AppContext.BaseDirectory, "service-shop.json");
string json = File.ReadAllText(jsonFile);
result = JsonSerializer.Deserialize<Shared.Models.ServiceShop>(json);
return result;
}
async Task<ServiceShopOrder[]> IServiceShopOrderRepository.GetAllServiceShopOrders()
{
ServiceShopOrder[] results;
string? methodName = IMethodName.GetActualAsyncMethodName();
using (LogContext.PushProperty("MethodName", methodName))
{
_Log.Debug("() => ...");
Shared.Models.ServiceShop? serviceShop = await Task.Run(GetServiceShopOrders);
results = GetServiceShopOrders(serviceShop);
}
return results.ToArray();
}
async Task<ServiceShopOrder[]> IServiceShopOrderRepository.GetServiceShopOrders(string id)
{
ServiceShopOrder[] results;
Shared.Models.ServiceShop? serviceShop = await Task.Run(GetServiceShopOrders);
results = GetServiceShopOrders(serviceShop).Where(l => l.Id == id).ToArray();
return results;
}
}

View File

@ -0,0 +1,177 @@
using Newtonsoft.Json;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
namespace OI.Metrology.Viewer.Repository;
public class ToolTypesRepository : IToolTypesRepository
{
private readonly Serilog.ILogger _Log;
public ToolTypesRepository() => _Log = Serilog.Log.ForContext<ToolTypesRepository>();
// Get a list of tooltypes, returns just Name and ID
object IToolTypesRepository.Index(IMetrologyRepository metrologyRepository)
{
var r = new
{
Results = metrologyRepository.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID })
};
return r;
}
// Gets the metadata for a tooltype, accepts a parameter which sorts the results
// This is used to setup the grid displays on the UI
object IToolTypesRepository.GetToolTypeMetadata(IMetrologyRepository metrologyRepository, int id, string sortby)
{
ToolType tt = metrologyRepository.GetToolTypeByID(id);
IEnumerable<ToolTypeMetadata> md = metrologyRepository.GetToolTypeMetadataByToolTypeID(id);
if (string.Equals(sortby, "grid", StringComparison.OrdinalIgnoreCase))
md = md.OrderBy(f => f.GridDisplayOrder).ToList();
if (string.Equals(sortby, "table", StringComparison.OrdinalIgnoreCase))
md = md.OrderBy(f => f.GridDisplayOrder).ToList();
var r = new
{
Results = new
{
ToolType = tt,
Metadata = md
}
};
return r;
}
// Gets headers, request/response format is to allow paging with igniteUI
// The headerid parameter is used for navigating directly to a header, when the button is clicked in Awaiting Dispo
string IToolTypesRepository.GetHeaders(IMetrologyRepository metrologyRepository, int id, DateTime? datebegin, DateTime? dateend, int? page, int? pagesize, long? headerid)
{
string result;
long totalRecs;
System.Data.DataTable dt = metrologyRepository.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs);
var r = new
{
Results = dt,
TotalRows = totalRecs,
};
result = JsonConvert.SerializeObject(r);
return result;
}
// Gets header titles, used in the Run Headers UI
string IToolTypesRepository.GetHeaderTitles(IMetrologyRepository metrologyRepository, int id, int? page, int? pagesize)
{
string result;
long totalRecs;
IEnumerable<HeaderCommon> dt = metrologyRepository.GetHeaderTitles(id, page, pagesize, out totalRecs);
var r = new
{
Results = dt,
TotalRows = totalRecs,
};
result = JsonConvert.SerializeObject(r);
return result;
}
// Get all of the fields for a header, used with the Run Header UI
string IToolTypesRepository.GetHeaderFields(IMetrologyRepository metrologyRepository, int id, long headerid)
{
string result;
var r = new
{
Results = metrologyRepository.GetHeaderFields(id, headerid).Select(x => new { Column = x.Key, x.Value }).ToList()
};
result = JsonConvert.SerializeObject(r);
return result;
}
// Get the data for a header, used with the Run Info UI
string IToolTypesRepository.GetData(IMetrologyRepository metrologyRepository, int id, long headerid)
{
string result;
var r = new
{
Results = metrologyRepository.GetData(id, headerid)
};
result = JsonConvert.SerializeObject(r);
return result;
}
// Display an attachment, used for Run Info - note it is by tool type ID and attachment GUID, so it is best for internal use
(string?, string?, Stream?) IToolTypesRepository.GetAttachment(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, int toolTypeId, string tabletype, string attachmentId, string filename)
{
Stream? stream = null;
string? message = null;
Guid attachmentIdParsed;
string? contenttype = null;
ToolType tt = metrologyRepository.GetToolTypeByID(toolTypeId);
bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);
if (!Guid.TryParse(attachmentId, out attachmentIdParsed))
message = "Invalid attachment id";
else
{
try
{
// figure out what content type to use. this is very simple because there are only two types being used
contenttype = "application/pdf";
if (filename.ToLower().TrimEnd().EndsWith(".txt"))
contenttype = "text/plain";
// Get attachment stream and feed it to the client
stream = attachmentsService.GetAttachmentStreamByAttachmentId(tt, header, attachmentIdParsed, filename);
}
catch (Exception ex) { message = ex.Message; }
}
return new(message, contenttype, stream);
}
// This endpoint triggers writing of the OI Export file
Exception? IToolTypesRepository.OIExport(IMetrologyRepository metrologyRepository, string oiExportPath, int toolTypeId, long headerid)
{
Exception? result = null;
// Call the export stored procedure
_Log.Debug($"Exporting to <{oiExportPath}>");
System.Data.DataSet ds = metrologyRepository.GetOIExportData(toolTypeId, headerid);
try
{
// The SP must return 3 result tables
if (ds.Tables.Count != 3)
throw new Exception("Error exporting, invalid results");
// The first table has just one row, which is the export filename
if (ds.Tables[0].Rows.Count != 1)
throw new Exception("Error exporting, invalid filename");
string? filename = Convert.ToString(ds.Tables[0].Rows[0][0]);
// The second table has the header data
if (ds.Tables[1].Rows.Count != 1)
throw new Exception("Error exporting, invalid header data");
System.Text.StringBuilder sb = new();
foreach (object? o in ds.Tables[1].Rows[0].ItemArray)
{
if ((o is not null) && (!Convert.IsDBNull(o)))
_ = sb.Append(Convert.ToString(o));
_ = sb.Append('\t');
}
// The third table has the detail data
foreach (System.Data.DataRow dr in ds.Tables[2].Rows)
{
foreach (object? o in dr.ItemArray)
{
if ((o is not null) && (!Convert.IsDBNull(o)))
_ = sb.Append(Convert.ToString(o));
_ = sb.Append('\t');
}
}
_ = sb.AppendLine();
// The output file will only have one line, the header columns are output first
// Then each detail rows has it's columns appended
// H1, H2, H3, D1.1, D1.2, D1.3, D2.1, D2.2, D2.3, etc
// Write the file
File.WriteAllText(Path.Join(oiExportPath, filename), sb.ToString());
}
catch (Exception ex) { result = ex; }
return result;
}
}

View File

@ -1,32 +1,32 @@
using System;
using System.Globalization;
using System.IO;
using System.Globalization;
namespace OI.Metrology.Viewer.Services;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using OI.Metrology.Viewer.Models;
public class AttachmentsService : IAttachmentsService
{
private readonly AppSettings _AppSettings;
private readonly IMetrologyRepository _MetrologyRepository;
private readonly IMetrologyRepo _Repo;
public AttachmentsService(AppSettings appSettings, IMetrologyRepo repo)
public AttachmentsService(AppSettings appSettings, IMetrologyRepository metrologyRepository)
{
_AppSettings = appSettings;
_Repo = repo;
_MetrologyRepository = metrologyRepository;
}
protected Stream GetAttachmentStream(string tableName, Guid attachmentId, string filename)
protected Stream GetAttachmentStream(string? tableName, Guid attachmentId, string filename)
{
if (attachmentId.Equals(Guid.Empty))
throw new Exception("No attachments found");
DateTime insertDate = Convert.ToDateTime(_Repo.GetAttachmentInsertDateByGUID(tableName, attachmentId));
if (tableName is null)
throw new NullReferenceException(nameof(tableName));
DateTime insertDate = Convert.ToDateTime(_MetrologyRepository.GetAttachmentInsertDateByGUID(tableName, attachmentId));
int year = insertDate.Year;
DateTime d = insertDate;
CultureInfo cul = CultureInfo.CurrentCulture;
@ -50,28 +50,28 @@ public class AttachmentsService : IAttachmentsService
public Stream GetAttachmentStreamByTitle(ToolType toolType, bool header, string title, string filename)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
Guid attachmentId;
string tableName;
string? tableName;
if (header)
{
tableName = toolType.HeaderTableName;
attachmentId = _Repo.GetHeaderAttachmentIDByTitle(toolType.ID, title);
attachmentId = _MetrologyRepository.GetHeaderAttachmentIDByTitle(toolType.ID, title);
}
else
{
tableName = toolType.DataTableName;
attachmentId = _Repo.GetDataAttachmentIDByTitle(toolType.ID, title);
attachmentId = _MetrologyRepository.GetDataAttachmentIDByTitle(toolType.ID, title);
}
return GetAttachmentStream(tableName, attachmentId, filename);
}
public Stream GetAttachmentStreamByAttachmentId(ToolType toolType, bool header, Guid attachmentId, string filename)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
string tableName;
string? tableName;
if (header)
tableName = toolType.HeaderTableName;
else
@ -79,27 +79,27 @@ public class AttachmentsService : IAttachmentsService
return GetAttachmentStream(tableName, attachmentId, filename);
}
private void SaveAttachment(ToolType toolType, long headerId, string dataUniqueId, string filename, Microsoft.AspNetCore.Http.IFormFile uploadedFile)
private void SaveAttachment(ToolType toolType, long headerId, string dataUniqueId, string filename, IFormFile uploadedFile)
{
if (toolType == null)
if (toolType is null)
throw new Exception("Invalid tool type");
using System.Transactions.TransactionScope trans = _Repo.StartTransaction();
using System.Transactions.TransactionScope trans = _MetrologyRepository.StartTransaction();
Guid attachmentId = Guid.Empty;
DateTime insertDate = new();
string tableName = "";
string? tableName = "";
if (string.IsNullOrWhiteSpace(dataUniqueId))
{
attachmentId = _Repo.GetHeaderAttachmentID(toolType.ID, headerId);
insertDate = Convert.ToDateTime(_Repo.GetHeaderInsertDate(toolType.ID, headerId));
attachmentId = _MetrologyRepository.GetHeaderAttachmentID(toolType.ID, headerId);
insertDate = Convert.ToDateTime(_MetrologyRepository.GetHeaderInsertDate(toolType.ID, headerId));
tableName = toolType.HeaderTableName;
}
else
{
attachmentId = _Repo.GetDataAttachmentID(toolType.ID, headerId, dataUniqueId);
insertDate = Convert.ToDateTime(_Repo.GetDataInsertDate(toolType.ID, headerId, dataUniqueId));
attachmentId = _MetrologyRepository.GetDataAttachmentID(toolType.ID, headerId, dataUniqueId);
insertDate = Convert.ToDateTime(_MetrologyRepository.GetDataInsertDate(toolType.ID, headerId, dataUniqueId));
// Get Date for new directory name
tableName = toolType.DataTableName;
@ -131,7 +131,7 @@ public class AttachmentsService : IAttachmentsService
public void SaveAttachment(ToolType toolType, long headerId, string dataUniqueId, string filename, object uploadedFile)
{
Microsoft.AspNetCore.Http.IFormFile formFile = (Microsoft.AspNetCore.Http.IFormFile)uploadedFile;
IFormFile formFile = (IFormFile)uploadedFile;
SaveAttachment(toolType, headerId, dataUniqueId, filename, formFile);
}

View File

@ -1,18 +1,17 @@
using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System;
using System.Collections.Generic;
using System.Linq;
#pragma warning disable CS8600, CS8602, CS8603, CS8604, CS8625
namespace OI.Metrology.Viewer.Services;
public class InboundDataService : IInboundDataService
{
private readonly IMetrologyRepo _Repo;
private readonly IMetrologyRepository _MetrologyRepository;
public InboundDataService(IMetrologyRepo repo) => _Repo = repo;
public InboundDataService(IMetrologyRepository metrologyRepository) => _MetrologyRepository = metrologyRepository;
public long DoSQLInsert(JToken jsonbody, ToolType toolType, List<ToolTypeMetadata> metaData)
{
@ -37,11 +36,11 @@ public class InboundDataService : IInboundDataService
long headerId = 0;
using (System.Transactions.TransactionScope transScope = _Repo.StartTransaction())
using (System.Transactions.TransactionScope transScope = _MetrologyRepository.StartTransaction())
{
try
{
_Repo.PurgeExistingData(toolType.ID, uniqueId);
_MetrologyRepository.PurgeExistingData(toolType.ID, uniqueId);
}
catch (Exception ex)
{
@ -50,7 +49,7 @@ public class InboundDataService : IInboundDataService
try
{
headerId = _Repo.InsertToolDataJSON(jsonbody, -1, metaData, toolType.HeaderTableName);
headerId = _MetrologyRepository.InsertToolDataJSON(jsonbody, -1, metaData, toolType.HeaderTableName);
}
catch (Exception ex)
{
@ -60,11 +59,11 @@ public class InboundDataService : IInboundDataService
int detailrow = 1;
try
{
if (detailsArray != null)
if (detailsArray is not null)
{
foreach (JToken detail in detailsArray)
{
_ = _Repo.InsertToolDataJSON(detail, headerId, metaData, toolType.DataTableName);
_ = _MetrologyRepository.InsertToolDataJSON(detail, headerId, metaData, toolType.DataTableName);
detailrow += 1;
}
}
@ -133,7 +132,7 @@ public class InboundDataService : IInboundDataService
if (jp.First is JArray array)
detailsArray = array;
else if ((jp.First is JValue value) && (value.Value == null))
else if ((jp.First is JValue value) && (value.Value is null))
detailsArray = null;
else
errors.Add("Invalid details field");
@ -169,7 +168,7 @@ public class InboundDataService : IInboundDataService
}
// if a Details container if found, process it by recursion
if (detailsArray != null)
if (detailsArray is not null)
{
int i = 1;
foreach (JToken detail in detailsArray)
@ -189,7 +188,7 @@ public class InboundDataService : IInboundDataService
{
// get the json data for this container field, ex: Points
JProperty contJP = jsonbody.Children<JProperty>().Where(jp => string.Equals(jp.Name, containerField, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
if ((contJP != null) && (contJP.Value is JArray array))
if ((contJP is not null) && (contJP.Value is JArray array))
{
JArray contJPArray = array;

View File

@ -1,10 +1,11 @@
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Viewer.Models;
using System;
using System.Data.Common;
using System.Data.SqlClient;
namespace OI.Metrology.Viewer.Repositories;
#pragma warning disable CS8600, CS8602, CS8603, CS8604, CS8625
namespace OI.Metrology.Viewer.Services;
public class SQLDbConnectionFactory : IDbConnectionFactory
{

View File

@ -73,7 +73,7 @@
<li><a href="https://oi-metrology-viewer-archive.mes.infineon.com/" target="_blank">Archive</a></li>
</ul>
<p class="navbar-text navbar-right">
@User.Identity.Name
@User.Identity?.Name
</p>
</div>
</div>

View File

@ -1,26 +1,6 @@
{
"AllowedHosts": "*",
"ApiLoggingContentTypes": "application/json",
"ApiLoggingPathPrefixes": "/api/inbound",
"ApiLogPath": "D:\\Metrology\\MetrologyAPILogs",
"AttachmentPath": "\\\\messv02ecc1.ec.local\\EC_Metrology_Si\\MetrologyAttachments",
"BuildNumber": "1",
"Company": "Infineon Technologies Americas Corp.",
"ConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Integrated Security=True;Initial Catalog=Metrology;",
"GitCommitSeven": "1234567",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Log4netProvider": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"InboundApiAllowedIPList": "",
"IsDevelopment": true,
"MonAResource": "OI_Metrology_Viewer_IFX",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
"OIExportPath": "\\\\openinsight-db-srv.na.infineon.com\\apps\\Metrology\\Data",
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
@ -58,6 +38,5 @@
"Application": "Sample"
}
},
"URLs": "https://localhost:7130;http://localhost:5126",
"WorkingDirectoryName": "IFXApps"
"URLs": "https://localhost:7130;http://localhost:5126"
}

View File

@ -17,6 +17,8 @@
}
},
"InboundApiAllowedIPList": "",
"IsDevelopment": false,
"IsStaging": false,
"MonAResource": "OI_Metrology_Viewer_EC",
"MonASite": "auc",
"Oi2SqlConnectionString": "Data Source=messv01ec.ec.local\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;",
@ -26,7 +28,7 @@
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "Debug",