Parsing error in cshtml file in ASP.NET MVC4 - c#

In the view, I am trying to display at most 5 images in a row.
The idea is to introduce a new row by using the </tr><tr> html tags to close the present row and start a new one as shown below, but this gives a Parser error.
Parser Error Message: The code block is missing a closing "}"
character. Make sure you have a matching "}" character for all the
"{" characters within this block, and that none of the "}" characters
are being interpreted as markup.
How can I correct this?
<table>
<tr>
#{
int indx = 0;
foreach(var item in Model) {
indx++;
<td>
<a href ="#Url.Action("ShowPic", "ViewPhotos", new { id = item.ID })">
<img src="#String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(item.Image))" />
</a>
<br />
#Html.DisplayFor(modelItem => item.Caption)
</td>
if(indx%5==0) {
</tr><tr><!--Error here-->
}
}
}
</tr>
</table>
Thanks.

Try adding this to the row in question
#: </tr><tr><!--Error here-->
Because you are wrapping it in a HTML tag element, Razor cannot determine that the content within the if is the start of a content block. By using #: we are indicating that the contents of the statement should be treated as content.

Your first <tr> and last </tr> is outside of the scope of it's opening/closing tag:
<table>
#{
<tr>
int indx = 0; foreach (var item in Model) { indx++;
<td>
<a href ="#Url.Action("ShowPic", "ViewPhotos", new { id = item.ID })">
<img src="#String.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(item.Image))" />
</a>
<br />
#Html.DisplayFor(modelItem => item.Caption)
</td>
if(indx%5==0) {
</tr>
<tr>
} }
</tr>
}
</table>

Related

Blazor App Not Using Nested If Statements Properly

I know, I suck because I am using a table and not div tags but I could not get the div tags to display properly and my deadline was some time last week...
I am trying to layout a bunch of devices along with their statuses and other simple options and yet I cannot get the ìf statements to work. Here is my code:
#if (CurrentSystem == null)
{
<p><em>Loading...</em></p>
}
else
{
#foreach (Device thisDevice in CurrentSystem.LocalDevices)
{
menuCounter++;
divCounter++;
if (divCounter == 1)
{
//Starting with the first column
<tr><td class=cardBox>
}
else
{
//Starting with the last column
<tr><td class=outSideColumns></td>
<td></td>
<td class=cardBox>
}
targetName = "target" + #menuCounter;
targetNameWithDot = "." + #targetName;
menuId = "contextMenu" + #menuCounter;
modalID = "modalWindow" + #menuCounter;
<table>
<tr>
<td></td>
<td>
<div class="targetName" style="text-align:right;justify-content:right;">
...
</div>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<h3>
thisDevice.DeviceName
</h3>
<img src="#ReturnDeviceImage(thisDevice)" class=deviceImage />
#if (thisDevice.CurrentStatus == Device.DeviceStatus.Alert)
{
<h4 Class="cardAlert">Status: Alert</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Inactive)
{
<h4 Class="cardInactive">Status: Inactive</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Unknown)
{
<h4 Class="cardUnknown">Status: Unknown</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Normal)
{
<h4 Class=cardNormal>Status: Normal</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Updating)
{
<h4 Class=cardUpdating>Status: Normal</h4>
}
else
{
<h4>Status: thisDevice.CurrentStatus</h4>
}
<TelerikContextMenu IdField="#menuId" Selector="#targetNameWithDot" Data="#MenuItems" OnClick="#((ContextMenuItem item) => OnItemClick(item, #thisDevice.DeviceIDHash))">
</TelerikContextMenu>
</td>
</tr>
<tr>
<td class=nameDivs>
Device Type:
</td>
<td>
#thisDevice.DeviceType
</td>
</tr>
<tr>
<td class=nameDivs>
Hostname:
</td>
<td>
#thisDevice.DeviceHostname
</td>
</tr>
<tr>
<td class=nameDivs>
Communications:
</td>
#if (thisDevice.UsingEncryption)
{
<td class=cardNormal>Are Encrypted</td>
}
else
{
<td> class=cardAlert>Are Not Encrypted</td>
}
</tr>
<tr>
<td class=nameDivs>
Anomaly Response Level:
</td>
<td>
#thisDevice.AnomalyResponse
</td>
</tr>
</table>
if (divCounter == 1)
{
//Ending the first column
</td>
<td></td>
<td class=outSideColumns></td>
</tr>
}
else
{
//Ending the last column
</td></tr>
divCounter = 0;
}
}
</table>
}
The beginning if statement and the if statements that run the CurrentStatus and UsingEncryption seem to be working, however the last if statement is simply writing text to the screen.
If I add # signs to the first and/or last if statements, I get a ton
of errors about not having closing tags, objects not being defined,
etc...
If I remove the # signs from the CurrentStatus and UsingEncryption if
statements, those statements stop working.
If I remove the # from the foreach statement, nothing prints out.
What am I doing wrong?!?
To use tag helpers, your html structure must mirror your control flow. You can't just start a tag inside an if test without also closing it within that if test.
While you can escape unmatched html tags with #: (eg Razor doesn't understand unclosed html tags), with a little effort, you can eliminate your unmatched tags;
<tr>
#if(divCounter != 1)
{
//Starting with the last column
<td class=outSideColumns></td>
<td></td>
}
<td class=cardBox>
While Jeremy provided an excellent answer. I ended up running into issues where I absolutely needed open tags and, in fact, I had to re-write everything back into DIV tags to make things work.
That is when I discovered my new bestest friend - the MarkupString - that I can use to insert any HTML code I desire without blowing up the IDE!
Here is a link that explains how to use it - https://www.meziantou.net/rendering-raw-unescaped-html-in-blazor.htm

parse table with href html agility pack

hi i want to parse table but I can't get the information completely
I used the following code that does not return the href link
HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[1]//tbody");
foreach (var cell in table.SelectNodes(".//tr/td"))
{
string someVariable = cell.InnerText;
Debug.WriteLine(someVariable);
}
i need to get href too, how can i do this?
<table>
<tbody>
<tr>
<td class="a1">
<a href="/subtitles/joker-2019/farsi_persian/2110062">
<span class="l r positive-icon">
Farsi/Persian
</span>
<span>
Joker.2019.WEBRip.XviD.MP3-SHITBOX
</span>
</a>
</td>
<td class="a3">
</td>
<td class="a40">
</td>
<td class="a5">
<a href="/u/695804">
meisam_t72
</a>
</td>
<td class="a6">
<div>
►► زیرنویس از میثم ططری - ویرایش شده ◄◄ - meisam_t72 کانال تلگرام </div>
</td>
</tr>
</tbody>
</table>
Inside your foreach you need to check if the content of your cell contains a <a> tag. If it contains just get the attribute href from this tag.
Something like this (untested)
foreach (var cell in table.SelectNodes(".//tr/td"))
{
string someVariable = cell.InnerText;
Debug.WriteLine(someVariable);
var links = cell.SelectNodes(".//a");
if (links == null || !links.Any())
{
continue;
}
foreach (var link in links)
{
var href = link.Attributes["href"].Value;
// do whatever you want with the link.
}
}

How to continue numbering a list from where it stops?

I'm reading content from some API, and the content may come as either come as "paragraph" or "ordered list".
My list order is always restarting numbering every time it reads a new record.
Example
1.TEST
1.TEST
My goal is to display the content as follows
1.TEST
2.TEST
even after reading different content in between
#foreach (var x in item.copy)
{
if (x.type == "o-list-item")
{
<tr>
<td>
<ol>
<li>
#Html.DisplayFor(modelItem => x.text)
</li>
</ol>
</td>
</tr>
}
else if(x.type== "paragraph")
{
<tr>
<td>
#Html.DisplayFor(modelItem => x.text)
</td>
</tr>
}
}
I understand that if the list sequence is interrupted, then it is a new list sequence, and can’t be a continuation of a previous list.
But, I have to make it, and
I tried to custom code myself, by concatenating an integer count=1 and increment when the for loop reads "o-list-item" type of content, but the DisplayFor razor view seems not allowing to concatenate any custom made variables.
#foreach (var x in item.copy)
{
if (x.type == "o-list-item")
{
int count=1;
<tr>
<td>
<ol>
<li>
count + "."+ #Html.DisplayFor(modelItem => x.text)
count ++;
</li>
</ol>
</td>
</tr>
}
else if(x.type== "paragraph")
{
<tr>
<td>
#Html.DisplayFor(modelItem => x.text)
</td>
</tr>
}
}
Any help please
I don't know a lot of C# and haven't seen this #foreach annotated like this yet. But maybe you could have some method that receives the text, from this method build a string concatenating the counter and the text received. Something like:
public List<String> receivesFromApi() {
return new ArrayList<String>();
}
public String iteratesThroughList() {
int counter = 1;
for(String data : receivesFromApi()){
System.out.println(counter+"."+data);
}
}
You can use Ordered List attribute "start" to specify start number.
#{int count = 1;}
#foreach (var x in item.copy)
{
if (x.type == "o-list-item")
{
<tr>
<td>
<ol start="#count++">
<li>
#Html.DisplayFor(modelItem => x.text)
</li>
</ol>
</td>
</tr>
}
else if(x.type== "paragraph")
{
<tr>
<td>
#Html.DisplayFor(modelItem => x.text)
</td>
</tr>
}
}

How to read values from two separate tags using C#

I have multiple tags, within each there are multiple tags and inside span tag there are bunch of inner tgs, for the reference i have attached the snapshot along with the question:
<div class="questionContainer field-type_single-select " id="abc" qbparent="0" fieldtype="single-select">
<span class="questionLabel">
<table class="guardAgainstInvalidMarkup">
<tbody>
<tr>
<td class="guardAgainstInvalidMarkup">
<span class="EDITPOPformlabel" align="right">
<font class="FONTMedium">test data</font>
</span>
</td>
<td class="helpLinkCell">
<span class="helpLink">
<span class="questionHelpText" />
</span>
</td>
</tr>
</tbody>
</table>
</span>
<span class="questionInput">
<div class="viewResponse">
<table class="guardAgainstInvalidMarkup">
<tbody>
<tr>
<td class="guardAgainstInvalidMarkup">test sample</td>
</tr>
</tbody>
</table>
</div>
</span>
<div class="clearBoth" />
</div>
I need to read value's of following tags
<font class="FONTMedium">test data</font> and
<td class="guardAgainstInvalidMarkup">test sample</td>
and create a map with values of these tags.
what i did is :
i used foreach loop on and obtain tags from them and kept going till i reach the tag from which i need value.
I want to know is there a easy way to accomplish these values.
any help will be much appreciated.
You can get whatever element you want using XPATH expressions.
Try below simple code. It gets the element which has font value "test data".
XmlDocument doc = new XmlDocument();
doc.Load("C:\\Users\\<xxxxx>\\Desktop\\14x\\div.xml");
XmlNode root = doc.DocumentElement;
XmlNode node = root.SelectSingleNode("descendant::span/table/tbody/tr/td/span[font='test data']");
This way you do not need to loop.
For documentation refer below link:
https://learn.microsoft.com/en-us/dotnet/standard/data/xml/select-nodes-using-xpath-navigation
You said "using C#" in your question but I can't see any runat="server" attribute...
So maybe you could achieve this using JavaScript? Something like:
$("span").each(function(){
var value = $(this).text(); // <- This holds every span content
// Do whatever with your span...
})

Select specific html with "Html Agility pack"

I'm using html-agility-pack and trying to select out a specific html in it.
The part I want to get is every GTIN-number in these blocks:
<td><span class="mobile-only">GTIN:</span>07330155011068</td>
-The part I want is the numbers after the ending span-tag. Ex: 07330155011068. Below is my html, and my c#-method:
<div class="table-wrapper" style='display: block;'>
<table id="tableSearchArticle">
<thead>
<tr>
<th>Article</th>
<th>art.nr.</th>
<th>Brand</th>
<th>GTIN</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="http://www.dabas.com/ProductSheet/Detail.ashx/121308" target="_blank">
Dalapannkaka fryst ca100st 6kg
</a>
</td>
<td><span class="mobile-only">Tillverkarens art.nr:</span>11068</td>
<td><span class="mobile-only">Varumärke:</span>test</td>
<td><span class="mobile-only">GTIN:</span>07330155011068</td>
</tr>
<tr>
<td>
<a href="http://www.dabas.com/ProductSheet/Detail.ashx/124494" target="_blank">
Dessertpannkaka fryst ca100st 6kg
</a>
</td>
<td><span class="mobile-only">Tillverkarens art.nr:</span>11405</td>
<td><span class="mobile-only">Varumärke:</span>test</td>
<td><span class="mobile-only">GTIN:</span>07330155114059</td>
</tr>
</tbody>
</table>
</div>
And I'm using this method to trying to get my values. The problem is I don't know what code to write in the SelectNode() to get the innerHtml containing the GTIN-numbers.
public void TestGetHtml()
{
var doc = new HtmlDocument();
doc.Load("C:/Users/Desktop/test.html");
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("TODO: Add code to select all GTIN"))
{
}
doc.Save("file.htm");
}
Use Xpath to select fourth cells from body of table with id tableSearchArticle. Then get inner text of cells (it will be without html tags, like GTIN:07330155114059) and remove GTIN prefix:
var xpath = "//table[#id='tableSearchArticle']/tbody/tr/td[4]";
var gtins = doc.DocumentNode.SelectNodes(xpath)
.Select(td => td.InnerText.Replace("GTIN:", ""));
Output:
[
"07330155011068",
"07330155114059"
]
SelectNodes receives an Xpath expression. So, you could start with this (untested):
foreach (HtmlNode tr in doc.DocumentNode.SelectNodes(
"//div[#class='table-wrapper']/table[#id='tableSearchArticle']/tbody/tr"))
{
Console.WriteLine(tr.InnerHtml);
Console.WriteLine(tr.SelectSingleNode(".//a").GetAttribute("href"));
Console.WriteLine(tr.SelectSingleNode(".//td[last()]").InnerText);
}

Categories