Pass Object Array into Request Body - c#

I have an object defined as follows.
public class ILT
{
public items items;
public options options;
}
public class items
{
public string course_code { get; set; }
public string session_code { get; set; }
public string date_name { get; set; }
public string date { get; set; }
public string time_start { get; set; }
public string time_end { get; set; }
public string location_name { get; set; }
public string location_address { get; set; }
public string location_country { get; set; }
public items() { }
public items(string course_code, string session_code, string date_name,
string date, string time_start, string time_end, string location_name,
string location_address, string location_country)
{
this.course_code = course_code;
this.session_code = session_code;
this.date_name = date_name;
this.date = date;
this.time_start = time_start;
this.time_end = time_end;
this.location_name = location_name;
this.location_address = location_address;
this.location_country = location_country;
}
}
I'm trying to pass the object into a RestfulAPI request body. The "items" attribute is supposed to be an array of objects.
The JSon should be formatted as follows:
{
"items": [
{
"course_id": 6,
"session_code": "my session code",
"session_name": "my session name",
"session_maximum_enrollments": 20,
"session_last_subscription_date": "2018-10-27",
"completion_type": "Evaluation",
"score_base": 100,
"date_name": "my date name",
"date": "2018-10-28",
"timezone": "America/New_York",
"time_start": "08:00:00",
"time_end": "12:00:00",
"location_name": "my location name",
"location_address": "10850 W. Park Place Suite 600, Milwaukee, WI 53225",
"location_country": "UNITED STATES OF AMERICA"
}
],
"options": {
"update_session_info": true
}
}
I'm having difficulty getting the items into an array. I'm trying to initialize the object into the request body as follows:
public bool CreateILT()
{
if (String.IsNullOrEmpty(Token))
Token = request.GetToken();
ILT classroom = new ILT
{
items = new items[0]
(
course_code = "APS_CLASSROOM",
session_code = "APS_CLASSROOM",
date_name = "August 27, 2018",
date = "2018-10-27",
time_start = "08:00:00",
time_end = "17:00:00",
location_name = "Crisis Prevention Institute",
location_address = "10850 W. Park Place Suite 600, Milwaukee, WI 53225",
location_country = "UNITED STATES OF AMERICA"
),
options = new options
{
update_session_info = true
}
};
dynamic response = request.Request_POST("/learn/v1/ilt/session/batch", Token, classroom);
if (response.data.success.ToString() == "True")
success = true;
return success;
}
Am I able to initialize an object array like this? I'm getting errors of various types when tweaking around. The above code errors out on each of the object's member's saying it does not exist in the current context.

Your class variable decleration is wrong. It stores object, not array/list of objects. And I could not see your options class. Do you have it right?
It should be declared as follows:
public class ILT
{
public List<items> items;
public options options;
}
And you should initialize it as follows:
ILT classroom = new ILT
{
items = new List<items> {
new item(
course_code = "APS_CLASSROOM",
session_code = "APS_CLASSROOM",
date_name = "August 27, 2018",
date = "2018-10-27",
time_start = "08:00:00",
time_end = "17:00:00",
location_name = "Crisis Prevention Institute",
location_address = "10850 W. Park Place Suite 600, Milwaukee, WI 53225",
location_country = "UNITED STATES OF AMERICA")
},
options = new options
{
update_session_info = true
}
};

Related

SQL Server / EF Core not respect date from the client

I'm a bit newbie with the MS tech stack, I developed a REST API using c# and EF core
I have this body request
{
"name": "Test Fecha",
"awardDate": "2020-05-19T00:00:00.000Z",
"governancePermit": "TEST",
"totalTickets": 5000,
"legals": "TEST",
"logo": "TEST",
"ticket": "TEST",
"ticketLifeTime": "200000",
"ticketPrice": 2000,
"saleStartDate": "2020-05-19T00:00:00.000Z",
"saleEndDate": "2020-05-19T00:00:00.000Z"
}
Thats the body of a post request to create a new resourse. That body is procesed by the next code:
Controller:
[HttpPost("/api/contest")]
public async Task<IActionResult> Create([FromBody] ContestCreateRequest request)
{
var activeContest = await _contestService.GetByStatus("Active");
if (activeContest == null)
{
var contest = new Contest
{
Name = request.Name,
AwardDate = DateTime.Parse(request.AwardDate),
TotalTickets = request.TotalTickets,
GovernancePermit = request.GovernancePermit,
Logo = request.Logo,
Ticket = request.Ticket,
Legals = request.Legals,
Status = "Active",
TicketLifeTime = request.TicketLifeTime,
TicketPrice = request.TicketPrice,
SaleStartDate = DateTime.Parse(request.SaleStartDate),
SaleEndDate = DateTime.Parse(request.SaleEndDate),
CreatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
UpdatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
};
var result = await _contestService.Create(contest);
if (result)
{
var response = new GeneralResponse
{
Message = "Contest Create",
Data = null,
Status = 201,
Success = true
};
return Ok(response);
}
else
{
var response = new GeneralResponse
{
Message = "Contest not create",
Data = null,
Status = 400,
Success = false
};
return BadRequest(response);
}
}
else
{
var response = new GeneralResponse
{
Message = "Only one contest can be active",
Data = null,
Status = 400,
Success = false
};
return BadRequest(response);
}
}
As you can see I am only parsing the dates from string to a DateTime Object
Then the the object(entity) is inserted in the data base with the following code:
public async Task<bool> Create(Contest contest)
{
await _dataContext.Contest.AddAsync(contest);
var create = await _dataContext.SaveChangesAsync();
return create > 0;
}
Model:
[Table("Contest")]
public class Contest
{
[Key]
public int ContestId { get; set; }
[Column("id_udlap")]
public int IdUdlap { get; set; }
[Column("name")]
public string Name { get; set; }
[Column("start_date")]
public DateTime StartDate { get; set; }
[Column("end_date")]
public DateTime EndDate { get; set; }
[Column("award_date")]
public DateTime AwardDate { get; set; }
[Column("avaible_tickets")]
public int AvaibleTickets { get; set; }
[Column("total_tickets")]
public int TotalTickets { get; set; }
[Column("status")]
public string Status { get; set; }
[Column("dynimic_fields")]
public string DynamycFields { get; set; }
[Column("custom_message")]
public string CustomMessage { get; set; }
[Column("grateful_message")]
public string GratefulMessage { get; set; }
[Column("ticket_life_time")]
public string TicketLifeTime { get; set; }
[Column("ticket_price")]
public double TicketPrice { get; set; }
[Column("governance_permit")]
public string GovernancePermit { get; set; }
[Column("legals")]
public string Legals { get; set; }
[Column("logo")]
public string Logo { get; set; }
[Column("ticket")]
public string Ticket { get; set; }
[Column("sale_start_date")]
public DateTime SaleStartDate { get; set; }
[Column("sale_end_date")]
public DateTime SaleEndDate { get; set; }
[Column("created_at")]
public DateTime CreatedAt { get; set; }
[Column("updated_at")]
public DateTime UpdatedAt { get; set; }
public List<Ticket> Tickets { get; set; }
public Contest() {}
}
But when I retrieve the object with this code:
public async Task<Contest> GetByStatus(string status)
{
var result = await _dataContext.Contest.SingleOrDefaultAsync(c => c.Status == status);
return result;
}
In this case status is "Active", that returns this.
{
"status": 200,
"message": "Active Contest",
"data": {
"contestId": 1,
"name": "Test Fecha",
"startDate": "0001-01-01T00:00:00",
"endDate": "0001-01-01T00:00:00",
"awardDate": "2020-05-18T19:00:00",
"avaibleTickets": 0,
"totalTickets": 5000,
"status": "Active",
"dynamycFields": null,
"customMessage": null,
"gratefulMessage": null,
"ticketLifeTime": "200000",
"ticketPrice": 2000,
"governancePermit": "TEST",
"legals": "TEST",
"logo": "TEST",
"ticket": "TEST",
"saleStartDate": "2020-05-18T19:00:00",
"saleEndDate": "2020-05-18T19:00:00",
"createdAt": "2020-05-19T19:04:10.517",
"updatedAt": "2020-05-19T19:04:10.518",
"tickets": null
},
"success": true,
"pages": 0,
"totalData": 0
}
This three fields (saleEndDate,saleEndDate,awardDate) are not the value that I charge in the request body.
The fast solution is add the hours that are out of phase, but Why this is happen? Is there other way to fix it or avoid it.
I suspect that is a SQL server configuration issue because I did it with two different instances and I obtain two different results, but I am not sure
Thanks a lot.
With the comments of Caius Jard (thanks a lot) and this question in SO
Convert DateTimeOffset to DateTime and add offset to this DateTime
And this:
Convert datetime without timezone
I was able to achieve the desired behavior
Hera the code that works for me:
var activeContest = await _contestService.GetByStatus("Active");
if (activeContest == null)
{
var AwardDateFormated = DateTimeOffset.Parse(request.AwardDate);
var StartDateFormated = DateTimeOffset.Parse(request.SaleStartDate);
var EndDateFormated = DateTimeOffset.Parse(request.SaleEndDate);
var contest = new Contest
{
Name = request.Name,
AwardDate = AwardDateFormated.UtcDateTime,
TotalTickets = request.TotalTickets,
GovernancePermit = request.GovernancePermit,
Logo = request.Logo,
Ticket = request.Ticket,
Legals = request.Legals,
Status = "Active",
TicketLifeTime = request.TicketLifeTime,
TicketPrice = request.TicketPrice,
SaleStartDate = StartDateFormated.UtcDateTime,
SaleEndDate = EndDateFormated.UtcDateTime,
CreatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
UpdatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
};
var result = await _contestService.Create(contest);
Now I retrieve exactly the data that I want, I don't really know if this is the best solution but for now works. Hope helps someone else.

handle empty Json Array from object

I have a json object that returns two empty arrays
"subQuestions": [] and "answers": []
I have created classes for the object, but I cannot get it to work,
this is what I have so far.
Object
"questions": [
{
"questionId": "1",
"question": "Ipsum",
"helpText": null,
"questionType": "MultipleChoice",
"answerChoices": [
{
"answerChoiceId": "b2b-2.01-answer1",
"value": "Lorem",
"subQuestions": []
}
],
"answers": []
}
Classes
public class AnswerChoice
{
public string answerChoiceId { get; set; }
public string value { get; set; }
public List<object> subQuestions { get; set; }
}
public class Question
{
public string questionId { get; set; }
public string question { get; set; }
public object helpText { get; set; }
public string questionType { get; set; }
public List<AnswerChoice> answerChoices { get; set; }
public List<object> answers { get; set; }
}
public class ObjectRoot
{
public string productId { get; set; }
public List<Question> questions { get; set; }
}
var jsonBody = new ObjectRoot()
{
productId = productId,
questions = new[]
{
new Question() {
questionId = "b2b-2.01",
question ="Vad är syftet med ert engagemang hos oss?",
helpText = null,
questionType = "MultiChoise",
answerChoices = new []{
new AnswerChoice{
answerChoiceId = "",
value = "",
**HERE is what it gets tricky for me**
}
}
}
}
};
The tricky part for me is after value = "", and the subQuestion object needs to be added, have tried multiple ways but no luck.
In your classes all collections is List not array. So to make it work you need to call ToList extension method. And for empty collections just call List constructor
var jsonBody = new ObjectRoot()
{
productId = "productId",
questions = new[]
{
new Question() {
questionId = "b2b-2.01",
question ="Vad är syftet med ert engagemang hos oss?",
helpText = null,
questionType = "MultiChoise",
answerChoices = new []{
new AnswerChoice{
answerChoiceId = "",
value = "",
subQuestions = new List<object>() // empty collection
}
}.ToList(),
answers = new List<object>()
}
}.ToList()
};

How can I create a JsonPatchDocument from comparing two c# objects?

Given I have two c# objects of the same type, I want to compare them to create a JsonPatchDocument.
I have a StyleDetail class defined like this:
public class StyleDetail
{
public string Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public decimal OriginalPrice { get; set; }
public decimal Price { get; set; }
public string Notes { get; set; }
public string ImageUrl { get; set; }
public bool Wishlist { get; set; }
public List<string> Attributes { get; set; }
public ColourList Colours { get; set; }
public SizeList Sizes { get; set; }
public ResultPage<Style> Related { get; set; }
public ResultPage<Style> Similar { get; set; }
public List<Promotion> Promotions { get; set; }
public int StoreStock { get; set; }
public StyleDetail()
{
Attributes = new List<string>();
Colours = new ColourList();
Sizes = new SizeList();
Promotions = new List<Promotion>();
}
}
if I have two StyleDetail objects
StyleDetail styleNew = db.GetStyle(123);
StyleDetail styleOld = db.GetStyle(456);
I now want to create a JsonPatchDocument so I can send the differences to my REST API... How to do this??
JsonPatchDocument patch = new JsonPatchDocument();
// Now I want to populate patch with the differences between styleNew and styleOld - how?
in javascript, there is a library to do this https://www.npmjs.com/package/rfc6902
Calculate diff between two objects:
rfc6902.createPatch({first: 'Chris'}, {first: 'Chris', last:
'Brown'});
[ { op: 'add', path: '/last', value: 'Brown' } ]
but I am looking for a c# implementation
Let's abuse the fact that your classes are serializable to JSON!
Here's a first attempt at a patch creator that doesn't care about your actual object, only about the JSON representation of that object.
public static JsonPatchDocument CreatePatch(object originalObject, object modifiedObject)
{
var original = JObject.FromObject(originalObject);
var modified = JObject.FromObject(modifiedObject);
var patch = new JsonPatchDocument();
FillPatchForObject(original, modified, patch, "/");
return patch;
}
static void FillPatchForObject(JObject orig, JObject mod, JsonPatchDocument patch, string path)
{
var origNames = orig.Properties().Select(x => x.Name).ToArray();
var modNames = mod.Properties().Select(x => x.Name).ToArray();
// Names removed in modified
foreach (var k in origNames.Except(modNames))
{
var prop = orig.Property(k);
patch.Remove(path + prop.Name);
}
// Names added in modified
foreach (var k in modNames.Except(origNames))
{
var prop = mod.Property(k);
patch.Add(path + prop.Name, prop.Value);
}
// Present in both
foreach (var k in origNames.Intersect(modNames))
{
var origProp = orig.Property(k);
var modProp = mod.Property(k);
if (origProp.Value.Type != modProp.Value.Type)
{
patch.Replace(path + modProp.Name, modProp.Value);
}
else if (!string.Equals(
origProp.Value.ToString(Newtonsoft.Json.Formatting.None),
modProp.Value.ToString(Newtonsoft.Json.Formatting.None)))
{
if (origProp.Value.Type == JTokenType.Object)
{
// Recurse into objects
FillPatchForObject(origProp.Value as JObject, modProp.Value as JObject, patch, path + modProp.Name +"/");
}
else
{
// Replace values directly
patch.Replace(path + modProp.Name, modProp.Value);
}
}
}
}
Usage:
var patch = CreatePatch(
new { Unchanged = new[] { 1, 2, 3, 4, 5 }, Changed = "1", Removed = "1" },
new { Unchanged = new[] { 1, 2, 3, 4, 5 }, Changed = "2", Added = new { x = "1" } });
// Result of JsonConvert.SerializeObject(patch)
[
{
"path": "/Removed",
"op": "remove"
},
{
"value": {
"x": "1"
},
"path": "/Added",
"op": "add"
},
{
"value": "2",
"path": "/Changed",
"op": "replace"
}
]
You could use my DiffAnalyzer. It's based on reflection and you can configure the depth you want to analyze.
https://github.com/rcarubbi/Carubbi.DiffAnalyzer
var before = new User { Id = 1, Name="foo"};
var after= new User { Id = 2, Name="bar"};
var analyzer = new DiffAnalyzer();
var results = analyzer.Compare(before, after);
You can use this
You can install using NuGet, see SimpleHelpers.ObjectDiffPatch at NuGet.org
PM> Install-Package SimpleHelpers.ObjectDiffPatch
Use:
StyleDetail styleNew = new StyleDetail() { Id = "12", Code = "first" };
StyleDetail styleOld = new StyleDetail() { Id = "23", Code = "second" };
var diff = ObjectDiffPatch.GenerateDiff (styleOld , styleNew );
// original properties values
Console.WriteLine (diff.OldValues.ToString());
// updated properties values
Console.WriteLine (diff.NewValues.ToString());

Json not returning the correct values in the desired pattern

I need this as my json return. This data is being pulled from the DB but currently I am using static data.
{
"data": [
{
"id": 1,
"latitude":17.3700,
"longitude": 78.4800,
"gallery":
[
"assets/img/items/1.jpg"
]
}
]
}
I have tried this in my code behind but I am not getting the desired result.
[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public List<> getData()
{
Account account = new Account
{
id = 1,
latitude = "17.3700",
longitude ="78.4800",
gallery = new List<string>
{
"assets/img/items/1.jpg",
"assets/img/items/2.jpg",
}
};
return new JavaScriptSerializer().Serialize(account);
}
public class Account
{
public int id { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public IList<string> gallery { get; set; }
}
Result:
{
"id":2,
"latitude":"17.3700",
"longitude":"78.4800",
"gallery":["assets/img/items/1.jpg","assets/img/items/2.jpg"]
}
You need to create a new class with the data property:
public class Result { public object[] Data { get; set; } }
and return that:
public string getData()
{
Result result = new Result
{
Data = new [] { new Account { id = 1, ... } }
};
return new JavaScriptSerializer().Serialize(result);
}

Appending to JSON object using JSON.net

I need to serialize a JSON object that looks like this:
{
"Documents": [
{
"Title": "",
"DatePublished": "",
"DocumentURL": "",
"ThumbnailURL": "",
"Abstract": "",
"Sector": "",
"Country": [
"", "", ""
],
"Document Type": ""
}
]
}
What I'm doing is taking the data from SQL server and storing the results into an object like this:
public List<Dictionary<string, string>> GetResults()
{
int index = 0;
while (this.myReader.Read())
{
this.dataFrmDb = new Dictionary<string, string>();
for (int i = 0; i < myReader.FieldCount; i++)
{
if (myReader.GetName(i) == "Country")
{
string[] delimiter = { " _qfvcq_ " };
string text = myReader[myReader.GetName(i)].ToString();
string[] results = text.Split(delimiter, StringSplitOptions.None);
//This list stores the values for "Country".
List<string> countries = new List<string>();
for (int j = 0; j < results.Count(); j++)
{
countries.Add(results[j].ToString());
}
}
else
{
this.dataFrmDb.Add(myReader.GetName(i),
myReader[myReader.GetName(i)].ToString());
}
}
this.dictList.Add(this.dataFrmDb);
}
return this.dictList;
}
I then take this data and serialize like this:
Database connect = new Database(
System.Configuration.ConfigurationManager.AppSettings["DatabaseConnectionString"],
System.Configuration.ConfigurationManager.AppSettings["StoredProcedure"]);
List<Dictionary<string, string>> dataResults = connect.GetResults();
Dictionary<string, List<Dictionary<string, string>>> myList =
new Dictionary<string, List<Dictionary<string, string>>>();
myList.Add("Documents", dataResults);
string ans = JsonConvert.SerializeObject(myList, Formatting.Indented);
System.Console.WriteLine(ans);
I get the proper output but if you would look in the original JSON format, "Country" needs to have multiple values. I don't know how to implement that into this JSON object. How do I add a list with the "Country" values to the JSON object using JSON.net? Is there another way to go about this?
If you change dataFrmDb to be Dictionary<string, object> instead of a Dictionary<string, string>, then you can store the Countries list into it like the other values. Json.Net will then serialize it like you want.
Here is an example program which demonstrates:
class Program
{
static void Main(string[] args)
{
List<Dictionary<string, object>> dataResults = GetResults();
Dictionary<string, List<Dictionary<string, object>>> myList =
new Dictionary<string, List<Dictionary<string, object>>>();
myList.Add("Documents", dataResults);
string ans = JsonConvert.SerializeObject(myList, Formatting.Indented);
System.Console.WriteLine(ans);
}
public static List<Dictionary<string, object>> GetResults()
{
List<Dictionary<string, object>> dictList = new List<Dictionary<string, object>>();
Dictionary<string, object> dataFrmDb = new Dictionary<string, object>();
dataFrmDb.Add("Title", "An Example Document");
dataFrmDb.Add("DatePublished", DateTime.Now.ToString());
dataFrmDb.Add("DocumentURL", "http://www.example.org/documents/1234");
dataFrmDb.Add("ThumbnailURL", "http://www.example.org/thumbs/1234");
dataFrmDb.Add("Abstract", "This is an example document.");
dataFrmDb.Add("Sector", "001");
dataFrmDb.Add("Country", new List<string> { "USA", "Bulgaria", "France" });
dataFrmDb.Add("Document Type", "example");
dictList.Add(dataFrmDb);
return dictList;
}
}
Output:
{
"Documents": [
{
"Title": "An Example Document",
"DatePublished": "4/9/2013 7:25:05 PM",
"DocumentURL": "http://www.example.org/documents/1234",
"ThumbnailURL": "http://www.example.org/thumbs/1234",
"Abstract": "This is an example document.",
"Sector": "001",
"Country": [
"USA",
"Bulgaria",
"France"
],
"Document Type": "example"
}
]
}
A somewhat more straightforward way to do it is to create separate classes to hold the data, as was suggested by Joey Gennari. Json.NET can serialize those as well. The data classes would look something like this:
class Result
{
public List<Document> Documents { get; set; }
public Result()
{
Documents = new List<Document>();
}
}
class Document
{
public string Title { get; set; }
public string DatePublished { get; set; }
public string DocumentURL { get; set; }
public string ThumbnailURL { get; set; }
public string Abstract { get; set; }
public string Sector { get; set; }
public List<string> Country { get; set; }
[JsonProperty(PropertyName="Document Type")]
public string DocumentType { get; set; }
public Document()
{
Country = new List<string();
}
}
And here is the usage:
class Program
{
static void Main(string[] args)
{
Document doc = new Document();
doc.Title = "An Example Document";
doc.DatePublished = DateTime.Now.ToString();
doc.DocumentURL = "http://www.example.org/documents/1234";
doc.ThumbnailURL = "http://www.example.org/thumbs/1234";
doc.Abstract = "This is an example document.";
doc.Sector = "001";
doc.Country.Add("USA");
doc.Country.Add("Bulgaria");
doc.Country.Add("France");
doc.DocumentType = "example";
Result result = new Result();
result.Documents.Add(doc);
string json = JsonConvert.SerializeObject(result, Formatting.Indented);
System.Console.WriteLine(json);
}
}
The output for this example is exactly the same as the first.
Here is a different way to solve it with DataContractJsonSerializer. First create a class to represent the object:
[DataContract]
public class DocumentHolder
{
[DataMember(Name = "Documents")]
public Documents Document { get; set; }
}
[DataContract]
public class Documents
{
[DataMember(Name = "Title", Order = 1)]
public string Title { get; set; }
[DataMember(Name = "DatePublished", Order = 2)]
public DateTime? DatePublished { get; set; }
[DataMember(Name = "DocumentURL", Order = 3)]
public string DocumentURL { get; set; }
[DataMember(Name = "ThumbnailURL", Order = 4)]
public string ThumbnailURL { get; set; }
[DataMember(Name = "Abstract", Order = 5)]
public string Abstract { get; set; }
[DataMember(Name = "Sector", Order = 6)]
public string Sector { get; set; }
[DataMember(Name = "Country", Order = 7)]
public List<string> Country { get; set; }
[DataMember(Name = "Document Type", Order = 8)]
public string DocumentType { get; set; }
public Documents()
{
this.Country = new List<string>();
}
}
Here's how you would fill the object and serialize it:
static void Main(string[] args)
{
var documentholder = new DocumentHolder { Document = new Documents { Title = "Title 1", DatePublished = DateTime.Now, Sector = "A17", Country = new List<string> { "EN-US", "EN-GB" } } };
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DocumentHolder));
var ms = new MemoryStream();
serializer.WriteObject(ms, documentholder);
var text = Encoding.UTF8.GetString(ms.ToArray());
}

Categories