ASP.net MVC, custom section html helper, opening/closing divs mismatch - c#

I have this helper:
public class PanelSection : IDisposable
{
protected HtmlHelper _helper;
private string f;
public PanelSection(HtmlHelper helper, string title, string subTitle, bool footer)
{
_helper = helper;
f = footer ? "" : "</div>"; //If footer is true, we end body ourselves, if footer is false, we end both - body and panel automatically
_helper.ViewContext.Writer.Write(
"<div class='panel panel-default'><div class='panel-heading'><h2>" + title + "</h2></div><div class='panel-body'>"
);
if (!string.IsNullOrEmpty(subTitle))
_helper.ViewContext.Writer.Write(
"<h4>" + subTitle + "</h4><hr/>"
);
}
public void Dispose()
{
_helper.ViewContext.Writer.Write("</div>" + f);
}
}
If footer is set to True, that means I will end panel-body myself, so on dispose it writes one less div. This should let me have panel-footer when I need it, or have table outside of body. But on when I do this I get
Parser Error Message: Encountered end tag "div" with no matching start tag.
My razor code looks like this:
using (Html.BeginPanel(#Resources.Contract, #Resources.CreateNew, true))
{ //starts panel, starts panel body
<b>Body content</b>
</div> //end of body
<div class="panel-footer">
#Resources.Back
</div>
} //end of panel
Obvious solution would be to simply not open panel body on that helper, and for panel body use different helper. But I'm still interested why it gives me that error. It should generate good html without any errors, but it looks like it process everything before changing helper into html, sees an extra div and throws parse error. Why is that? Is there any way to make this work?

Unbalanced razor tags can be output using the #: syntax.
Providing everything else compiles you can output the razor as follows:
using (Html.BeginPanel(#Resources.Contract, #Resources.CreateNew, true))
{
//starts panel, starts panel body
<b>Body content</b>
#:</div> //end of body
<div class="panel-footer">
#Resources.Back
</div>
} //end of panel
Note the #:</div>.

Related

ASP.NET MVC razor code and javascript errors

I have this code
#if (Model.Name!= null)
{
<div>#Model.Name, <span>#Model.Email</span></div>
}
and I want to highlight the postal code if this condition - IsFlaggedEmail is true:
if (Model.IsFlaggedEmail(out flagComments))
{
<span id="flagged" style="background-color:yellow;font-size:10pt">
}
and I want to display the comments in the title of the span (a tool tip). How can I write this in the cshtml file?
This is what I tried, but I keep getting errors like: "The if 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."
#if (Model.Name!= null)
{
<div>#Model.Name, #{
string flagComments;
if (Model.IsFlaggedEmail(out flagComments))
{
<span id="flagged" style="background-color:yellow;font-size:10pt">
}
} #Model.Email</span></div>
}
#{ string comments;
if (Model.IsFlaggedEmail(out comments)) {
#section Scripts {
$("#flagged").val('title', comments)
}
}}
Also, can I do something like that directly from jQuery?:
#if (Model.Name!= null)
{
<div>#Model.Name, <span id="flagged">#Model.Email</span></div>
}
#{ string flagComments;
if (Model.IsFlaggedEmail(out flagComments)) {
#section Scripts {
$('#flagged').css('background-collor', 'yellow')
$('#flagged').attr('title', #flagComments);​
}
}}
No javascript needed.
You can use something like:
#if (Model.Name != null)
{
string flagComments;
bool isFlagged = Model.IsFlaggedEmail(out flagComments);
<div>
#Model.Name, <span id="#Html.Raw(isFlagged? "flagged": "")">#Model.Email</span>
</div>
And for styling it is better to use CSS. (You have an ID flagged).
Also try to avoid spreading html building across if statements. It is always better to keep tags matching inside one clause.

Dynamically Embed Html Attribute in C# ASP.NET View

I'm trying to dynamically set an attribute(data-status) for a div if a condition is met.
I am currently using the #Html.Raw helper however it's not making its way in to the element.
I have also attempted to use Response.Write() however it just writes everything to the top of the page.
Is there a best way to actually embed this in to the code or maybe create/set a new attribute?
#foreach (var r in Model)
{
<div class="marker"
data-date="#r.date_finished"
data-name="#r.name"
#if (r.complete == "CP")
{
#Html.Raw("data-status='complete'");
}
>
</div>
}
This should do it:
<div class="marker"
data-date="#r.date_finished"
data-name="#r.name"
#{if (r.complete == "CP") { <text>data-status='complete'</text> }}>
Notice the usage of <text> tag. This is a special tag which Razor uses to output content as is.
When I run into this scenario I use a tertiary expression:
<div #(r.complete == "CP" ? "data-status='complete'" : "") >
If your logic is more complex you could also use a static helper method.
<div #r.RenderComplete() >
public static class RExtension{
public static string RenderComplete( this R r){
// logic here
}
}

Selenium WebDriver and C# (VS): Look for a specific header string

I've been trying, without luck, to use IJavaScriptExecutor to find a specific header string in a page. Here's the html code form the page:
<div class="wrap">
<h2>Edit Page <a href="http://www.webtest.bugrit.net/wordpress/wp-admin/post-
new.php?post_type=page" class="add-new-h2">Add New</a></h2>
<div id...
The text I need to check for is the "Edit Page" string.
This is the closest I've come, which isn't very close:
var element = FFDriver.Instance.FindElements(By.ClassName("add-new-h2"));
IJavaScriptExecutor js = FFDriver.Instance as IJavaScriptExecutor;
if (js != null) {
string innerHtml = (string)js.ExecuteScript("return arguments[0].innerHTML;", element);
//System.Windows.Forms.MessageBox.Show(innerHtml);
if (innerHtml.Equals("Edit Page")) {
return true;
} else {
return false;
}
}
Now, I realize that the text I should expect to get from that code isn't the exact string "Edit Page". But shouldn't it return something? When I enable the MessageBox line, the innerHtml string is empty.
Or, of couse - if someone knows another, possible easier, way to check for the existance of a specific string inside a specific html tag, I'm all ears.
Your element returns you <a> element, not <h2>. Your <a> doesn't contain Edit Page string.
Try find your element like this to the parent element <h2> (only if class name add-new-h2 is unique, otherwise you will get the first matching one):
var element = FFDriver.Instance.FindElement(By.XPath(".//a[#class='add-new-h2']/.."));
var containsText = element.Text.Contains("Edit Page");

How to use Html Agility Pack for HTML validations

I am using HTML Agility Pack for validating my html. Below is what I am using,
public class MarkupErrors
{
public string ErrorCode { get; set; }
public string ErrorReason { get; set; }
}
public static List<MarkupErrors> IsMarkupValid(string html)
{
var document = new HtmlAgilityPack.HtmlDocument();
document.OptionFixNestedTags = true;
document.LoadHtml(html);
var parserErrors = new List<MarkupErrors>();
foreach(var error in document.ParseErrors)
{
parserErrors.Add(new MarkupErrors
{
ErrorCode = error.Code.ToString(),
ErrorReason = error.Reason
});
}
return parserErrors;
}
So say my input is something like the one shown below :
<h1>Test</h1>
Hello World</h2>
<h3>Missing close h3 tag
So my current function return a list of following errors
- Start tag <h2> was not found
- End tag </h3> was not found
which is fine...
My problem is that I want the entire html to be valid, that is with a proper <head> and <body> tags, because this html will later be available for preview, download as .html files.
So I was wondering if I could check for this using HTML Agility Pack ?
Any ideas or other options will be appreciated. Thanks
You can check there is a HEAD element or a BODY element under an HTML element like this for example:
bool hasHead = doc.DocumentNode.SelectSingleNode("html/head") != null;
bool hasBody = doc.DocumentNode.SelectSingleNode("html/body") != null;
These would fail if there is no HTML element, or if there is no BODY element under the HTML element.
Note I don't use this kind of XPATH expression "//head" because it would give a result even if the head was not directly under the HTML element.

Input string was not in a correct format when trying to add jQuery in code behind

I try this and it gives the error mentioned in the title at the line I call String.Format.
public static void JqueryDialogue(string divId)
{
String script = String.Format(
"$(document).ready(function(){ $('#{0}').dialog('open'); });",
divId);
// Gets the executing web page
Page page = HttpContext.Current.CurrentHandler as Page;
string codeId = "openDialoge" + divId.ToString();
// Checks if the handler is a Page and that the script isn't already on Page
if (page != null && !page.ClientScript.IsClientScriptBlockRegistered(codeId))
{
page.ClientScript.RegisterStartupScript(
typeof(JavascriptHelper),
codeId,
script,
true);
}
}
If you use String.Format you'll need to escape the { and } characters that you want to be outputted literally since they are Javascript code. To achieve this you use {{ and }} respectively.
You can read more about string formatting here where an odd behavior resulting from escaping curly braces is also explained.
I think you will need to escape the { after function declaration something like
String script = String.Format("$(document).ready(function()
{{ $('#{0}').dialog('open'); }});", divId);

Categories

Resources