I'm at my wit's end here. I think I just need another set of eyes.
Method Signature:
public async Task<IHttpActionResult> Post(ApiRequest request)
Model:
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Global")]
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")]
public class ApiRequest
{
[JsonProperty("allowLoadingToDataWarehouse")]
public bool AllowLoadingToDataWarehouse { get; set; }
[JsonProperty("initialDelay")]
public string InitialDelay { get; set; }
[JsonProperty("reportIds")]
public IEnumerable<string> ReportIds { get; set; }
[JsonProperty("reportTypeDelay")]
public string ReportTypeDelay { get; set; }
[JsonProperty("runType")]
[JsonConverter(typeof(StringEnumConverter))]
public ReportRunType RunType { get; set; }
[JsonProperty("userId")]
public string UserId { get; set; }
[JsonProperty("wwDelay")]
public string WWDelay { get; set; }
[JsonProperty("weeks")]
public IEnumerable<string> Weeks { get; set; }
}
Javascript:
var submitReportRequest = {
userId: userid,
reportIds: reportids,
runType: 'Custom',
weeks: selectedweeks,
initialDelay: $('#InitialDelay').val(),
reportTypeDelay: $('#ReportTypeDelay').val(),
wwDelay: $('#WWDelay').val(),
allowLoadingToDataWarehouse: $('#AllowLoadingToDataWarehouse').val()
};
$.post("/api/SubmitReport", JSON.stringify(submitReportRequest), function (data) {
alert('success');
});
Serialized Json From JavaScript Post:
{
"userId": "30",
"reportIds": [
"59",
"60",
"61",
"62",
"63",
"64"
],
"runType": "Custom",
"weeks": [
"201409",
"201410",
"201411",
"201412"
],
"initialDelay": "00:00:00",
"reportTypeDelay": "00:00:00",
"wwDelay": "00:00:00"
}
Quickwatch of Deserialized Object
Initially I had int and TimeSpan for the Ids and Delays, respectively, and those were not deserializing correctly. So I changed them all to strings, and they're still not deserializing correctly.
What am I doing wrong or missing?
Edit: After trying every combination of attributes, I finally decided to stick it into the Fiddler Composer. And it works. So something must be off with my JavaScript.
Turns out that shorthand JQuery post() method was setting the Content-Type attribute on the Request to application/x-www-form-urlencoded; charset=UTF-8 when it needed to be set to application/json; charset=UTF-8
I found by watching the Network traffic in Chrome, and by changing my javascript to this
answer.
Related
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.
I'm using .net core Web API. I'm posting generic QueryFilter class from angular. But, generic part of class return null. When, i change to parameter like this, it is working perfectly :
public async Task<ServiceResult> GetStudentsForGrid([FromQuery]QueryFilter queryFilter,[FromQuery]StudentFilter studentFilter)
{ } //This working perfectly
QueryFilter.cs
public class QueryFilter<T> where T : class
{
public string SortBy { get; set; }
public bool IsSortAscending { get; set; }
public int PageFirstIndex { get; set; }
public byte PageSize { get; set; }
public T CustomFilter { get; set; }
}
StudentFilter.cs
public class StudentFilter
{
public string Name { get; set; }
public string Surname { get; set; }
}
Controller.cs (not working)
[HttpGet("GetStudentsForGrid")]
public async Task<ServiceResult> GetStudentsForGrid([FromQuery]QueryFilter<StudentFilter> queryFilter)
{ } //This not working
I don't want to send every time two parameter. So, I want to use generic way. How can i fix this null exception?
If you want to use a "generic" way , let's say your controller action is :
public IActionResult GetStudentsForGrid([FromQuery]QueryFilter<StudentFilter> queryFilter)
{
var x= queryFilter;
return new JsonResult(x);
}
you have to sent the request with a well formatted querystring :
GET https://localhost:5001/api/students?sortBy=Hello&pageSize=10&customFilter.Name=1&customFilter.SurName=2 HTTP/1.1
Note the way we pass the parameters of customFilter.Name and customFilter.SurName.
The response will be :
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked
{
"sortBy": "Hello",
"isSortAscending": false,
"pageFirstIndex": 0,
"pageSize": 10,
"customFilter": {
"name": "1",
"surname": "2"
}
}
I have a web api method that looks like this:
[HttpPost]
[Route("messages")]
public IHttpActionResult Post(IEnumerable<Email> email)
{
AddToQueue(email);
return Ok("message added to queue");
}
My Email class looks like this currently:
public string Body { get; set; }
public string From { get; set; }
public string Template { get; set; }
public string To { get; set; }
public string Type { get; set; }
And I'm posting to my Post method using fiddler, like this:
User-Agent: Fiddler
Host: localhost:3994
Content-Length: 215
Content-Type: application/json; charset=utf-8
[
{"Body":"body","From":"from","To":"to","Template":"template"},
{"Body":"body1","From":"from1","To":"to1","Template":"template1"},
{"Body":"body2","From":"from2","To":"to2","Template":"template2"}
]
This works fine. However, I want to be able to add a Dictionary to my Email class, so it will look like this:
public string Body { get; set; }
public string From { get; set; }
public string Template { get; set; }
public string To { get; set; }
public string Type { get; set; }
public Dictionary<string, string> HandleBars { get; set; }
And I changed my request to look like this:
[{
"Body": "body",
"From": "from",
"To": "to",
"Template": "template",
"HandleBars": [{
"something": "value"
}]
},
{
"Body": "body1",
"From": "from1",
"To": "to1",
"Template": "template1"
},
{
"Body": "body2",
"From": "from2",
"To": "to2",
"Template": "template2"
}]
However, when the Post method receives this, all the Email fields are populated, except for the HandleBars dictionary. What do I have to do in order to pass it in correctly? Is my json structured incorrectly?
The default JsonFormatter is unable to bind Dictionary from Javascript Array because it doesn't define a key to each item.
You need to use an Object instead:
"HandleBars": {
"something": "value"
}
You should have
{
"Body": "body",
"From": "from",
"To": "to",
"Template": "template",
"HandleBars": [
{ key: 'key1', value: 'something'}
]
}
Basically I am working with Campaign Monitor's webhook. I have created an update webhook so when email is updated, Campaign Monitor sends HTTP POST request to the URL I specified. I am having trouble parsing JSON.
Here it is:
POST /subscribe HTTP/1.1
Host: example.com:80
Accept: */*
Content-Type: application/json
{
"Events": [
{
"CustomFields": [
{
"Key": "website",
"Value": "http:\/\/example.org"
}
],
"Date": "2010-12-14 11:32:00",
"OldEmailAddress": "test#example.org",
"EmailAddress": "test#example.org",
"Name": "Test Subscriber Renamed",
"Type": "Update",
"State": "Active"
}
],
"ListID": "96c0bbdaa54760c8d9e62a2b7ffa2e13"
}
I looked at the example http://msdn.microsoft.com/en-ca/library/cc197957(v=vs.95).aspx but couldn't get to work it out.
I would like to get OldEmailAddress, EmailAddress, Type and State. Thanks,
Reference to Campaign Monitor's webhooks https://www.campaignmonitor.com/api/webhooks/#currently_available_webhooks
Thanks,
If I understand correctly you try to get json data from url using C#. First of all you need to get NuGet packages called Newtonsoft.Json
Then you can use this code
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://yourapisite.com"); // Not whole link, just host
var url = "link after your host url";
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsStringAsync();
YourClass responsedata = JsonConvert.DeserializeObject<YourClass>(data.Result.ToString());
}
}
Hope this help.
EDIT
First of all,Newtonsoft is a very sensitive about deserialize json.Every json property like CustomField has a property with same name. I edited my answer to your code. Please check and let me know how is working.
I cannot debug this code because I didnt know your api url.
public class Events {
public Events()
{
this.eventData = new List<EventData>();
}
public string ListID { get; set; }
public List<EventData> eventData { get; set; }
}
public class EventData {
public EventData()
{
this.CustomFields = new List<CustomFields>();
}
public DateTime Date { get; set; }
public string OldEmailAddress { get; set; }
public string EmailAddress { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string State { get; set; }
public List<CustomFields> CustomFields { get; set; }
}
public class CustomFields
{
public string Key { get; set; }
public string Value { get; set; }
}
Hi I have a function that will expose to the RestAPI. I need to pass in a JSON string to be a defined class. I use the following class for JSON format:
public class Registrant : Guest
{
public int RegistrantID { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public int EventID { get; set; }
public bool IsPrimary { get; set; }
}
And I have the following function in my controller:
public HttpResponseMessage Create(string id, [FromBody]Registrant registrant)
However When I pass in the JSON string the same structure, it could not deserialize correctly.
Is there anything wrong with it?
PS: my JSON string in request body:
{
"RegistrantID":"0",
"Email": "abc#abc.com",
"Phone": "123456789",
"EventID": "8",
"IsPrimary": "true",
"CustomerId": "12345678",
"FirstName": "abc",
"LastName": "def"
}
Update:
The problem is resolved by choosing Content-Type as Application/Json
Also, I took out the quotes on int and bool params it works fine.
Finally the api call look like this in project:
public HttpResponseMessage Create([FromUri]string id, [FromBody]Registrant registrant)