I'm fairly new to C# so go easy on me.
I have a class UserData.
public class UserData
{
public int UserId { get; set; }
public string Token { get; set; }
public string ConversationID { get; set; }
}
And instantiate it in my main class.
public class Main {
var userDataObjects = new UserData();
userDataObjects.UserId = 5;
userDataObjects.Token = "sampleXh123xczx";
userDataObjects.ConversationID = "2";
protected DialogsTurn _GetDialog;
public main(){
_GetDialog = new DiagsTurn();
}
public override async Task OnTurnAsync()
{
await _GetDialog.GetNextDialog();
}
}
public class DialogsTurn : Controller
{
private readonly HttpClient client = new HttpClient();
private const string BASE_URL = "https://sample.net";
var userDataObjects = new UserData();
public async Task GetNextDialog()
{
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Get,
$"{BASE_URL}/api/Dialogs/GetNextDialog?Id={userDataObjects.UserId}");
request.Headers.Add("Accept", "application/json");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", userDataObjects.Token);
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<dynamic>(body).result;
UserDataExtractedDto.DialogTurnID = result.dialogId;
}
}
And once it was instantiated I need to call it from other classes.
Let's say in my DialogSTurn class I have a GetNextDialog method and I need the Token and UserId. I know I can that data as a parameter. But it's not the case for my application that I built.
Related
So, I have been struggling with this for a while now, but I am getting a bit further each day. But now I am really stuck.
What I am trying to do:
I have an automation account with a runbook (PowerShell)
I want to create a schedule
Then I want to connect that schedule to the runbook so the runbook is executed at a specific date and time.
I want to achieve this through C# with the Management API of Azure. I found a few webpages that should give me all the information I needed, but it doesn't work.
The first one is this: https://learn.microsoft.com/en-us/rest/api/automation/schedule/create-or-update?tabs=HTTP
I get this to work and I can see the schedule after I ran the code.
The second one is this: https://learn.microsoft.com/en-us/rest/api/automation/job-schedule/create?tabs=HTTP
And here I get stuck. I get a 404 error when I execute the request and I have no idea what I am doing wrong.
The code below is far from perfect, but it's a POC and not the actual application. I want to make it work before I refactor.
This class has all the logic for the schedule:
public class ScheduleLogic
{
const string subscriptionId = "######";
const string resourceGroupName = "######";
const string automationAccountName = "######";
const string tenantId = "######";
const string clientId = "######";
const string clientSecret = "######";
const string resourceId = "https://management.azure.com/";
public string accessToken { get; set; }
// THIS ONE DOESN'T WORK!
public async Task ConnectScheduleToRunbook(RunbookSchedule runbookSchedule)
{
StringContent body = new(JsonSerializer.Serialize(runbookSchedule));
body.Headers.ContentType = new MediaTypeHeaderValue("application/json");
string url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Automation/automationAccounts/{automationAccountName}/jobSchedules/{runbookSchedule.Properties.Schedule.JobScheduleId}?api-version=2019-06-01";
await ExecuteRequest(RequestType.Put, url, body);
}
public async Task CreateSchedule(Schedule schedule)
{
if (string.IsNullOrEmpty(schedule.JobScheduleId))
throw new Exception("Job schedule ID is empty");
StringContent body = new(JsonSerializer.Serialize(schedule));
body.Headers.ContentType = new MediaTypeHeaderValue("application/json");
string url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Automation/automationAccounts/{automationAccountName}/schedules/{schedule.JobScheduleId}?api-version=2019-06-01";
await ExecuteRequest(RequestType.Put, url, body);
}
public async Task DeleteSchedule(string scheduleName)
{
string url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Automation/automationAccounts/{automationAccountName}/schedules/{scheduleName}?api-version=2019-06-01";
await ExecuteRequest(RequestType.Delete, url, null);
}
private async Task ExecuteRequest(RequestType requestType, string url, StringContent? body)
{
HttpResponseMessage response;
using (HttpClient client = new())
{
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {await GetAccessToken()}");
switch (requestType)
{
case RequestType.Put:
if (body == null)
throw new Exception("Body cannot be empty");
response = await client.PutAsync(url, body);
break;
case RequestType.Delete:
response = await client.DeleteAsync(url);
break;
default:
throw new Exception("Unknown request type");
}
if (!response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
throw new Exception(content);
}
}
}
private async Task<string> GetAccessToken()
{
if (!string.IsNullOrEmpty(accessToken))
return accessToken;
AuthenticationContext authContext = new("https://login.microsoftonline.com/" + tenantId);
ClientCredential clientCreds = new(clientId, clientSecret);
AuthenticationResult authResult = await authContext.AcquireTokenAsync(resourceId, clientCreds);
accessToken = authResult.AccessToken;
return accessToken;
}
}
Models:
public class RunbookSchedule
{
public RunbookScheduleProperties Properties { get; set; }
}
public class RunbookScheduleProperties
{
public Schedule Schedule { get; set; }
public Runbook Runbook { get; set; }
public object Parameters { get; set; }
}
public class Runbook
{
public string Name { get; set; }
}
public class Schedule
{
public string Name { get; set; }
[JsonIgnore]
public string JobScheduleId { get; set; }
[JsonPropertyName("properties")]
public ScheduleProperties ScheduleProperties { get; set; }
}
public class ScheduleProperties
{
public string Description { get; set; }
public DateTime StartTime { get; set; }
public DateTime ExpiryTime { get; set; }
public string Frequency { get; set; }
public object AdvancedSchedule => new { };
}
And the unit tests I use to test the logic:
public class ScheduleTests
{
private readonly string jobId = "d52004cc-b7ec-4b9b-99c1-3922492f6e1b-1";
private readonly string runbookName = "RunFunctionApp";
private readonly ScheduleLogic scheduleService;
public ScheduleTests()
{
scheduleService = new();
}
[Fact]
public async Task Should_CreateASchedule()
{
Schedule newScheduleSettings = new()
{
Name = jobId,
JobScheduleId = jobId,
ScheduleProperties = new()
{
Description = "Here is another example",
StartTime = new DateTime(2024, 03, 27, 9, 0, 0, 0),
ExpiryTime = new DateTime(2024, 03, 27, 10, 0, 0, 0),
Frequency = "OneTime"
}
};
await scheduleService.CreateSchedule(newScheduleSettings);
}
[Fact]
public async Task Should_DeleteSchedule()
{
await scheduleService.DeleteSchedule(jobId);
}
[Fact]
public async Task Should_ConnectScheduleAndRunbook()
{
await scheduleService.ConnectScheduleToRunbook(new RunbookSchedule
{
Properties = new()
{
Schedule = new() { Name = jobId, JobScheduleId = jobId },
Runbook = new() { Name = runbookName },
Parameters = new { id = 12 }
}
});
}
}
Somehow I think I am doing something stupid and the fix/answer is really simple.
I tried to mess around with the URL because I think there is a problem with that, not sure why... Just a feeling.
Google did show me some results, but those were for schedules of other services. Runbooks and automation don't seem to be very popular.
ChatGPT comes with older, obsolete solutions. Visual Studio gives a lot of green and even red lines when I try those suggestions.
I have the following. It seems to not be waiting after the request has been sent out in the GetAllProjects. It waits for the response, then doesn't wait for the response content to be read in.
NOTE: using nuget package for ReadAsAsync (could have used a json object to deserialize however)
public class Project
{
public string? Id { get; set; }
public string? Name { get; set; }
public string? Url { get; set; }
}
public class Main
{
public static void Main(string[] args)
{
AzureClient ac = new AzureClient();
var projects = ac.GetAllProjects();
}
}
public class AzureClient
{
private readonly HttpClient _client;
private const string PAT = "myToken";
private const string API_VERSION = "api-version=5.0";
public AzureClient()
{
_client = new HttpClient()
{
BaseAddress = new Uri("some uri"),
Timeout = TimeSpan.FromSeconds(30)
};
// added media type and passed in auth token to _client. client returns 200 on requests
}
public async Task<ICollection<Project>> GetAllProjects()
{
var response = await _client.GetAsync("_apis/projects?{API_VERSION }");
var projects = await response.Content.ReadAsAsync<dynamic>();
return projects.value.ToObject<ICollection<Project>>();
}
}
You are missing an await here
var projects = await ac.GetAllProjects();
you will also need to make your Main method async
I am relatively new to building with Azure's LUIS for chatbot development. I am stuck on testing my bot with a deployed LUIS and QnA Maker. I essentially developed questions on LUIS but how do I get the response based on the questions directed from LUIS? Thanks!
To Invoke QNA maker you could have a look on following code:
Invoke QNA Maker API:
//Take User Input And Validate param
if (string.IsNullOrEmpty(objQnAMakerQuestion.question))
{
validationMessage = new OkObjectResult("Question is required!");
return (IActionResult)validationMessage;
}
// Call QnA API
var jsonContent = JsonConvert.SerializeObject(objQnAMakerQuestion);
var endpointKey = "YourSubscriptionKey";
var qnaMakerURI = "https://YourSource.azurewebsites.net/qnamaker/knowledgebases/YourSubscription/generateAnswer";
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(qnaMakerURI);
request.Content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
request.Headers.Add("Authorization", "EndpointKey" + endpointKey);
var response = await client.SendAsync(request);
//Check status code and retrive response
if (response.IsSuccessStatusCode)
{
QnAMakerModelClass objQnAResponse = JsonConvert.DeserializeObject<QnAMakerModelClass>(await response.Content.ReadAsStringAsync());
// var responseBody = await response.Content.ReadAsStringAsync();
foreach (var item in objQnAResponse.answers)
{
QnAMakerAnswer objAnswer = new QnAMakerAnswer();
objAnswer.answer = item.answer;
return new OkObjectResult(objAnswer);
}
}
else
{
var result_string = await response.Content.ReadAsStringAsync();
return new OkObjectResult(result_string);
}
Class Used To Invoke QNA Maker:
public class QnAMakerQuestion
{
public string question { get; set; }
}
public class QnAMakerAnswer
{
public string answer { get; set; }
}
public class Metadata
{
public string name { get; set; }
public string value { get; set; }
}
public class Context
{
public bool isContextOnly { get; set; }
public List<object> prompts { get; set; }
}
public class Answer
{
public List<string> questions { get; set; }
public string answer { get; set; }
public double score { get; set; }
public int id { get; set; }
public string source { get; set; }
public List<Metadata> metadata { get; set; }
public Context context { get; set; }
}
public class QnAMakerModelClass
{
public List<Answer> answers { get; set; }
public object debugInfo { get; set; }
}
For more details you could refer this official document
Hope it will help.
If you have a chatbot that is calling QnAMaker, a slightly easier method would be to use the QnAMaker class. Here's how you would do this in C#:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
var httpClient = _httpClientFactory.CreateClient();
var qnaMaker = new QnAMaker(new QnAMakerEndpoint
{
KnowledgeBaseId = _configuration["QnAKnowledgebaseId"],
EndpointKey = _configuration["QnAEndpointKey"],
Host = _configuration["QnAEndpointHostName"]
},
null,
httpClient);
_logger.LogInformation("Calling QnA Maker");
var options = new QnAMakerOptions { Top = 1 };
// The actual call to the QnA Maker service.
var response = await qnaMaker.GetAnswersAsync(turnContext, options);
if (response != null && response.Length > 0)
{
await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
}
else
{
await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
}
}
There is a good example on how to integrate QnA into a bot here, along with the official documentation here.
I have 2 viewmodel, aviewmodel and bviewmodel. in aviewmodel and bviewmodel are used method GetListEmployees(). i have a problem.
In aviewmodel,I have successfully run the GetListEmployees().but in bviewmodel then it does not work. I debug and I see it was thrown when it came to response. I don't know why it's like that.
video description. https://youtu.be/CD3lHKx3igs
Function to get the list.
async private Task GetListEmployees()
{
var result = await GeneralMethods.Ins.GetDataFromDB<Employee>("Employee/employees");
// ListEmployee = new ObservableCollection<Employee>(result);
}
This is class read api.
public class GeneralMethods
{
private static GeneralMethods _Ins;
public static GeneralMethods Ins
{
get
{
if (_Ins == null)
_Ins = new GeneralMethods();
return GeneralMethods._Ins;
}
private set
{
GeneralMethods._Ins = value;
}
}
public async Task<List<T>> GetDataFromDB<T>(string urlDB)
{
string url = "http://webapi.local/api/" + urlDB;
using (HttpResponseMessage response = await APIHelper.ApiClient.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsAsync<List<T>>().Result;
return result;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
}
}
APIHelper
public static class APIHelper
{
public static HttpClient ApiClient { get; set; }
public static void InitializeClient()
{
ApiClient = new HttpClient();
ApiClient.DefaultRequestHeaders.Accept.Clear();
ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
I'm trying to implement Facebook login and get data in c# project.
what I'm trying to do is that user press his firstname and password then he press on the login button and login then it return his data.
the when I press on the button the program is freeze.
that's my project implementation
Account.cs
public class Account
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Birthday { get; set; }
}
Facebook.client
public interface IFacebookClient
{
Task<T> GetAsync<T>(string accessToken, string endpoint, string args = null);
Task PostAsync(string accessToken, string endpoint, object data, string args = null);
}
public class FacebookClient : IFacebookClient
{
private readonly HttpClient _httpClient;
public FacebookClient()
{
_httpClient = new HttpClient
{
BaseAddress = new Uri("https://graph.facebook.com/v2.8/")
};
_httpClient.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<T> GetAsync<T>(string accessToken, string endpoint, string args = null)
{
var response = await _httpClient.GetAsync($"{endpoint}?access_token={accessToken}&{args}");
if (!response.IsSuccessStatusCode)
return default(T);
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
public async Task PostAsync(string accessToken, string endpoint, object data, string args = null)
{
var payload = GetPayload(data);
await _httpClient.PostAsync($"{endpoint}?access_token={accessToken}&{args}", payload);
}
private static StringContent GetPayload(object data)
{
var json = JsonConvert.SerializeObject(data);
return new StringContent(json, Encoding.UTF8, "application/json");
}
}
FacebookService.cs
public interface IFacebookService
{
Task<Account> GetAccountAsync(string accessToken);
Task PostOnWallAsync(string accessToken, string message);
}
public class FacebookService : IFacebookService
{
private readonly IFacebookClient _facebookClient;
public FacebookService(IFacebookClient facebookClient)
{
_facebookClient = facebookClient;
}
public async Task<Account> GetAccountAsync(string accessToken)
{
var result = await _facebookClient.GetAsync<dynamic>(
accessToken, "me", "fields=id,name,birthday,email");
if (result == null)
{
return new Account();
}
var account = new Account
{
Id = result.id,
Email = result.email,
Name = result.name,
Birthday = result.Birthday
};
return account;
}
public async Task PostOnWallAsync(string accessToken, string message)
=> await _facebookClient.PostAsync(accessToken, "me/feed", new {message});
}
FacebookSettings.cs
var facebookClient = new FacebookClient();
var facebookService = new FacebookService(facebookClient);
var getAccountTask = facebookService.GetAccountAsync(FacebookSettings.AccessToken);
Task.WaitAll(getAccountTask);
var account = getAccountTask.Result;
Console.WriteLine($"{account.Id} {account.Name}");
Login form button
private void btn_facebook_Click(object sender, EventArgs e)
{
var facebookClient = new FacebookClient();
var facebookService = new FacebookService(facebookClient);
var getAccountTask = facebookService.GetAccountAsync(FacebookSettings.AccessToken);
Task.WaitAll(getAccountTask);
var account = getAccountTask.Result;
//Console.WriteLine($"{account.Id} {account.Name}");
}
it stuck on this line on the await
public async Task<Account> GetAccountAsync(string accessToken)
{
var result = await _facebookClient.GetAsync<dynamic>(accessToken, "me", "fields=id,name,birthday,email");
if (result == null)
{
return new Account();
}
var account = new Account
{
Id = result.id,
Email = result.email,
Name = result.name,
Birthday = result.Birthday
};
return account;
}
in this line
var result = await _facebookClient.GetAsync<dynamic>(accessToken, "me", "fields=id,name,birthday,email");
Here's your problem:
Task.WaitAll(getAccountTask);
Don't block on async code. Use await instead:
private async void btn_facebook_Click(object sender, EventArgs e)
{
var facebookClient = new FacebookClient();
var facebookService = new FacebookService(facebookClient);
var account = await facebookService.GetAccountAsync(FacebookSettings.AccessToken);
}