I have not found any code examples how to write Cognito trigger in C#. I am particularly interested in pre authentication trigger.
Right now I have the following Lambda function which is set as a pre authentication trigger in Cognito:
public APIGatewayProxyResponse ExampleTrigger(APIGatewayProxyRequest request, ILambdaContext context)
{
context.Logger.LogLine("trigger called");
return new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK
};
}
However, I receive this error:
{code: "InvalidLambdaResponseException", name: "InvalidLambdaResponseException", message: "Unrecognizable lambda output"}
I think this error is caused because the type APIGatewayProxyResponse is not correct. But what is the correct type?
According to the documentation, handler should expect an object, which represents the following JSON ( including common parameters) :
{
"version": "string",
"triggerSource": "string",
"region": "string",
"userPoolId": "string",
"userName": "string",
"callerContext": {
"awsSdkVersion": "string",
"clientId": "string"
},
"request": {
"userAttributes": {
"string": "string",
. . .
},
"validationData": {
"string": "string",
. . .
},
"userNotFound": boolean
},
"response": {}
}
Also lambda handler should return the same type of object.
Since you are working with C#, probably you can use following classes to deserialize the object. So instead of both APIGatewayProxyRequest and APIGatewayProxyResponse, please use below mentioned Event Type.
public class Event
{
[JsonPropertyName("version")]
public string Version { get; set; }
[JsonPropertyName("region")]
public string Region { get; set; }
[JsonPropertyName("userPoolId")]
public string UserPoolId { get; set; }
[JsonPropertyName("userName")]
public string UserName { get; set; }
[JsonPropertyName("callerContext")]
public CallerContext CallerContext { get; set; }
[JsonPropertyName("triggerSource")]
public string TriggerSource { get; set; }
[JsonPropertyName("request")]
public Request Request { get; set; }
[JsonPropertyName("response")]
public Response Response { get; set; }
}
public class CallerContext
{
[JsonPropertyName("awsSdkVersion")]
public string AwsSdkVersion { get; set; }
[JsonPropertyName("clientId")]
public string ClientId { get; set; }
}
public class Request
{
[JsonPropertyName("userAttributes")]
public Dictionary<string, string> UserAttributes { get; set; }
[JsonPropertyName("validationData")]
public Dictionary<string, string> validationData { get; set; }
}
public class Response
{
}
Let me mention a tip for this kind of scenarios:
Write the handler as:
public dynamic ExampleTrigger(dynamic request, ILambdaContext context)
{
return request
}
Add the following environment variable for lambda.
LAMBDA_NET_SERIALIZER_DEBUG = true
Invoke the Auth flow and check the logs on CloudWatch. You can see the content of the incoming event object.
Related
I am trying to serialize JSON objects received from an API in a cli app. I'm having issues understanding how to create the objects in .NET for JSON objects which have an indented structure.
For example, this is fine:
{"status": "ok" }
public class Success
{
public string status { get; set; }
}
But something like this is where I'm stuck and both of the examples from the below return null when the client API receives them.
[
{
"id": "some_uuid_string_1",
"message": "hello"
},
{
"id": "some_uuid_string_2",
"message": "world"
}
]
Attempted solution
public class Received
{
public Dictionary<string,string> received { get; set; }
}
Alternatively I also tried a simpler structure, leaving out the explicit names and just using the IDs and values, which is closer to what my app requires and lets me make smaller requests.
{
"some_uuid_string_1": "hello",
"some_uuid_string_2": "world"
}
For this example I tried this, a list of key value pairs in the form of a dictionary.
public class Message
{
public Dictionary<string,string> message { get; set; }
}
public class Received
{
public List<Message> received { get; set; }
}
How can I create objects in C# for these two structures? One indented with set names and one 'generic' with no set names.
public class MyClass
{
public string id { get; set; }
public string message { get; set; }
}
[
{
"id": "some_uuid_string",
"message": "hello"
},
{
"id": "some_uuid_string",
"message": "world"
}
]
Deserializes to a List<MyClass> or MyClass[]
{
"some_uuid_string_1": "hello",
"some_uuid_string_2": "world"
}
Deserializes to
public class MyClass
{
public string some_uuid_string_1 { get; set; }
public string some_uuid_string_2 { get; set; }
}
or Dictionary<string, string>
The reason your Received class solution didn't work is because it is expecting a JSON property of received, as your class has a property named received, but the JSON does not.
This is the same issue with your Message class. Your class has property message whereas your JSON does not.
create a class
public class MessageId
{
public string id { get; set; }
public string message { get; set; }
}
you can deserialize your json
using Newtonsoft.Json;
var messages=JsonConvert.DeserializeObject<List<MessageId>>(yourJson);
I am trying to de-serialize a weird complex json string but having issues. I am getting an exception:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Response' because the type requires a JSON object (e.g. {"name":"value"})
The Json looks like this
{
"success":true,
"error":null,
"response":{
"responses":[
{
"success":true,
"error":null,
"response":{
"ob":{
"icon":"sunny.png",
"weatherShort":"Sunny"
}
},
"request":"requeststring"
},
{
"success":true,
"error":null,
"response":[
{
"indice":{
"current":{
"dateTimeISO":"2016-08-09T10:00:00-05:00",
"indexENG":"dry"
}
}
}
],
"request":"requeststring"
}
]
}
}
The problem when trying to create a C# class is that inside the responses list there is a Response object and a Response list.
Here is my class structure:
public class Responses
{
public bool success { get; set; }
public object error { get; set; }
public Response response { get; set; }
public List<Response> responses { get; set; }
public string request { get; set; }
}
public class Indice
{
public Current current { get; set; }
}
public class Current
{
public string indexENG { get; set; }
public string dateTimeISO { get; set; }
}
public class Ob
{
public string icon { get; set; }
public string weatherShort { get; set; }
}
public class Response
{
public List<Responses> responses { get; set; }
public Indice indice { get; set; }
public Ob ob { get; set; }
}
public class RootJsonObject
{
public bool success { get; set; }
public object error { get; set; }
public Response response { get; set; }
}
Am I doing something completely wrong here to handle the Responses list with a Response object and a Response list?
In case anyone wants to know, here is how I deserialize it:
RootJsonObject obj = JsonConvert.DeserializeObject<RootJsonObject>(response);
response being the string from a web request.
I am just trying to figure out how to map this strange JSON to a C# class. I've tried quite a few different class structures but seem to get the same exception regardless. I've also tried c# class generators but they don't give a decent output for this particular JSON. Appreciate any input! Thanks!
There is an error in your JSON. Second element in array has square brackets wrapping classic curly brackets, as if response was a collection but it's not. It's expected to be of type Response:
{
"success": true,
"error": null,
"response": [ <<<HERE {
"indice": {
"current": {
"dateTimeISO": "2016-08-09T10:00:00-05:00",
"indexENG": "dry"
}
}
}] <<<HERE,
"request": "requeststring"
}
Final, proper JSON that you should have received would look like this:
{
'success': true,
'error': null,
'response': {
'responses': [{
'success': true,
'error': null,
'response': {
'ob': {
'icon': 'sunny.png',
'weatherShort': 'Sunny'
}
},
'request': 'requeststring'
}, {
'success': true,
'error': null,
'response': {
'indice': {
'current': {
'dateTimeISO': '2016-08-09T10:00:00-05:00',
'indexENG': 'dry'
}
}
},
'request': 'requeststring'
}]
}
}
After hours of attempts and research, I am asking for your help.
I am calling a public API which returns the same structure except for the datas returned.
For examples, the REST calls which retrieve stations and districts return those two JSON answers :
Stations response :
"response" : {
"status": { "#attributes": {"code": "0", "message": "OK"} },
"data" : {
"station": [{
"number": "stationId",
"name": "stationName",
"address": "stationAddress",
"state": "1",
"latitude": "stationLat",
"longitude": "stationLong",
"slotsavailable": "10",
"bikesavailable": "20",
"pos": "0",
"district": "stationDistrict",
"lastupdate": "2016-03-28T11:47:08+02:00"
}, {...}, ...]}
}
Districts response :
"response" : {
"status": { "#attributes": {"code": "0", "message": "OK"} },
"data" : { "district": [{"id": "districtId", "name": "districtName"}, {...}, ...] }
}
I am using a .NET 4.5/C# solution with Newtonsoft.Json to execute the call.
I want to make the object, mapped to the client response, generic so the execution of the call will be made as follow :
var result = await client.Execute<Response<ApiResponseDistrict>>(request);
var result = await client.Execute<Response<ApiResponseStation>>(request);
My first attempt was to make a non generic call (create a full object by returned datas) which was a success.
My second attempt was to created a generic object so I made the following classes using the JsonProperty of the library Newtonsoft :
public class ApiResponse<T>
{
[JsonProperty("response")]
public Response<T> Response { get; set; }
}
public class Response<T>
{
[JsonProperty("status")]
public Status Status { get; set; }
[JsonProperty("data")]
public Data<T> Data { get; set; }
}
public class Data<T>
{
public T ResponseData { get; set; }
}
public class ApiResponseDistrict
{
[JsonProperty("district")]
public List<District> Districts { get; set; }
}
public class District
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
At this point, when I am executing the call the object Response is valorized and also its property Status with the value waited but the property Data is never valorized (null).
My third attempt was to continue on the second attempt but using the JsonObject of the Newtonsoft library which it's given (with the same result) :
[JsonObject("district")]
public class ApiResponseDistrict
{
public List<District> Districts { get; set; }
}
As I am new to Newtonsoft, I would like to know if it is possible to use generic classes, as I am trying to do, to mapped the object returned by the call or I have to create a complete object for each "data" returned ?
Thank you for your answer and explanations or clues for me to find the answer !
public class Response<T>
{
[JsonProperty("status")]
public Status Status { get; set; }
[JsonProperty("data")]
public Data<T> Data { get; set; }
}
public class Data<T>
{
public T ResponseData { get; set; }
}
This adds another layer between the data, so a response would look like this:
{
"Status": …,
"Data": {
"ResponseData": {
<The actual type T>
}
}
}
Instead, you want to remove that ResponseData level:
public class Response<T>
{
[JsonProperty("status")]
public Status Status { get; set; }
[JsonProperty("data")]
public T Data { get; set; }
}
So for example, for the JSON above, you would have a StationResponseData class:
public class StationResponseData
{
public List<Station> Stations
{ get; set; }
}
And then you would deserialize the JSON as Response<StationResponseData>. The Station class would then contain those properties for number, name, address, etc.
Suppose I have JSON like this, how can I model my class for deserialization?
I have no problems to model class for standard attribute like "dummy" or normal arrays, but in this case, my "links" array is a list of items with different name ("addons", "conditions", "conversion", etc.).
"dummy": "1",
"links": {
"addons": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/addons",
"method": "GET"
},
"conditions": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/conditions",
"method": "GET"
},
"conversions": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/conversions",
"method": "GET"
},
"list_prices": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/list-prices",
"method": "GET"
},
"mutual_exclusion": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/mutually-exclusive-offers",
"method": "GET"
},
"prerequisites": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/prerequisites",
"method": "GET"
},
"product": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/products/f245ecc8-75af-4f8e-b61f-27d8114de5f3",
"method": "GET"
}
},
Assuming you are specifically looking for the set of LinkTypes if you will, in your JSON, could you use something like the following, and execute the Deserialize on the RootObject?
Working dotNet Fiddle: https://dotnetfiddle.net/ZWSlK4
Check out the output on the Console pane on the fiddle page.
public class Link
{
public string Href { get; set; }
public string Method { get; set; }
}
public class Links
{
[JsonProperty("addons")]
public Link Addons { get; set; }
[JsonProperty("conditions")]
public Link Conditions { get; set; }
[JsonProperty("conversions")]
public Link Conversions { get; set; }
[JsonProperty("list_prices")]
public Link ListPrices { get; set; }
[JsonProperty("mutual_exclusion")]
public Link MutualExclusion { get; set; }
[JsonProperty("prerequisites")]
public Link Prerequisites { get; set; }
[JsonProperty("product")]
public Link Product { get; set; }
}
public class RootObject
{
public string dummy { get; set; }
public Links links { get; set; }
}
and then execute the Deserializer like so.
var myDummyLinksList = JsonConvert.DeserializeObject<RootObject>(jsonText);
where jsonText contains the json string you have listed in your example:
However, if you List of links objects is dynamic and the number of objects inside varies and you need to capture all of them, then you might have to write a custom Converter that inherits from the JsonConverter object. then use the answer that #mfarouk has posted.
I forked my dotNet Fiddle and implemented his solution and it works like a boss for the dynamic case!
Working dotNet Fiddle (dynamic case): https://dotnetfiddle.net/7bFcNM
Hope this helps!
the links attribute could be parsed as key, value dictionary , the class can be like
public class JSONClass
{
public string dummy { get; set; }
public Dictionary<string, Link> links;
public class Link
{
public string Href { get; set; }
public string Method { get; set; }
}
}
then de-serialized as
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JSONClass>(JSON);
I have to deserialize the following json response (the Result list has variable length):
{
"ResultSet": {
"Query": "volkswagen",
"Result": [
{
"symbol": "VLKAY",
"name": "Volkswagen AG",
"exch": "PNK",
"type": "S",
"exchDisp": "OTC Markets",
"typeDisp": "Equity"
},
{
"symbol": "VOW3.DE",
"name": "Volkswagen AG",
"exch": "GER",
"type": "S",
"exchDisp": "XETRA",
"typeDisp": "Equity"
},
{
"symbol": "VOW.DE",
"name": "Volkswagen AG",
"exch": "GER",
"type": "S",
"exchDisp": "XETRA",
"typeDisp": "Equity"
}
]
}
}
What I got:
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonString = "...String is here...";
SearchObj obj = js.Deserialize<SearchObj>(jsonString);
I understand that I usually have to create a fitting obj. e.g. SearchObj which will get filled but in this case I'm not entirely sure how this object is supposed to look like. I came up with:
class Data
{
public string symbol { get; set; }
public string name { get; set; }
public string exch { get; set; }
public string type { get; set; }
public string exchDisp { get; set; }
public string typeDisp { get; set; }
}
class Container
{
public string Query { get; set; }
public List<Data> Result { get; set; }
}
class SearchObj
{
public Container ResultSet { get; set; }
}
But guess what, it's not working, I only get ResultSet = null.
Try to change your class Container as
class Container
{
public string Query { get; set; }
public Data[] Result { get; set; }
}
I have not tested it, based on my observation
I always feel bad when I answer my own question but here it goes.
Basically my idea was correct, I only made one mistake which is that I don't need the
class SearchObj
{
public Container ResultSet { get; set; }
}
Using
Container obj = js.Deserialize<Container>(jsonString);
instead of
SearchObj obj = js.Deserialize<SearchObj>(jsonString);
made the trick. Both Data[] and List<Data> in Container work btw.
Edit:
From giammins comment it seems that it is working on some machines without that change but I guess that's a case for undefined behavior.
You can use http://www.json2charp.com to create your classes.