First off, I'm a total newbie when it comes to Web APIs. This is actually my first attempt. I'm beginner-intermediate when it comes to Winforms.
That being said, I've created a Web API (ASP.NET Web Application) that basically interfaces with a SQL server to retrieve entries in a certain database. I've also created a simple Winform application that uses the API to get that information from the database. I come from a procedural background, so my OO-approach might be a little messy. Originally, my Winform app was written moreprodecurally, and everything worked fine, i.e. I could call the API from the UI (Form1.cs) and I would get back the correct data.
However, once I began abstracting out, and creating a more OO-environment, I had to implement a lot of Tasks, asyncs, awaits, etc. When I step through my code, the correct data is returned; however, it locks the UI.
In my Form1.cs, I have the following:
string selected = radioButtonArray.FirstOrDefault(c => c.Checked).Name; BusinessLogicLayer BLL = new BusinessLogicLayer(serialNumbersToPrint); BLL.Process(selected);
This takes the name of the radiobutton that is checked and passes it into the BussinessLogicLayer.cs class. The "serialNumbersToPrint" is just a list of objects that would get populated once the code is successfully executed.
Going to my Business Logic Layer, I have the following:
public class BusinessLogicLayer
{
private List<AbstractDatabaseContents> localCollection;
public BusinessLogicLayer(List<AbstractDatabaseContents> ObjectList)
{
localCollection = ObjectList;
}
public void Process(string deviceType)
{
DeviceType dT = new DeviceType(localCollection);
Strategy strategy = dT.deviceType(deviceType).Result;
var context = new StrategyContext(strategy);
context.ContextInterface();
}
}Pretty straightforward, I think. Here's the DeviceType class:
public class DeviceType
{
private List<AbstractDatabaseContents> localCollection;
private Strategy sd;
public string lastSerial { get; set; }
public DeviceType(List<AbstractDatabaseContents> ObjectList)
{
localCollection = ObjectList;
}
public async Task<Strategy> deviceType(string deviceType)
{
sd = null;
if (deviceType == "radioCamOldUS")
{
Object lS = await SqlAPI.GetSerialAsync("CAMOLD");
lastSerial = lS.ToString();
int dType = 1;
sd = new Cam(lastSerial, dType, localCollection);
}
return sd;
}
}And finally, my SqlAPI class:
public class SqlAPI
{
public static async Task<object> GetSerialAsync(string path)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
Object sn = null;
client.BaseAddress = new Uri("https://localhost:44319/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync($"api/DeviceData?deviceType={path}").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
sn = await response.Content.ReadAsAsync<object>();
}
return sn;
}
}
}The above code is all in my WinForm application. The first few lines in the Web API Controller in the web application is:
public class DeviceDataController : ApiController
{
public DeviceDataController()
{
using (ManufacturingEntities entities = new ManufacturingEntities())
{
entities.Configuration.ProxyCreationEnabled = false;
}
}
public List<string> sn = new List<string>();
public List<string> sn2 = new List<string>();
public List<int> intList = new List<int>();
public List<int> intList2 = new List<int>();
public async Task<object> Get(string deviceType)
{
using (ManufacturingEntities entities = new ManufacturingEntities())
{
List<Device_Devices> CAM = entities.Device_Devices.Where(c => c.DeviceTypeID == 1).
Where(c => SqlFunctions.IsNumeric(c.SerialNumber) > 0).
Where(c => String.Compare(c.SerialNumber, "100000") > 0 &&
String.Compare(c.SerialNumber, "999999") <= 0).
ToList();
sn = CAM.Select(o => o.SerialNumber).ToList();
foreach (var item in sn)
{
int i = Convert.ToInt32(item);
intList.Add(i);
}
if (deviceType == "CAMNEW")
{
List<int> Result = new List<int>(intList.FindAll(c => c > 100000 && c < 999999));
Result.Sort();
int first = Result[0];
return Result[Result.Count - 1];
}
if (deviceType == "CAMOLD")
{
List<int> Result = new List<int>(intList.FindAll(c => c > 0 && c < 99999));
Result.Sort();
int first = Result[0];
return Result[Result.Count - 1];
}
}
}
}Again, the problem is deadlock. It works when I, e.g., put a button on the UI of the WinForm, and then program the click event like:
private async void metroButton1_Click(object sender, EventArgs e)
{
Object lS = await SqlAPI.GetSerialAsync("CAMOLD");
string lastSerial = lS.ToString();
txtStatus.AppendText(lastSerial);
}I'm not entirely sure why it's deadlocking like this. I've read a few articles about why things deadlock, but in this particular case, I couldn't find the reason why.