This is a follow up question of this one.
Since the original question was posted, it has turned out that in some cases I want the code to be synchronous and in others to be async. I have updated the code the 'handle registration' method is now fully sync I believe:
public void HandleRegistration(IProgress<string> progressInfo = null)
{
Task.Run((() => HandleRegistrationAsync(progressInfo))).Wait();
}
Since that I have also created a 'handle updates' logic (which is more or less identical). Method returns true if new version is available and false if it is not.
public bool HandleUpdates(IProgress<string> progressInfo = null)
{
return Task.Run((() => HandleUpdatesAsync(progressInfo))).Result;
}
And I have made their async counterparts public as well.
Now, when I am using the code, and I want to block the main thread, I use simply updateHelper.HandleUpdates(prog);
. This blocks the thread pretty well. However, I am not sure about the following - what is the difference between:
Task.Run(() => regHelp.HandleRegistration(progressInfo1)); //appears to not block the thread
Task.Run(() => regHelp.HandleRegistrationAsync(progressInfo1)); //appears to not block the thread
regHelp.HandleRegistrationAsync(prog0); //without 'await', appears to block the thread, but not 'fully'
Also, I believe that I could only use await regHelp.HandleRegistrationAsync(prog0);
in an async method.
If I am using it for example in the constructor (e.g. public MainWindow()
or in static void Main(string[] args)
), the proper way would be to use Task.Run();
for it?
As for other changes, I have replaced const value for connString
in my app with a connection string settings from Azure. As for naming of instances of RegistrationHelper
, I will keep that in mind - though in my non-English head it sounds pretty good. It's only used once per app in two lines of code anyways.
As for the security, I have already introduced something very basic a couple of weeks ago.
I am sending a little string (a 'password' let's say) along with the HTTP request. And at the beginning of each API method I check if the 'password' provided is correct. If not, then return with an error code.
[Route("api/getver/{programname}")]
public async Task<string> GetLatestVersionNumberAsync(string programname)
{
if (!BasicAuthProvider.PerformBasicAuthentication(this.Request))
{
return "-960";
}
//rest of code
}
public static class BasicAuthProvider
{
private static string BasicAuthenticationKey
{
get { return ConfigurationManager.ConnectionStrings["BasicAuthenticationKey"].ConnectionString; }
//I keep it as connection string because it's not 'visible' by default in manage interface of Azure, though I suppose it's //a litte difference if any
}
public static bool PerformBasicAuthentication(HttpRequestMessage message)
{
var authorization = message.Headers.Authorization;
var decodedHeader = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(authorization.Parameter));
if (decodedHeader.Equals(BasicAuthenticationKey))
{
return true;
}
return false;
}
}
Now, as for the HttpPost,
I have handled it as follows:
For the data that I want to post, I have created a class in my UserController
:
public class UserInfo
{
public string Email { get; set; }
public string UserName { get; set; }
public string MachineName { get; set; }
}
Then, the action is as follows:
[Route("registerbyemail")]
[HttpPost]
public async Task<int> RegisterUserByEmailAsync(UserInfo info)
{
if (!string.IsNullOrEmpty(info.Email) && !string.IsNullOrEmpty(info.UserName) && !string.IsNullOrEmpty(info.MachineName))
{
return await RegisterUserEmailAsync(info.Email, info.UserName, info.MachineName);
}
else
{
return (int)(ResultCodes.Post | ResultCodes.IncorrectInputParameters | ResultCodes.RegisterUser);
}
}
And the generic extension method that calls it is:
internal static async Task<string> SendPostMessageAsync(Uri apiUri, string action, Dictionary<string, string> values, bool throwExceptions)
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = apiUri;
client.DefaultRequestHeaders.Accept.Clear();
var byteArray = Encoding.ASCII.GetBytes(ApiHelper.DefaultApiCreds);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var content = new FormUrlEncodedContent(values);
HttpResponseMessage response = await client.PostAsync(action, content);
return response.IsSuccessStatusCode
? response.Content.ReadAsStringAsync().Result
: string.Format("-{0}", Bj.ConcatInts(100, (int)response.StatusCode));
}
}
catch (Exception)
{
//handle it
}
}