3 Commits

Author SHA1 Message Date
Matthew Burke 87a73ff24b Refactor to api connections. Update Checker. 2023-08-24 12:45:56 -04:00
Matthew Burke 4a4bcc81e0 Created Unit Test Project 2023-08-14 17:10:38 -04:00
Matthew Burke 19153c9d02 Cleaned references and imports 2023-07-27 19:15:49 -04:00
35 changed files with 570 additions and 253 deletions
+6
View File
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.33529.622
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PWAPPv2", "PWAPPv2\PWAPPv2.csproj", "{45E26AF8-41D7-4308-A2C8-D55A0350DB47}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PWAPPv2", "PWAPPv2\PWAPPv2.csproj", "{45E26AF8-41D7-4308-A2C8-D55A0350DB47}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{164B9220-F337-4E88-B619-0C52C502B9C4}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Debug|Any CPU.Build.0 = Debug|Any CPU {45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Release|Any CPU.ActiveCfg = Release|Any CPU {45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Release|Any CPU.Build.0 = Release|Any CPU {45E26AF8-41D7-4308-A2C8-D55A0350DB47}.Release|Any CPU.Build.0 = Release|Any CPU
{164B9220-F337-4E88-B619-0C52C502B9C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{164B9220-F337-4E88-B619-0C52C502B9C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{164B9220-F337-4E88-B619-0C52C502B9C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{164B9220-F337-4E88-B619-0C52C502B9C4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+2 -8
View File
@@ -1,10 +1,4 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace PWAPPv2 namespace PWAPPv2
{ {
@@ -16,7 +10,7 @@ namespace PWAPPv2
public static string[] Args; public static string[] Args;
void app_Startup(object sender, StartupEventArgs e) void app_Startup(object sender, StartupEventArgs e)
{ {
if(e.Args.Length > 0) if (e.Args.Length > 0)
{ {
Args = e.Args; Args = e.Args;
} }
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<Config>
<ODhost>10.0.1.107</ODhost>
<ODuser>root</ODuser>
<ODpassword></ODpassword>
<pwuserid>testdoctor</pwuserid>
<pwpassword>testdoctor</pwpassword>
<pwpracticeid>210</pwpracticeid>
<pwapiid>12345678</pwapiid>
</Config>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<Config>
<PWBaseURI>http://apipatientweb.azurewebsites.net/</PWBaseURI>
<PWUpdateURI>https://localhost:44354/api/PWAppVersion</PWUpdateURI>
</Config>
+1 -1
View File
@@ -69,7 +69,7 @@
<GroupBox Header="Refer To" HorizontalAlignment="Left" Height="55" Margin="0,120,0,0" VerticalAlignment="Top" Width="458" Grid.Column="1"> <GroupBox Header="Refer To" HorizontalAlignment="Left" Height="55" Margin="0,120,0,0" VerticalAlignment="Top" Width="458" Grid.Column="1">
<ComboBox x:Name="boxReferTo" HorizontalAlignment="Left" Margin="0,10,-2,0" VerticalAlignment="Top" Width="448"/> <ComboBox x:Name="boxReferTo" HorizontalAlignment="Left" Margin="0,10,-2,0" VerticalAlignment="Top" Width="448"/>
</GroupBox> </GroupBox>
<CheckBox x:Name="contact" Content="Contact Doctor" HorizontalAlignment="Left" Margin="0,175,0,0" VerticalAlignment="Top" Grid.Column="1" Checked="CheckBox_Checked" Height="15" Width="101"/> <CheckBox x:Name="contact" Content="Contact Patient" HorizontalAlignment="Left" Margin="0,175,0,0" VerticalAlignment="Top" Grid.Column="1" Checked="CheckBox_Checked" Height="15" Width="101"/>
<GroupBox Header="Remarks" HorizontalAlignment="Left" Height="150" Margin="10,347,0,0" VerticalAlignment="Top" Width="309"> <GroupBox Header="Remarks" HorizontalAlignment="Left" Height="150" Margin="10,347,0,0" VerticalAlignment="Top" Width="309">
<RichTextBox x:Name="fieldRemakrs" HorizontalAlignment="Left" Height="127" VerticalAlignment="Top" Width="299" Margin="0,0,-2,0"> <RichTextBox x:Name="fieldRemakrs" HorizontalAlignment="Left" Height="127" VerticalAlignment="Top" Width="299" Margin="0,0,-2,0">
<FlowDocument> <FlowDocument>
+80 -42
View File
@@ -1,19 +1,10 @@
using System; using Microsoft.Win32;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Forms;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Win32;
/** /**
* TODO: * TODO:
@@ -27,52 +18,100 @@ namespace PWAPPv2
/// </summary> /// </summary>
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
static Source.APIConfig apiconfig = new Source.APIConfig(); static Source.APIConfig apiconfig;// = new Source.APIConfig();
static Source.Database.DatabaseConfig DataConfig; static Source.Database.DatabaseConfig DataConfig;
static Source.API.APIConnection apiConnection; static Source.API.APIConnection apiConnection;
Source.DataObjects.APICredentials apiCreds; Source.DataObjects.APICredentials apiCreds;
Source.API.PWApiConnection pwapiConnection;
Source.DataObjects.ComboBoxData TypeBox; Source.DataObjects.ComboBoxData TypeBox;
Source.DataObjects.ComboBoxData ToBox; Source.DataObjects.ComboBoxData ToBox;
Source.DataObjects.ComboBoxData FromBox; Source.DataObjects.ComboBoxData FromBox;
Source.Config.Configuration practiceConfig;
Source.Config.Configuration universalConfig;
string[] args; string[] args;
Source.Patient patient; Source.Patient patient;
List<Source.DataObjects.PWImage> images; List<Source.DataObjects.PWImage> images;
string ConfigPath = "C:\\PWAPP\\Config\\Config.xml";
public MainWindow() public MainWindow()
{ {
try try
{ {
args = App.Args; args = App.Args;
} }
catch(Exception) catch (Exception)
{ } { }
images = new List<Source.DataObjects.PWImage>(); try
{
practiceConfig = new Source.Config.Configuration(".\\Config\\PracticeConfig.xml");
universalConfig = new Source.Config.Configuration(".\\Config\\UniversalConfig.xml");
}
catch
(Exception)
{
System.Windows.MessageBox.Show("An error has occured in the configurations files.");
}
apiconfig.LoadConfig("./Config/Config.xml"); pwapiConnection = new Source.API.PWApiConnection(practiceConfig, universalConfig);
DataConfig = new Source.Database.DatabaseConfig("./Config/Config.xml");
Source.Database.DatabaseConnection dbcon = new Source.Database.DatabaseConnection(DataConfig);
apiCreds = new Source.DataObjects.APICredentials(apiconfig); try
{
if(pwapiConnection.CheckForUpdate() == true)
{
string message = "An update is available! Would you like to install it?";
string title = "Update available!";
MessageBoxButtons buttons = MessageBoxButtons.YesNo;
DialogResult result = System.Windows.Forms.MessageBox.Show(message, title, buttons);
if(result == System.Windows.Forms.DialogResult.Yes)
{
System.Windows.MessageBox.Show("HAHA NO UPDATE FOR YOU!");
}
}
}
catch (Exception)
{
System.Windows.MessageBox.Show("An error has occured while checking for updates");
}
apiConnection = new Source.API.APIConnection("http://apipatientweb.azurewebsites.net/", try
apiCreds); {
images = new List<Source.DataObjects.PWImage>();
InitializeComponent();
PopulateComboBoxes(); Source.Database.DatabaseConnection dbcon = new Source.Database.DatabaseConnection(practiceConfig);
patient = new Source.Patient(); apiconfig = new Source.APIConfig(practiceConfig, universalConfig);
apiCreds = new Source.DataObjects.APICredentials(apiconfig);
apiConnection = new Source.API.APIConnection(universalConfig.Get("PWBaseURI"), apiCreds);
patient.BuildFromDatabase(dbcon, args[0]); InitializeComponent();
this.DataContext = new Source.PatientGUIAdapter(patient); PopulateComboBoxes();
patient = new Source.Patient();
patient.BuildFromDatabase(dbcon, args[0]);
this.DataContext = new Source.PatientGUIAdapter(patient);
}
catch(NullReferenceException)
{
}
catch(Exception e)
{
System.Windows.MessageBox.Show(e.Message);
}
} }
private void PopulateComboBoxes() private void PopulateComboBoxes()
@@ -122,15 +161,15 @@ namespace PWAPPv2
{ {
TypeBox.GetSelectedID(); TypeBox.GetSelectedID();
} }
catch(Source.DataObjects.ReferralTypeDefaultException) catch (Source.DataObjects.ReferralTypeDefaultException)
{ {
} }
catch(Source.DataObjects.InvalidReferralTypeException) catch (Source.DataObjects.InvalidReferralTypeException)
{ {
} }
catch(NullReferenceException) catch (NullReferenceException)
{ {
} }
@@ -146,7 +185,7 @@ namespace PWAPPv2
private void Button_Click_1(object sender, RoutedEventArgs e) private void Button_Click_1(object sender, RoutedEventArgs e)
{ {
Source.DataObjects.Referral referral; Source.DataObjects.Referral referral;
if(images.Count == 0) if (images.Count == 0)
{ {
referral = new Source.DataObjects.Referral(apiCreds, patient, referral = new Source.DataObjects.Referral(apiCreds, patient,
(Source.DataObjects.ReferralTypeBox)TypeBox, (Source.DataObjects.ReferralTypeBox)TypeBox,
@@ -167,23 +206,23 @@ namespace PWAPPv2
{ {
string referralString = referral.ToJsonString(); string referralString = referral.ToJsonString();
string result = apiConnection.SendPostRequestAsync("api/PWMakeReferral", referralString); string result = apiConnection.SendPostRequestAsync("api/PWMakeReferral", referralString);
if(images.Count > 0) if (images.Count > 0)
{ {
foreach(Source.DataObjects.PWImage im in images) foreach (Source.DataObjects.PWImage im in images)
{ {
Source.DataObjects.Attachment att = new Source.DataObjects.Attachment(apiCreds, im, result); Source.DataObjects.Attachment att = new Source.DataObjects.Attachment(apiCreds, im, result);
string json = att.ToJsonString(); string json = att.ToJsonString();
apiConnection.SendPostRequestAsync("api/PWAttachment", json); apiConnection.SendPostRequestAsync("api/PWAttachment", json);
} }
MessageBox.Show("Referral added successfully!"); System.Windows.MessageBox.Show("Referral added successfully!");
} }
else else
{ {
MessageBox.Show(result); System.Windows.MessageBox.Show(result);
} }
this.Close(); this.Close();
} }
catch(Source.DataObjects.Referral.InvalidReferalDataException) catch (Source.DataObjects.Referral.InvalidReferalDataException)
{ {
} }
@@ -192,12 +231,12 @@ namespace PWAPPv2
//AddImage Button //AddImage Button
private void Button_Click_2(object sender, RoutedEventArgs e) private void Button_Click_2(object sender, RoutedEventArgs e)
{ {
OpenFileDialog openFileDialog = new OpenFileDialog(); System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
openFileDialog.Multiselect = true; openFileDialog.Multiselect = true;
openFileDialog.Filter = "Image files (*.jpg,*.jpeg)|*.jpg;*.jpeg"; openFileDialog.Filter = "Image files (*.jpg,*.jpeg)|*.jpg;*.jpeg";
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
if(openFileDialog.ShowDialog() == true) if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{ {
foreach (string filename in openFileDialog.FileNames) foreach (string filename in openFileDialog.FileNames)
{ {
@@ -205,7 +244,7 @@ namespace PWAPPv2
{ {
images.Add(new Source.DataObjects.PWImage(filename)); images.Add(new Source.DataObjects.PWImage(filename));
} }
catch(NullReferenceException) catch (NullReferenceException)
{ {
images = new List<Source.DataObjects.PWImage>(); images = new List<Source.DataObjects.PWImage>();
images.Add(new Source.DataObjects.PWImage(filename)); images.Add(new Source.DataObjects.PWImage(filename));
@@ -222,7 +261,7 @@ namespace PWAPPv2
ImageList.Items.Add(CreateImageGridItem(image)); ImageList.Items.Add(CreateImageGridItem(image));
} }
} }
catch(NullReferenceException) catch (NullReferenceException)
{ } { }
} }
@@ -230,7 +269,7 @@ namespace PWAPPv2
private void Button_Click_3(object sender, RoutedEventArgs e) private void Button_Click_3(object sender, RoutedEventArgs e)
{ {
int index = ImageList.SelectedIndex; int index = ImageList.SelectedIndex;
if(index == -1) if (index == -1)
{ {
return; return;
} }
@@ -251,10 +290,9 @@ namespace PWAPPv2
{ {
Grid imageGrid = new Grid(); Grid imageGrid = new Grid();
imageGrid.Width = 477; imageGrid.Width = 477;
imageGrid.HorizontalAlignment = HorizontalAlignment.Left; imageGrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
imageGrid.VerticalAlignment = VerticalAlignment.Top; imageGrid.VerticalAlignment = VerticalAlignment.Top;
imageGrid.ShowGridLines = true; imageGrid.ShowGridLines = true;
imageGrid.Background = new SolidColorBrush(Colors.LightSteelBlue);
ColumnDefinition imageColumn = new ColumnDefinition(); ColumnDefinition imageColumn = new ColumnDefinition();
imageColumn.Width = new GridLength(50); imageColumn.Width = new GridLength(50);
+2 -1
View File
@@ -210,10 +210,11 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="PwImage.cs" />
<Compile Include="Source\API\APIConfig.cs" /> <Compile Include="Source\API\APIConfig.cs" />
<Compile Include="Source\API\APIConnection.cs" /> <Compile Include="Source\API\APIConnection.cs" />
<Compile Include="Source\API\APIRequestBuilder.cs" /> <Compile Include="Source\API\APIRequestBuilder.cs" />
<Compile Include="Source\API\PWApiConnection.cs" />
<Compile Include="Source\Config\Configuration.cs" />
<Compile Include="Source\Database\DatabaseConfig.cs" /> <Compile Include="Source\Database\DatabaseConfig.cs" />
<Compile Include="Source\Database\DatabaseConnection.cs" /> <Compile Include="Source\Database\DatabaseConnection.cs" />
<Compile Include="Source\DataObjects\APICredentials.cs" /> <Compile Include="Source\DataObjects\APICredentials.cs" />
-2
View File
@@ -1,6 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
-6
View File
@@ -1,6 +0,0 @@
namespace PWAPPv2
{
internal class PwImage
{
}
}
+24 -8
View File
@@ -1,19 +1,35 @@
using System; using PWAPPv2.Source.Config;
using System.Collections.Generic; using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml; using System.Xml;
namespace PWAPPv2.Source namespace PWAPPv2.Source
{ {
class APIConfig public class APIConfig
{ {
public string PWUserID; public string PWUserID;
public string PWPassword; public string PWPassword;
public string PWPracticeID; public string PWPracticeID;
public string PWApiID; public string PWApiID;
public string PWBaseURI;
public string PWUpdateURI;
public string PWAppVersion;
public APIConfig() { }
public APIConfig(Config.Configuration practiceConfig, Config.Configuration universalConfig)
{
PWUserID = practiceConfig.Get("pwuserid");
PWPassword = practiceConfig.Get("pwpassword");
PWPracticeID = practiceConfig.Get("pwpracticeid");
PWApiID = practiceConfig.Get("pwapiid");
PWBaseURI = universalConfig.Get("PWBaseURI");
PWUpdateURI = universalConfig.Get("PWUpdateURI");
PWAppVersion = universalConfig.Get("PWAppVersion");
}
public void LoadConfig(string path) public void LoadConfig(string path)
{ {
XmlDocument cfgDoc = new XmlDocument(); XmlDocument cfgDoc = new XmlDocument();
@@ -21,12 +37,12 @@ namespace PWAPPv2.Source
{ {
cfgDoc.Load(path); cfgDoc.Load(path);
} }
catch(XmlException) catch (XmlException)
{ {
Console.WriteLine("An error has occured parsing the config file."); Console.WriteLine("An error has occured parsing the config file.");
return; return;
} }
catch(System.IO.FileNotFoundException) catch (System.IO.FileNotFoundException)
{ {
Console.WriteLine("Config file could not be found!"); Console.WriteLine("Config file could not be found!");
return; return;
+84 -82
View File
@@ -1,50 +1,42 @@
using System; using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
using System.Collections.Generic; using System;
using System.Linq; using System.Diagnostics;
using System.Text; using System.IO;
using System.Threading.Tasks;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.IO; using System.Text;
using Newtonsoft.Json;
namespace PWAPPv2.Source.API namespace PWAPPv2.Source.API
{ {
class APIConnection public class APIConnection
{ {
private static string BaseURL; private static string BaseURL;
public DataObjects.APICredentials Credentials; public DataObjects.APICredentials Credentials;
private static bool ResponseReady = false;
private static string Response = ""; HttpClient Client;
public APIConnection(string baseUrl, DataObjects.APICredentials credentials) public APIConnection(string baseUrl, DataObjects.APICredentials credentials)
{ {
Credentials = credentials; Credentials = credentials;
BaseURL = baseUrl; BaseURL = baseUrl;
Client = new HttpClient();
Client.BaseAddress = new Uri(BaseURL);
Client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
} }
public string GetResponse()
{
while (!ResponseReady) ;
return Response;
}
/// <summary>
/// Dont use. Doesn't work, sillyhead.
/// </summary>
/// <param name="Call"></param>
public static async void APIGet(string Call) public static async void APIGet(string Call)
{ {
//WebRequest request = WebRequest.Create(BaseURL + Call);
//request.Method = "GET";
//request.ContentType = "application/json; charset=utf-8";
//var response = (HttpWebResponse)request.GetResponse();
//string text;
//using (var sr = new StreamReader(response.GetResponseStream()))
//{
// text = sr.ReadToEnd();
//}
//return text;
using (var client = new HttpClient()) using (var client = new HttpClient())
{ {
client.BaseAddress = new Uri(BaseURL); client.BaseAddress = new Uri(BaseURL);
@@ -56,66 +48,16 @@ namespace PWAPPv2.Source.API
} }
} }
public string APIPost() /// <summary>
{ /// Send a post requst without data. Essentially an advanced get since I was a retard when I wrote the original API.
string text; /// </summary>
try /// <param name="apiUri"></param>
{ /// <returns></returns>
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://apipatientweb.azurewebsites.net/api/PWReferralTypes");
request.Method = "POST";
request.ContentType = "application/json; charset=\"utf-8\"";
request.Accept = "application/json";
string postData = Source.API.APIRequestBuilder.BuildJsonBodyRequest(Credentials);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(postData);
request.ContentLength = data.Length;
Stream newStream = request.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
var response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
}
catch(WebException wex)
{
text = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();
}
return text;
}
public string SendPostRequestAsync(string apiUri) public string SendPostRequestAsync(string apiUri)
{ {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BaseURL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
StringContent contetnt = new StringContent(Credentials.ToJsonString(), Encoding.UTF8, "application/json"); StringContent contetnt = new StringContent(Credentials.ToJsonString(), Encoding.UTF8, "application/json");
var response = client.PostAsync(apiUri, contetnt).Result; var response = Client.PostAsync(apiUri, contetnt).Result;
if(response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
return "";
}
public string SendPostRequestAsync(string apiUri, string PostData)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BaseURL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
StringContent contetnt = new StringContent(PostData, Encoding.UTF8, "application/json");
var response = client.PostAsync(apiUri, contetnt).Result;
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
@@ -124,5 +66,65 @@ namespace PWAPPv2.Source.API
return ""; return "";
} }
/// <summary>
/// Send a post request with data
/// </summary>
/// <param name="apiUri"></param>
/// <param name="PostData"></param>
/// <returns></returns>
public string SendPostRequestAsync(string apiUri, string PostData)
{
StringContent contetnt = new StringContent(PostData, Encoding.UTF8, "application/json");
var response = Client.PostAsync(apiUri, contetnt).Result;
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
return "";
}
/// <summary>
/// Send a post request with the API credengials in the header of the request.
/// </summary>
/// <param name="apiUri"></param>
/// <param name="PostData"></param>
/// <returns></returns>
/// <exception cref="RequestFailedExcpetion"></exception>
public string SendPostWithCredsInHeader(string apiUri, string PostData)
{
Client.DefaultRequestHeaders.Add("UserID", Credentials.UserID);
Client.DefaultRequestHeaders.Add("Password", Credentials.Password);
Client.DefaultRequestHeaders.Add("PracticeID", Credentials.PracticeId);
Client.DefaultRequestHeaders.Add("ApiID", Credentials.APIid);
StringContent content = new StringContent(PostData, Encoding.UTF8, "application/json");
var response = Client.PostAsync(apiUri, content).Result;
Client.DefaultRequestHeaders.Remove("UserID");
Client.DefaultRequestHeaders.Remove("Password");
Client.DefaultRequestHeaders.Remove("PraticeID");
Client.DefaultRequestHeaders.Remove("ApiID");
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
throw new RequestFailedExcpetion(response.StatusCode.ToString());
}
}
public class RequestFailedExcpetion : Exception
{
public string RequestError;
public RequestFailedExcpetion(string errorCode)
{
RequestError = "Server responded with error code: " + errorCode;
}
} }
} }
+2 -8
View File
@@ -1,11 +1,5 @@
using System; using Newtonsoft.Json;
using System.Collections.Generic; using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
namespace PWAPPv2.Source.API namespace PWAPPv2.Source.API
{ {
+50
View File
@@ -0,0 +1,50 @@
using PWAPPv2.Source.DataObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.API
{
public class PWApiConnection
{
private APIConnection BaseConnection;
private APIConnection UpdateConnection;
private APICredentials Credentials;
private string AppVersion;
public PWApiConnection(Source.Config.Configuration practiceConfig, Source.Config.Configuration universalConfig)
{
Credentials = new APICredentials(practiceConfig);
BaseConnection = new APIConnection(universalConfig.Get("PWBaseURI"), Credentials);
UpdateConnection = new APIConnection(universalConfig.Get("PWUpdateURI"), Credentials);
AppVersion = universalConfig.Get("PWAppVersion");
}
public string PostToApi(string uri, string data)
{
return BaseConnection.SendPostRequestAsync(uri, data);
}
public string GetFromApi(string uri)
{
return BaseConnection.SendPostRequestAsync(uri);
}
public bool CheckForUpdate()
{
string currentVersion = UpdateConnection.SendPostWithCredsInHeader("", "");
currentVersion = currentVersion.Replace("\"", "");
if(currentVersion != AppVersion)
{
return true;
}
return false;
}
}
}
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;
namespace PWAPPv2.Source.Config
{
public class Configuration
{
private Dictionary<string, string> values;
public Configuration(string file)
{
values = new Dictionary<string, string>();
if(!File.Exists(file))
{
throw new ConfigFileNotFoundException();
}
string f = File.ReadAllText(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(f);
XmlNodeList xmlNodeList = xmlDoc.DocumentElement.ChildNodes;
foreach (XmlNode xmlNode in xmlNodeList)
{
values.Add(xmlNode.Name, xmlNode.InnerText);
}
}
public string Get(string key)
{
try
{
return values[key];
}
catch
{
throw new ConfigValueNotFoundException();
}
}
}
public class ConfigFileNotFoundException : Exception { }
public class ConfigValueNotFoundException: Exception { }
}
+15 -8
View File
@@ -1,18 +1,17 @@
using System; namespace PWAPPv2.Source.DataObjects
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
{ {
class APICredentials public class APICredentials
{ {
public string UserID; public string UserID;
public string Password; public string Password;
public string PracticeId; public string PracticeId;
public string APIid; public string APIid;
public APICredentials()
{
}
public APICredentials(Source.APIConfig config) public APICredentials(Source.APIConfig config)
{ {
UserID = config.PWUserID; UserID = config.PWUserID;
@@ -21,6 +20,14 @@ namespace PWAPPv2.Source.DataObjects
APIid = config.PWApiID; APIid = config.PWApiID;
} }
public APICredentials(Source.Config.Configuration practiceConfig)
{
UserID = practiceConfig.Get("pwuserid");
Password = practiceConfig.Get("pwpassword");
PracticeId = practiceConfig.Get("pwpracticeid");
APIid = practiceConfig.Get("pwapiid");
}
public string BuildJsonBodyContents() public string BuildJsonBodyContents()
{ {
return "'UserID':'" + UserID + "'," + return "'UserID':'" + UserID + "'," +
+1 -7
View File
@@ -1,10 +1,4 @@
using System; namespace PWAPPv2.Source.DataObjects
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
{ {
class Attachment class Attachment
{ {
+1 -7
View File
@@ -1,10 +1,4 @@
using System; using System.Windows.Controls;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
{ {
-4
View File
@@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
{ {
+2 -5
View File
@@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
{ {
@@ -18,11 +15,11 @@ namespace PWAPPv2.Source.DataObjects
public NumValList(string Content, char Delim) public NumValList(string Content, char Delim)
{ {
string[] split = Content.Split(Delim); string[] split = Content.Split(Delim);
if((split.Length % 2) != 0) if ((split.Length % 2) != 0)
{ {
throw new UnevenValuesException(); throw new UnevenValuesException();
} }
for(int i = 0; i < split.Length; i++) for (int i = 0; i < split.Length; i++)
{ {
this.Add(int.Parse(split[i]), split[i + 1]); this.Add(int.Parse(split[i]), split[i + 1]);
i++; i++;
+1 -7
View File
@@ -1,10 +1,4 @@
using System; namespace PWAPPv2.Source.DataObjects
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source.DataObjects
{ {
class NumValPair class NumValPair
{ {
+1 -6
View File
@@ -1,12 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Windows.Media.Imaging;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
{ {
@@ -1,9 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
-4
View File
@@ -1,9 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
+4 -8
View File
@@ -1,11 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Windows;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
{ {
@@ -40,7 +36,7 @@ namespace PWAPPv2.Source.DataObjects
string RemarksText = new TextRange(RemarksBox.Document.ContentStart, RemarksBox.Document.ContentEnd).Text; string RemarksText = new TextRange(RemarksBox.Document.ContentStart, RemarksBox.Document.ContentEnd).Text;
int contact = 0; int contact = 0;
if(ContactBox.IsChecked == true) if (ContactBox.IsChecked == true)
{ {
contact = 1; contact = 1;
} }
@@ -76,11 +72,11 @@ namespace PWAPPv2.Source.DataObjects
{ {
MessageBox.Show("Please select a referral type"); MessageBox.Show("Please select a referral type");
} }
catch(Source.DataObjects.ReferToDefaultException) catch (Source.DataObjects.ReferToDefaultException)
{ {
MessageBox.Show("Please select a refer to"); MessageBox.Show("Please select a refer to");
} }
catch(Source.DataObjects.ReferFromDefaultException) catch (Source.DataObjects.ReferFromDefaultException)
{ {
MessageBox.Show("Please select a refer from"); MessageBox.Show("Please select a refer from");
} }
@@ -1,9 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
namespace PWAPPv2.Source.DataObjects namespace PWAPPv2.Source.DataObjects
@@ -28,7 +24,7 @@ namespace PWAPPv2.Source.DataObjects
TypeID.Add(id); TypeID.Add(id);
} }
catch(Exception) catch (Exception)
{ {
throw new DataInvalidException(); throw new DataInvalidException();
} }
@@ -36,7 +32,7 @@ namespace PWAPPv2.Source.DataObjects
} }
foreach(string name in TypeName) foreach (string name in TypeName)
{ {
Add(name); Add(name);
} }
@@ -52,9 +48,9 @@ namespace PWAPPv2.Source.DataObjects
{ {
throw new ReferralTypeDefaultException(); throw new ReferralTypeDefaultException();
} }
for(int i = 0; i < TypeName.Count; i++) for (int i = 0; i < TypeName.Count; i++)
{ {
if(TypeName[i] == Selected) if (TypeName[i] == Selected)
{ {
return TypeID[i]; return TypeID[i];
} }
+2 -6
View File
@@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml; using System.Xml;
namespace PWAPPv2.Source.Database namespace PWAPPv2.Source.Database
@@ -22,12 +18,12 @@ namespace PWAPPv2.Source.Database
{ {
cfg.Load(path); cfg.Load(path);
} }
catch(XmlException) catch (XmlException)
{ {
Console.WriteLine("An error has occured parsing the config file."); Console.WriteLine("An error has occured parsing the config file.");
return; return;
} }
catch(System.IO.FileNotFoundException) catch (System.IO.FileNotFoundException)
{ {
Console.WriteLine("Config file could not be found!"); Console.WriteLine("Config file could not be found!");
} }
+12 -7
View File
@@ -1,13 +1,12 @@
using System; using MySqlConnector;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using MySqlConnector;
namespace PWAPPv2.Source.Database namespace PWAPPv2.Source.Database
{ {
/// <summary>
/// Class <c>DatabaseConnection</c> creates and maintains a connection to and OpenDental MySqlDatabase.
/// </summary>
class DatabaseConnection class DatabaseConnection
{ {
@@ -22,13 +21,19 @@ namespace PWAPPv2.Source.Database
Connection = new MySqlConnection(SqlString); Connection = new MySqlConnection(SqlString);
} }
public DatabaseConnection(Config.Configuration config)
{
SqlString = "server=" + config.Get("ODhost") + ";Uid=" + config.Get("ODuser") + ";database=" + config.Get("ODdatabase") + ";Pwd=" + config.Get("ODpassword");
Connection = new MySqlConnection(SqlString);
}
public void Connect() public void Connect()
{ {
try try
{ {
Connection.Open(); Connection.Open();
} }
catch(Exception) catch (Exception)
{ {
throw new DatabaseConnectionException(); throw new DatabaseConnectionException();
} }
+1 -5
View File
@@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source namespace PWAPPv2.Source
{ {
+1 -7
View File
@@ -1,10 +1,4 @@
using System; namespace PWAPPv2.Source
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PWAPPv2.Source
{ {
class PatientGUIAdapter class PatientGUIAdapter
{ {
+21
View File
@@ -0,0 +1,21 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using PWAPPv2.Source;
namespace UnitTests
{
[TestClass]
public class ConfigTest
{
[TestMethod]
public void TestGetPracticeConfigs()
{
PWAPPv2.Source.Config.Configuration configuration = new PWAPPv2.Source.Config.Configuration(".\\Config\\PracticeConfig.xml");
Assert.IsNotNull(configuration);
string apiKey = configuration.Get("pwapiid");
Assert.IsNotNull(apiKey);
}
}
}
+22
View File
@@ -0,0 +1,22 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace UnitTests
{
[TestClass]
public class PWConnectionTest
{
[TestMethod]
public void TestCheckUpdate()
{
PWAPPv2.Source.Config.Configuration practiceConfig = new PWAPPv2.Source.Config.Configuration(".\\Config\\PracticeConfig.xml");
PWAPPv2.Source.Config.Configuration universalConfig = new PWAPPv2.Source.Config.Configuration(".\\Config\\UniversalConfig.xml");
PWAPPv2.Source.API.PWApiConnection pwApiConnection = new PWAPPv2.Source.API.PWApiConnection(practiceConfig, universalConfig);
Assert.IsNotNull(pwApiConnection);
Assert.IsFalse(pwApiConnection.CheckForUpdate());
}
}
}
+20
View File
@@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("UnitTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UnitTests")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("164b9220-f337-4e88-b619-0c52c502b9c4")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+59
View File
@@ -0,0 +1,59 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using PWAPPv2.Source.API;
using PWAPPv2.Source.DataObjects;
// System.Threading.Tasks.Task<TResult>.Result.get returned "\"1|Endo|2|Implant|3|Oral Surgery|4|Ortho|5|Pedo|6|Perio|7|Restore|8|Other \\n\"" string
namespace UnitTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestV1Get()
{
APICredentials creds = new APICredentials();
creds.UserID = "testdoctor";
creds.Password = "testdoctor";
creds.PracticeId = "210";
creds.APIid = "12345678";
APIConnection conn = new APIConnection("http://apipatientweb.azurewebsites.net/", creds);
string res = conn.SendPostRequestAsync("api/PWReferralTypes");
Assert.AreEqual("\"1|Endo|2|Implant|3|Oral Surgery|4|Ortho|5|Pedo|6|Perio|7|Restore|8|Other \\n\"", res);
}
[TestMethod]
public void TestV2Get()
{
APICredentials creds = new APICredentials();
creds.UserID = "testdoctor";
creds.Password = "testdoctor";
creds.PracticeId = "210";
creds.APIid = "12345678";
APIConnection conn = new APIConnection("https://localhost:44354/", creds);
string res = conn.SendPostWithCredsInHeader("api/PWAppVersion", "");
}
[TestMethod]
[ExpectedException(typeof(RequestFailedExcpetion))]
public void TestInvalidCredentialsV2()
{
APICredentials creds = new APICredentials();
creds.UserID = "testdoctor";
creds.Password = "badPassword";
creds.PracticeId = "210";
creds.APIid = "12345678";
APIConnection conn = new APIConnection("https://localhost:44354/", creds);
string res = conn.SendPostWithCredsInHeader("api/PWAppVersion", "");
}
}
}
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{164B9220-F337-4E88-B619-0C52C502B9C4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UnitTests</RootNamespace>
<AssemblyName>UnitTests</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="UnitTest1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ConfigTest.cs" />
<Compile Include="PWConnectionTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PWAPPv2\PWAPPv2.csproj">
<Project>{45e26af8-41d7-4308-a2c8-d55a0350db47}</Project>
<Name>PWAPPv2</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.1.2\build\net45\MSTest.TestAdapter.targets')" />
</Project>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="2.1.2" targetFramework="net472" />
<package id="MSTest.TestFramework" version="2.1.2" targetFramework="net472" />
</packages>