Cant get model fields to display on the page - c#

I'm using this model:
public class ListCoins
{
public Dictionary<string,Dictionary<string,float>> listCoins{ get; set; }
}
when I try to display them in the view using this method:
model IEnumerable<Crytocurrency_Web___Main.JResult.ListCoins>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<h4>Coin Value: #ViewBag.WalletValue</h4>
<table class="table">
<tr>
<th>
#Html.DisplayName("Name"))
</th>
<th>
#Html.DisplayName("CoinValue")
</th>
<th>
#Html.DisplayName("CoinAmmount")
</th>
<th></th>
</tr>
#for (var i = 0; i < Model.ElementAt(i).listCoins.Count; i++)
{
foreach (var coin in Model.ElementAt(i).listCoins)
{
<p>#coin.Key + " " + #coin.Value)</p>
}
}
i get the error on the line:
#for (var i = 0; i < Model.ElementAt(i).listCoins.Count; i++)
but in the controller i have checked that count is over one:
int counter = listOfCoins.Count;
which equals four and all the data is there.
i may just be displaying them wrong but i cant figure it out
controller code:
List<ListCoins> newListCoins = new List<ListCoins>();
foreach (var coin in listOfCoins)
{
using (WebClient client = new WebClient())
{
var json = client.DownloadString(
"https://min-api.cryptocompare.com/data/pricemulti?fsyms=" + queryString + "&tsyms=" +
queryString);
var result = Newtonsoft.Json.JsonConvert
.DeserializeObject<Dictionary<string, Dictionary<string, float>>>(json);
newListCoins.Add(new ListCoins
{
listCoins = result,
});
}
}
return View(newListCoins.ToList());

I don't think you need to use: Model.ElementAt(i). You can do this:
#for (var i = 0; i < Model.listCoins.Count; i++)
rather than this:
#for (var i = 0; i < Model.ElementAt(i).listCoins.Count; i++)
You can then loop through all of the elements in listCoins and display the values in the view.

You are getting ArgumentOutOfRangeException because you are trying to access an item in the collection with an index which does not exist!
This part in your for loop
i < Model.ElementAt(i).listCoins.Count
You are trying to loop until n where n is the Count of your child property listCoins of each item.
Your view is strongly typed to a collection of ListCoins. So Your outer loop should be from 0 to Model.Count
#for (var i = 0; i < Model.Count; i++)
{
foreach (var coin in Model.ElementAt(i).listCoins)
{
<p>#coin.Key + " " + #coin.Value)</p>
}
}
Here , the coin.Value is again another dictionary(Dictionary<string,float>), so you probably want to loop through the items in that as well.
I feel the foreach version could be more readable.
#foreach (var item in Model)
{
foreach (var coin in item.listCoins)
{
<h1>#coin.Key</h1>
foreach (var v in coin.Value)
{
<p>#v.Key - #v.Value</p>
}
}
}

Related

C# Blazor Table RemoveVariant event

This is a Razor page.
I'm trying to write a function that can be binded to an event that deletes the current row.
How to write the function?
the html code
#for (int i = 0; i < Count; i++)
{
<th width="250" > #(i + 1)
<MatIconButton Icon="clear" OnClick="#RemoveVariant" class="text-right"></MatIconButton>
</th>
}
</tr>
C# code
private void RemoveVariant(int index)
{
ShouldRender();
l_VKDTI_TSI.Remove(l_VKDTI_TSI[index]);
l_VKDTI_VI.Remove(l_VKDTI_VI[index]);
l_VKDTI_DIMENSIONS.Remove(l_VKDTI_DIMENSIONS[index]);
l_VKDTI_VW.Remove(l_VKDTI_VW[index]);
l_VKDTI_ENGINE.Remove(l_VKDTI_ENGINE[index]);
l_VKDTI_TRANSMISSION.Remove(l_VKDTI_TRANSMISSION[index]);
l_VKDTI_DRIVETRAIN.Remove(l_VKDTI_DRIVETRAIN[index]);
l_VKDTI_TAW.Remove(l_VKDTI_TAW[index]);
l_VKDTI_HUMP.Remove(l_VKDTI_HUMP[index]);
l_VKDTI_WAP.Remove(l_VKDTI_WAP[index]);
l_VKDTI_PEDAL.Remove(l_VKDTI_PEDAL[index]);
l_VKDTI_BOOSTER.Remove(l_VKDTI_BOOSTER[index]);
l_VKDTI_MC.Remove(l_VKDTI_MC[index]);
l_VKDTI_FB.Remove(l_VKDTI_FB[index]);
l_VKDTI_RB.Remove(l_VKDTI_RB[index]);
l_VKDTI_OVI.Remove(l_VKDTI_OVI[index]);
l_ESPTI_VAF_ALL.Remove(l_ESPTI_VAF_ALL[index]);
l_ESPTI_VAF_ALL_SELECTED.Remove(l_ESPTI_VAF_ALL_SELECTED[index]);
StateHasChanged();
}
Call your function with a copy of the loop variable.
#for (int i = 0; i < Count; i++)
{
var iCopy = i;
<th width="250" >
<MatIconButton Icon="clear" OnClick="#(()=>RemoveVariant(iCopy))" class="text-right"></MatIconButton>
</th>
}

Filling specific cells in html table with razor pages

After trying to fill a html table with data from a MVC model, we ran into a problem. This code below generates a table, which is supposed to represent a schedule. The first row displays the days of the week, and the first column displays the number representation of the school hours.
<table class="table2">
<tr>
<th></th>
#{ string[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };}
#for (int i = 0; i < days.Length; i++)
{
<th>#(days[i])</th>
}
</tr>
#{
TimeSpan timeSpan = new TimeSpan(8, 30, 0); //08:30:00
TimeSpan AddTime = new TimeSpan(0, 50, 0); //00:50:00
TimeSpan timeSpan2 = new TimeSpan();
}
#{ for (int i = 1; i < 16; i++)
{
<tr>
<td>
<h3>#(i)</h3>
<a>
#{timeSpan.ToString();}
#(string.Format("{0:00}:{1:00}", timeSpan.Hours, timeSpan.Minutes))
</a>
#{timeSpan2 = timeSpan.Add(AddTime);}
<div>
<a>
#(string.Format("{0:00}:{1:00}", timeSpan2.Hours, timeSpan2.Minutes))
#{timeSpan = timeSpan2;}
</a>
</div>
</td>
#foreach (var item in Model)
{
if (item.Hours.Contains(i))
{
for (int x = 0; x < days.Length; x++)
{
if (item.Day != days[x])
{
<td>
</td>
}
else
{
<td>
#(item.Class)
#(item.Classroom)
</td>
}
}
}
}
</tr>
}
}
</table>
Our model looks like this;
public class ScheduleModel
{
[Display(Name = "Lesson Code")]
public string LessonCode { get; set; }
[Display(Name = "Day")]
public string Day { get; set; }
[Display(Name = "Classroom")]
public string Classroom { get; set; }
[Display(Name = "Hours")]
public int[] Hours { get; set; }
[Display(Name = "Class")]
public string Class { get; set; }
}
Ill try to explain what we're trying to do. Our view gets a list of models, filled with the data specified above. We want to display this data in the html table we tried to create above. The "Day" variable corresponds to the days in the top row of the table, and the Hours int[] corresponds to the hours in the first column of the table. These values should be compared with eachother to find the correct spot in the table. We almost got it to work, with the code displayed above, but we ran into a problem with duplicate hours and empty cells.
Lets say we get 2 instances of the model, one looks like this;
Day : Monday
Hours : [1,2,3]
and the second looks like this :
Day : Tuesday
Hours: [1,2,3]
The problem with this is that the foreach loop goes through the first model completly, and fills all cells in the first row with empty cells, then when the foreach loops through the second model, it cannot fill the already created empty cells, so it just sticks them on at the end; screenshot to visualize the problem ;
So it all boils down to this; how do we generate the rows, but in such a way that we can still add new data into the empty fields.
This works perfectly!
#for (int x = 0; x < 7; x++)
{
<td>
#foreach(var item in Model)
{
if (item.Hours.Contains(i))
{
if(item.Day == days[x]){
#(item.Class)
#(item.Classroom)
}
else
{
#("")
}
}
}
</td>
}

How to load a csv file as Json data in a MVC web application. Header can be different

I'm trying to read a csv file so that I can load a jQuery DataTable. The csv file might have different headers. I was using the header to create the columns for the jQuery table. Then loading the file in and creating the rows. I was doing this directly from the csv file and all worked okay, but only if the file was small. I needed to move to using Json in order to implement a way using Linq to sort, filter, and query in the Model portion of the code. While trying to move to an MVC model, I got into a position where I can't extract the rows from the Json data.
Here is the ViewFile, which currently has the LoadDataAsJson (which should be in the Model class, I'll bet). The Json it creates is correct.
public IActionResult ViewFile()
{
string fileName = Request.Form["fileName"];
ViewData["name"] = fileName;
ViewData["data"] = LoadDataAsJson(dir + Path.DirectorySeparatorChar + fileName, 100);
return View();
}
private string LoadDataAsJson(string fileName, int limit)
{
string[] headers = new string[8];
StringBuilder bldr = new StringBuilder();
bldr.Append("[");
using (TextReader reader = new StreamReader(fileName))
{
String line = null;
int k = 0;
while ((line = reader.ReadLine()) != null)
{
if (k > limit)
break;
if (k++ != 0)
{
if (k != 2)
bldr.Append(","); // append a comma to the end of previous line
List<string> aRow = FormatAsJsonArray(line);
bldr.AppendLine();
bldr.Append("{");
for (int i = 0; i < headers.Length; i++)
{
bldr.Append(headers[i]);
bldr.Append(":\"");
bldr.Append(aRow[i]);
bldr.Append("\"");
if (i != headers.Length - 1)
bldr.Append(",");
}
bldr.Append("}");
}
else
{
headers = line.Split(',');
}
}
}
bldr.Append(Environment.NewLine + "]" + Environment.NewLine);
return bldr.ToString();
}
private List<string> FormatAsJsonArray(string aLine)
{
int k = 0;
string[] tokens = aLine.Split(',');
List<string> items = new List<string>();
string lastPart = "";
if (tokens.Length > 6)
{
for (int i = 7; i < tokens.Length; i++)
{
lastPart = String.Concat(lastPart, tokens[i]);
if (i != tokens.Length - 1)
lastPart += ",";
}
}
for (int i = 0; i < tokens.Length; i++)
{
if (i > 8)
break;
if (tokens[i].Contains("["))
{
List<string> msecs = MsecColumnAsJson(tokens[i]);
for (int kk = 0; kk < msecs.Count; kk++)
items.Add(msecs[kk]);
}
else if (k < 7)
items.Add(tokens[i]);
k++;
}
if (lastPart != null && lastPart.Length > 0)
items.Add(lastPart);
return items;
}
The ViewFile.cshtml contains in part.
<h2>#ViewData["name"]</h2>
<div class="container">
<br />
<table id="table_id" class="table table-condensed table-striped table-hover display">
<thead>
<tr>
<th>DateTime</th>
<th>Msecs</th>
<th>Thread</th>
<th>Level</th>
<th>Logger</th>
<th>Host</th>
<th>Msg Type</th>
<th>Message</th>
</tr>
</thead>
<tbody>
#{
string logFile = (string)#ViewData["data"];
var k = 0;
}
#foreach (string lf logFile)
{
if (k++ > 50)
{
break;
}
<tr>
#foreach (string item in lf)
{
<td>
#item
</td>
}
</tr>
}
</tbody>
</table>
</div>
I end up getting cannot convert type 'char' to 'string' in each of the foreach statements. I tried using var for the var logFile = #ViewData["data"] line, but then the rest isn't working.
My intention was to extract on Json array line at a time, then break each of those up into a single td. How can I use the LogFileModel to contain the handling of the data, and create a view and controller to do this?
I would suggest going a different approach.
Use TextFieldParser from Microsoft.VisualBasic.FileIO (Yes, you can use that in C#) to read CSV and place it as data model and then use Newtonsoft.Json to create json from that objects.
Here's more on TextFieldParser: https://coding.abel.nu/2012/06/built-in-net-csv-parser/

razor syntax to write tags based on the condistion

#for (var i = 0; i < 3; i++)
{
if(#Model.lstEmp[i].isTrue==true)
{
<tr bgcolor="red">
}
else
{
<tr>
}
<td>#Model.lstDept[i].DeptId</td>
<td>#Model.lstEmp[i].EmpId</td>
</tr>
}
I am facing an error message that '}' not found. when I write everything inside the if and else block I'm not facing any issue but if I write like above I'm facing the issue. please help me in solving this.
Try the following:
#for (var i = 0; i < 3; i++)
{
if(#Model.lstEmp[i].isTrue==true)
{
#:<tr bgcolor="red">
}
else
{
#:<tr>
}
#:<td>#Model.lstDept[i].DeptId</td>
#:<td>#Model.lstEmp[i].EmpId</td>
#:</tr>
}
I think the only problem is that you have if(#Model). You don't need the # there because it is still in the razor context. Somehow it knows whether or not to interpret it as c# or html (not always perfect).
#for (var i = 0; i < 3; i++)
{
if(Model.lstEmp[i].isTrue==true)
{
<tr bgcolor="red">
}
else
{
<tr>
}
<td>#Model.lstDept[i].DeptId</td>
<td>#Model.lstEmp[i].EmpId</td>
</tr>
}

Razor View dynamic table rows

I want have a table in my view that is going to put 3 elements from my Model in each row. So the way I was going to do this is to loop through the model and inside of the foreach loop do a check on a count variable I have set up. If count mod 3 == 0 I would do something like </tr><tr> to start a new row. This isn't working the way I want it to because I would have a } following the <tr>. So basically my question is, how would I create a dynamic table inside of a razor view based on the elements in the model where each row has 3 items?
#{
int count = 0;
<div>
<table>
<tr>
#foreach (var drawing in Model)
{
<td style="width:240px;margin-left:30px; margin-right:30px;">
<img src="#Url.Action("GetImage", "Home", new { id = drawing.drw_ID })" alt="drawing" />
</td>
count++;
if(count%3==0)
{
</tr>
<tr>
}
}
</tr>
</table>
</div>
}
Maybe there is a much easier way of doing this that I am not thinking of
How about using two loops - this will make your document be setup much more nicely and make it a bit more readable. Also, it takes care of the problems that occur if the number of rows is not divisible by three:
<div>
<table>
#for(int i = 0; i <= (Model.Count - 1) / 3; ++i) {
<tr>
for(int j = 0; j < 3 && i + j < Model.Count; ++j) {
<td style="width:240px;margin-left:30px; margin-right:30px;">
<img src="#Url.Action("GetImage", "Home", new { id = Model[i + j].drw_ID })" alt="drawing" />
</td>
}
</tr>
}
</table>
</div>
Edited to reflect your pasted code. Note, this assumes the model implements IList or an array
Maybee this is the solution you are looking for works for me
#{
int count = 0;
**
var tr = new HtmlString("<tr>");
var trclose = new HtmlString("</tr>");
**
<div>
<table>
<tr>
#foreach (var drawing in Model)
{
<td style="width:240px;margin-left:30px; margin-right:30px;">
<img src="#Url.Action("GetImage", "Home", new { id = drawing.drw_ID })" alt="drawing" />
</td>
count++;
if(count%3==0)
{
**
trclose
tr
**
}
}
</tr>
</table>
</div>
}
Check this out, this should work for you !!!
<h2>Index</h2>
<table>
<tr>
#{
var index = 0;
}
#foreach (int num in Model)
{
if ((index % 10) == 0)
{
#Html.Raw("</tr>");
#Html.Raw("<tr>");
}
<td>
<h2>#num</h2>
</td>
index++;
}
</tr>
</table>
The #christian solution worked for me.I was not sure of "trclose" and "tr" hence posting here the solution that worked for me in razor view.
<table>
<tr><td><input type="checkbox" id="chkAssetCategories" /> SELECT ALL</td></tr>
<tr>
#{
var count=0;
foreach (var item in Model.AssetCategories)
{
<td><input type="checkbox" class = "Catgories" id='#item.ID' value ='#item.ID' /><label>#item.Name</label></td>
if (count%5 == 0)
{
#:</tr><tr>
}
count++;
}
}
</table>
#{ int counter = 0;}
<div>
<table>
#for(int i = 0; i <= (Model.Count - 1) / 3; ++i) {
<tr>
for(int j = 0; j < 3; ++j) {
<td style="width:240px;margin-left:30px; margin-right:30px;">
#Model[counter]
</td>
counter++;
}
</tr>
}
</table>
</div>

Categories

Resources