I am trying to create a POST endpoint where on success, it will send an HTML email with the POST data. I am struggling trying to iterate over the JSON array of objects and appending that data to a HTML table.
JSON data:
{
"Submitter":[
{
"Obj1":[
"test",
"test2"
]
},
{
"Obj2":[
"test3",
"test4"
]
}
]
}
TestingController:
public class Testing2Controller : ControllerBase
{
public class Submitter
{
public List<string> Obj1 { get; set; }
public List<string> Obj2 { get; set; }
}
public class MyData
{
public List<Submitter> Submitter { get; set; }
}
public string POST([FromBody] MyData data)
{
string composeTableObj1 = @"";
string composeTableObj2 = @"";
foreach (var item in data.Submitter)
{
composeTableObj1 = $"<tr>"; //start row tag
//Column 1 Obj1 data
if (item.Obj1 != null)
{
foreach (var objItem in item.Obj1)
{
composeTableObj1 = $"<td>{objItem}</td>";
}
}
//Column 2 Obj2 data
if (item.Obj2 != null)
{
foreach (var objItem in item.Obj2)
{
composeTableObj1 = $"<td>{objItem}</td>";
}
}
composeTableObj1 = $"</tr>"; //end row tag
}
string body = @$"<table>
<thead>
<tr>
<th>Object 1</th>
<th>Object 2</th>
</tr>
</thead>
<tbody>
{composeTableObj1}
</tbody>
</table>
";
return body;
}
}
The above code gives me the following undesired result:
| Object 1 | Object 2 |
|----------|----------|
| test | test2 |
| test3 | test4 |
This is the desired result I'm after:
| Object 1 | Object 2 |
|----------|----------|
| test | test3 |
| test2 | test4 |
Been stuck on this for quite some time, TIA!
CodePudding user response:
Looks like your HTML is a bit off - writing HTML like this can be tedious. I am guessing based off of the hard coded table headers in the HTML and the structure of the Submitter
class that you will only ever have two Objn
items in your JSON. If this is true, you can ditch the foreach
loop for a for
loop, and get the value out of data.Submitter[n]
using the loops iterator:
public string Post([FromBody] MyData data)
{
string composeTableObj = "";
for (int i = 0; i < data.Submitter.Count(); i )
{
composeTableObj = $"<tr>"; //start row tag
composeTableObj = $"<td>{data.Submitter[0].Obj1[i]}</td>";
composeTableObj = $"<td>{data.Submitter[1].Obj2[i]}</td>";
composeTableObj = $"</tr>"; //end row tag
}
return @$"<table><thead><tr><th>Object 1</th><th>Object 2</th></tr></thead><tbody>{composeTableObj}</tbody></table>";
}
Returned HTML:
<table><thead><tr><th>Object 1</th><th>Object 2</th></tr></thead><tbody><tr><td>test</td><td>test3</td></tr><tr><td>test2</td><td>test4</td></tr></tbody></table>
Rendered:
Obviously, this isn't very dynamic. If you find you need more Objn
, you'll need to update the Submitter
class, and you will have to add to the code within the loop (and add another header for your HTML).
If you have more items in the Obj
arrays, you can do the following:
public string Post([FromBody] MyData data)
{
string composeTableObj = "";
int obj1Count = data.Submitter[0].Obj1.Count;
int obj2Count = data.Submitter[1].Obj2.Count;
int loopCount = obj1Count >= obj2Count ? obj1Count : obj2Count;
for (int i = 0; i < loopCount; i )
{
string obj1String = obj1Count <= i ? " " : data.Submitter[0].Obj1[i];
string obj2String = obj2Count <= i ? " " : data.Submitter[1].Obj2[i];
composeTableObj = $"<tr>"; //start row tag
composeTableObj = $"<td>{obj1String}</td>";
composeTableObj = $"<td>{obj2String}</td>";
composeTableObj = $"</tr>"; //end row tag
}
return @$"<table><thead><tr><th>Object 1</th><th>Object 2</th></tr></thead><tbody>{composeTableObj}</tbody></table>";
}
This first gets the greater of the two .Count
s between your Obj
lists to set the loops condition, and then performs an index bounds check. If the objnCount
is less than or equal to i
, set it to a space, otherwise take the value for its respective Obj
list. With 6 items in Obj2
and only 2 items in Obj1
, the HTML looked like this: