I'm having a bit of difficulty with an AWS issue that doesn't seem to have that great of documentation.
I have my lambda function here:
public async Task<string> FunctionHandler(ConnectRequest request, ILambdaContext context)
{
AmazonLexClient lexClient = new AmazonLexClient();
var response = new PostTextResponse();
PostTextRequest postRequest = new PostTextRequest();
postRequest.BotName = "X";
postRequest.BotAlias = "X";
postRequest.UserId = Guid.NewGuid().ToString();
postRequest.InputText = "What Time Is My Appointment?";
try
{
response = await lexClient.PostTextAsync(postRequest);
context.Logger.Log(response.IntentName);
context.Logger.Log(response.DialogState);
}
catch (Exception ex)
{
context.Logger.Log($"EXCEPTION CAUGHT: {Environment.NewLine} {ex.ToJson()} {Environment.NewLine} {response.Message} {response.IntentName} {response.SlotToElicit}");
return "Error";
}
context.Logger.Log($"Success from lambda {Environment.NewLine} Message: {response.Message} {Environment.NewLine} " +
$"Dialog State:{response.DialogState}");
return "Success";
}
I am invoking this from a connect flow like so:
And what I'm getting back in return is:
"ErrorType": 2,
"ErrorCode": "DependencyFailedException",
"RequestId": "",
"StatusCode": 424,
"Message": "Invalid Lambda Response: Received error response from Lambda: Unhandled",
"Data": {},
"InnerException": {
"Response": {
"StatusCode": 424,
"IsSuccessStatusCode": false,
"ContentType": "application/json",
"ContentLength": 85,
"ResponseBody": {}
},
"Message": "Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown."
Which I read in the Amazon PostText Documentation could mean a couple things:
If Amazon Lex does not have sufficient permissions to call a Lambda
function.
If a Lambda function takes longer than 30 seconds to execute.
If a fulfillment Lambda function returns a Delegate dialog action
without removing any slot values.
I have confirmed that my Lambda does have permission to use PostText and access Lex. I have tried changing my return type of my function to PostTextReponse with no luck, So I'm not sure where to go from here, there isn't much documentation for this kind of thing.
Any help is appreciated, thanks!
For anybody that is curious about this I have found an answer:
First off, when using a Lambda function like this it is a good idea to return an object of what you want. Which is what I ended up doing. You also need to set SessionAttributes in JSON format.
My code is working and is as follows now:
public async Task<LambdaResponseItem> FunctionHandler(ConnectRequest request, ILambdaContext context)
{
var client = new AmazonLexClient();
var response = new PostContentResponse();
var lambdaInfo = new Dictionary<string, string>();
var contentRequest = new PostContentRequest();
var postContentStream = new MemoryStream();
var postContentWriter = new StreamWriter(postContentStream);
try
{
var userInput = request.Details?.Parameters?.GetValueOrDefault("UserInput");
postContentWriter.Write(userInput); // Grab user input (utterance) value from AWS Connect.
postContentWriter.Flush();
postContentStream.Position = 0;
contentRequest.Accept = "text/plain; charset=utf-8";
contentRequest.BotName = "IntroGreeting";
contentRequest.BotAlias = EnvironmentVariables.IsProduction ? "Production" : "Development";
contentRequest.ContentType = "text/plain; charset=utf-8";
contentRequest.UserId = request.Details?.ContactData?.ContactId;
contentRequest.InputStream = postContentStream;
contentRequest.SessionAttributes = request.Details?.Parameters?.ToJson(); // * Must be in Json format or request will return error *
// POST to Lex
response = await client.PostContentAsync(contentRequest);
return new LambdaResponseItem(){
Content = ""
}
}
catch (Exception ex)
{
context.Logger.Log($"POST Request to Amazon Lex Failed {ex.ToJson()}");
}
Related
Good moring Team,
Since yersterday im trying to post an API using Flurl but im still getting this error and the post code block is not executed, i dont know where should be the issue.
bellow is my code:
public async Task<GetCustomerAcctsDetail_Model> GetCustomerAcctsDetail(string num_compte)
{
try
{
//getting fcub endpoint
var customerdetail_api = Configuration.GetValue<string>("APIs:accountdetails");
var api_key = Configuration.GetValue<string>("APIs:Authorisation_key");
var customer_details= await customerdetail_api
.WithHeader("Accept", "application/json")
.WithHeader("Authorization",api_key)
.PostJsonAsync(new
{
channel_code = "MYCHANELCODE",
account_no = num_compte
})
.ReceiveJson<GetCustomerAcctsDetail_Model>();
return customer_details;
}
catch(Exception Ex)
{
_logger.LogError(Ex.Message);
return null;
}
}
i am always getting this error:
Id = 17, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
and the post is never executed.
can someone help please??
I've been trying to call Microsoft Graph API for creating events, however I've not been able to do it.
Context: I have a Web MVC application (C#) already in production, with the "common" authentication method, reading a database of users. Recently the customer asked me the possibility to create Microsoft Teams Meetings from the application and also those created meetings have to be scheduled in the Microsoft Teams Calendar with the "Join" button to enter the meeting.
I already configured the API permissions, client secret and used the other properties like tenant, user id, etc from the Azure Portal, I'm sharing a screenshot of my configuration. I'm doing the "Get access on behalf of a user" process.
API Permissions:
Permissions image
Taking the example of the authorize endpoint from the docs, of course I'm replacing the values with my own info
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=11111111-1111-1111-1111-111111111111
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&scope=offline_access%20user.read%20mail.read
&state=12345
Here is my code to Receive the code once the user authorizes the permissions, I'm just storing the value in a static class for testing
public ActionResult ReceiveCode(string code)
{
AuthenticationConfig.Code = code;
//this.Code = code;
return RedirectToAction("Index");
}
Once I got the Auth code, I'm using it to create the event with the generated token, also I already verified that the token contains the permissions given in the Azure Portal.
This is the input for the /events endpoint
var json = JsonConvert.SerializeObject(new
{
subject = "Let's go for lunch",
body = new
{
contentType = "HTML",
content = "Does noon work for you?"
},
start = new
{
dateTime = "2017-04-15T12:00:00",
timeZone = "Pacific Standard Time",
},
end = new
{
dateTime = "2017-04-15T14:00:00",
timeZone = "Pacific Standard Time"
},
location = new
{
displayName = "Harry's Bar",
},
attendees = new List<Attendee>()
{
new Attendee
{
EmailAddress = new EmailAddress
{
Address = "mymail#whatever.com",
Name = "Foo Bar"
},
Type = AttendeeType.Required
}
},
allowNewTimeProposals = true,
isOnlineMeeting = true,
onlineMeetingProvider = "teamsForBusiness",
});
This is the complete method, for the json value, please see the json above. I also tried with the "me" url but it does not work either.
public async Task<ActionResult> OnlineMeeting()
{
try
{
var httpClient = new HttpClient();
var paramsDictionary = new Dictionary<string, string>();
paramsDictionary.Add("client_id",AuthenticationConfig.ClientId);
paramsDictionary.Add("scope", "Calendars.ReadWrite");
paramsDictionary.Add("code", AuthenticationConfig.Code);
paramsDictionary.Add("redirect_uri", "https://localhost:44379/Meeting/Reunion/ReceiveCode");
paramsDictionary.Add("grant_type", "authorization_code");
paramsDictionary.Add("client_secret", AuthenticationConfig.ClientSecret);
var url = string.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", "tenant");
var response = await httpClient.PostAsync(url, new FormUrlEncodedContent(paramsDictionary));
if (response.IsSuccessStatusCode)
{
var jsonResponse = await response.Content.ReadAsStringAsync();
var jsonResult = JsonConvert.DeserializeObject(jsonResponse) as JObject;
var accessToken = jsonResult.GetValue("access_token").ToString();
httpClient = new HttpClient();
var json = JsonConvert.SerializeObject(new { });
var defaultRequestHeaders = httpClient.DefaultRequestHeaders;
if (defaultRequestHeaders.Accept == null || !defaultRequestHeaders.Accept.Any(m => m.MediaType == "application/json"))
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
defaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var data = new StringContent(json);
response = await httpClient.PostAsync("https://graph.microsoft.com/v1.0/users/{user id}/events", data);
if (response.IsSuccessStatusCode)
{
// Nice
}
else
{
Console.WriteLine($"Failed to call the web API: {response.StatusCode}");
string content = await response.Content.ReadAsStringAsync();
}
}
else
{
Console.WriteLine($"Failed to call the web API: {response.StatusCode}");
string content = await response.Content.ReadAsStringAsync();
}
}
catch (Exception ex)
{
}
return View();
}
I'm able to the get the token, but when trying to create the event returns the next response.
{
"error": {
"code": "ResourceNotFound",
"message": "Resource could not be discovered.",
"innerError": {
"date": "2021-08-31T22:58:18",
"request-id": "c5c07afa-fa89-4948-a9f8-f80ca4cbafc3",
"client-request-id": "c5c07afa-fa89-4948-a9f8-f80ca4cbafc3"
}
}
}
Am I missing something? Maybe the wrong endpoint?
Please, help.
Thanks in advance.
I am using QnAMaker REST API in my Bot Framework to query a knowledge base.
It works fine but I would like to filter the 'questions' based on the 'source' as specified on the requestData. Referring to the documentation- https://learn.microsoft.com/en-us/azure/cognitive-services/qnamaker/how-to/metadata-generateanswer-usage I did not see any option to do that. The documentation states that 'source' is only part of the response answer and not the request.
I tried passing 'source' as metadata to strictFilters.
Dictionary<string, object> requestData = new Dictionary<string, object>
{
["question"] = question,
["top"] = top,
["strictFilters"] = new Dictionary<string, object>
{
["source"] = "test.tsv"
}
};
string requestBody = JsonConvert.SerializeObject(requestData);
kbId = _configuration[qnaKbName];
method = "/knowledgebases/" + kbId + "/generateAnswer/";
var uri = host + method;
var response = await Post(uri, requestBody);
return response;
Request JSON format-
{"question":"flexible working","top":5,"strictFilters":{"source":"test.tsv"}}
It does not work and I get below response-
{
"error": {
"code": "BadArgument",
"message": "Parameter is null"
}
}
Tried creating the Request JSON like this-
{"question":"sabbatical","top":5,"strictFilters":[{"name":"source","value":"test.tsv"}]}
Got below response-
{
"error": {
"code": "Unspecified",
"message": "Something happened. Please retry after some time."
}
}
Is there any option to do that? Please let me know if I can provide more details..
the error BadArgument, Parameter is null comes when input json being passed does not match with QnA API request body. For example if API is expecting {"question":"this is my question"} and we pass {"questionAB":"this is my question"}, this will throw error.
I'm writing a RESTful API in Web API and I'm not sure how to handle errors effectively. I want the API to return JSON, and it needs to consist of the exact same format every single time - even on errors. Here are a couple of examples of what a successful and a failed response might look like.
Success:
{
Status: 0,
Message: "Success",
Data: {...}
}
Error:
{
Status: 1,
Message: "An error occurred!",
Data: null
}
If there is an exception - any exception at all, I want to return a response that is formed like the second one. What is the foolproof way to do this, so that no exceptions are left unhandled?
Implement IExceptionHandler.
Something like:
public class APIErrorHandler : IExceptionHandler
{
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
var customObject = new CustomObject
{
Message = new { Message = context.Exception.Message },
Status = ... // whatever,
Data = ... // whatever
};
//Necessary to return Json
var jsonType = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
var response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, customObject, jsonType);
context.Result = new ResponseMessageResult(response);
return Task.FromResult(0);
}
}
and in the configuration section of WebAPI (public static void Register(HttpConfiguration config)) write:
config.Services.Replace(typeof(IExceptionHandler), new APIErrorHandler());
I'm looking at creating a REST WebAPI and want to return "error" messages along with my status codes - as desciption to the end client as to what went wrong.
One of the responses will be a 422 status code - but I can't see how to get the data element into my reponse?
public HttpResponseMessage GetValidate(string number)
{
var response = Request.CreateResponse((HttpStatusCode)422);
response.Content new { error = "something wrong here", item = "number" }; // This is wrong!
return response;
}
There is no definition in the HttpStatusCode for 422 code. Take a look at documentation.
You could use the 500 http status code which is Interval Error:
return Request.CreateResponse(HttpStatusCode.InternalServerError, new {error = "something wrong here", item = "number"});
or 400 Bad Request:
return Request.CreateResponse(HttpStatusCode.BadRequest, new { error = "something wrong here", item = "number" });
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "message"); or other overloads.
There is a draft proposal to the IETF for a standard way of returning error information from an API. The details are here https://datatracker.ietf.org/doc/html/draft-nottingham-http-problem-04
I have a library that supports creating this format on Nuget and a GitHub project.
It works like this..
var problem = new ProblemDocument
{
ProblemType = new Uri("http://example.org"),
Title = "Houston we have a problem",
StatusCode = HttpStatusCode.BadGateway,
ProblemInstance = new Uri("http://foo")
};
problem.Extensions.Add("bar", new JValue("100"));
var response = new HttpResponseMessage(HttpStatusCode.BadGateway)
{
Content = new ProblemContent(problem)
};