How can i parse document.write/response.write to use single quotes instead of double quotes for AngleSharp? - anglesharp

I'm working with old html(ASP) files and i need to convert/parse them to work with new browsers.
I'm using AngleSharp, my problem is when it tries to parse response and document.write that uses single quotes for it's values and AngleSharp parse it to double quotes.
Input
Response.Write ("<input type=text name=attrname value='" + sVar + "'>");
Output (AngleSharp)
Response.Write ("<input type="text" name="attrname" value="" + sVar + "">");
Output expected
Response.Write ("<input type='text' name='attrname' value='" + sVar + "'>");
Is there a way to skip parsing or set a different formating for both? Thank you in advance!

The serialization is done by an IMarkupFormatter. By default, this formatter uses double quotes for the attributes (as the formatter does not know that you are inside some ASP code where you use double quotes on the outside).
Easiest way would be to roll your own formatter (example):
class MyMarkupFormatter : HtmlMarkupFormatter
{
protected override string Attribute(IAttr attr)
{
return $"{attr.Name}='{attr.Value}'";
}
}
You could use it like this:
var config = Configuration.Default;
var context = BrowsingContext.New(config);
var input = "<input type=text name=attrname value='\" + sVar + \"'>";
var document = await context.OpenNewAsync();
var formatter = new MyMarkupFormatter();
document.Body.InnerHtml = input;
document.Body.FirstChild.ToHtml(formatter).Dump(); // <input type='text' name='attrname' value='" + sVar + "'>
Note that the implementation of Attribute is only so simple for illustration purposes. You should handle more cases (and potentially take care of transforming contained single quotes etc.).

Related

Posting a collection - is empty/null when adding a class on the table row

I have a simple ASP.NET MVC application, where our users have a table which has some options to edit some settings.
This table is build dynamically using jQuery since this is some legacy code. The code to make the table is:
function setInvoiceTable(result) {
result.OverduesPaged.forEach(function (item, index) {
var externalName = 'OverduesPaged[' + index + '].ExternalInvoiceGuid';
var debtorName = 'OverduesPaged[' + index + '].Debtor';
var visibleName = 'OverduesPaged[' + index + '].IsSelected';
var externalInvoiceGuidField = '<input type=\'hidden\' value=\'' + item.ExternalInvoiceGuid + '\' name=\'' + externalName+ '\' />';
var debtorField = '<input type=\'hidden\' value=\'' + item.Debtor + '\' name=\'' + debtorName + '\' />';
var invisibleField = '<input type=\'hidden\' value=\'false\' name=\'' + visibleName + '\' id=\'' + visibleName + '\' /></label>';
var visibleField = '<label><input type=\'checkbox\' value=\'true\' name=\'' + visibleName + '\' id=\'' + visibleName + '\' /> Start sag';
var insertStr = "<tr>" +
"<td>" + externalInvoiceGuidField + debtorField + visibleField + invisibleField + "</td>" +
"<td>" + item.InvoiceId + "</td>" +
"<td>" + item.Debtor + "</td>" +
"<td>" + item.DateString +"</td>" +
"<td>" + item.DaysSinceDueString +"</td>" +
"<td>" + item.GrossAmountString + "</td>" +
"<td>" + item.RemainderAmountString + "</td>" +
"</tr>";
$('#accounting_invoices_table').append(insertStr);
});
}
When I POST, this works perfectly for us. We have an endpoint in our controller which has this signature:
[System.Web.Mvc.HttpPost]
public ActionResult StartDebtCollectionCases(UpcomingDashboardViewModel vm)
{
// code
}
The collection I'm building is the OverduesPaged which is a part of our view model:
public class UpcomingDashboardViewModel
{
public List<OverdueUpcomingInvoiceViewModel> OverduesPaged { get; set; }
// more stuff not relevant to question
}
This is my challenge:
I've added a css class to the <tr> row like this:
// new code added
var removeClass = 'ok';
if (item.IsAlreadyCase) {
visibleField = '<label type="text">Allerede startet</label>';
removeClass = 'remove';
} else if (item.IsBlocked) {
visibleField = '<label type="text">Sat i bero</label>';
removeClass = 'remove';
}
else if (item.Currency != "DKK") {
visibleField = '<label type="text">Faktura skal være dansk valuta</label>';
removeClass = 'remove';
}
var insertStr = "<tr class='" + removeClass + "'>" +
"<td>" + externalInvoiceGuidField + debtorField + visibleField + invisibleField + "</td>" +
// rest of code from above
Now I end up with a table exactly like before, but with a class which is either OK or REMOVE.
However, when I now do the POST, the whole collection, OverduesPaged, is null/empty:
I tried to add the class to the <td> instead, but then the collection was null/empty.
Any ideas what is wrong here?
The issue is not related to adding the class name itself, but rather the invalid html that you generating if ant of the code in the if or else if blocks are executed. In those blocks you are creating <label> element with a closing tag, but no input (its not clear if you need the checkbox or not in those cases), so when you combine visibleField + invisibleField you get unbalanced <label> tags (visibleField has opening and closing tags, but invisibleField only has a closing </label> tag.
You code in the if blocks to generate visibleField would need to be similar to what you generate in the original code - i.e. just an opening <label> with the html for the checkbox.
As you have acknowledged in the comments, this is very fragile and error prone code that is difficult to debug. As you are intending to rewrite it, consider returning a partial view in your ajax call (that is strongly bound to the model), or if you need to return Json, then consider a hidden template (outside the <form> tags) that you clone and update in the script, for example
<div id="newrow" style="display:none">
<tr>
<td>
<input class="invoice" type="hidden" name="OverduesPaged[#].ExternalInvoiceGuid value />
<input class="debtor" type="hidden" name="OverduesPaged[#].Debtor value />
....
</td>
....
</tr>
</div>
and then you script becomes
var table = $('#accounting_invoices_table');
result.OverduesPaged.forEach(function (item, index) {
var clone = $('#newrow').clone();
// Update indexer
clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
// Update values
clone.find('.invoice').val(item.ExternalInvoiceGuid);
....
table.append(clone.html());
});
As a side note, your existing id attributes are invalid because they contain ., [ and ] characters (if you attempted to use these in jQuery selectors, they would fail (for example the . will be interpreted as a class name), so they should be omitted in the html

Convert underscores to hyphens in angular variable

I have data icons whose classes are formatted by vehicle type and then sub-type, like so:
.di-icon-type-car-full-size-car
.di-icon-type-car-mid-size-car
.di-icon-type-van-large-van
.di-icon-type-van-minivan
In my view I am trying to dynamically set the class based on the current vehicle's information:
span(ng-class="'di-icon-type-' + vehicle.type + '-' + vehicle.sub_type")
The problem is, my vehicle.sub_type variable is formatted with underscores, not dashes. So the class appears as di-icon-type-car-full_size_car instead of di-icon-type-car-full-size-car, for example. Is there a way I can convert all underscores in my vehicle.sub_type variable to hyphens before using it?
I would suggest to move a string concatenation and dash normalization into a function in a controller like this:
$scope.getIconClass = function(vehicle) {
var className = 'di-icon-type-' + vehicle.type + '-' + vehicle.sub_type;
return className.replace(/_/g, '-');
};
Then use it like this in the template:
<span ng-class="getIconClass(vehicle)"></span>
Alternatively, you could write a custom filter to do the job:
.filter('kebabcase', function() {
return function (value) {
return value && value.replace(/_/g, '-');
};
});
Then use it like this:
<span ng-class="'di-icon-type-' + vehicle.type + '-' + vehicle.sub_type | kebabcase"></span>
Example Plunker: http://plnkr.co/edit/dRj6Sf3NeUq8IxnBshyE?p=preview
span(ng-class="'di-icon-type-' + vehicle.type.replace(/_/g, "-") + '-' + vehicle.sub_type")
should work for you

Display Pound currency sign (£) in a DataBound DropDownListItem

I need to show items like in below image.
I'm using this code to bind dropdownlist.
var options = (from option in _serviceOptions
select new
{
OptionId = option.OptionId,
OptionText = option.OptionText + " - " + option.Price + "£/month"
}).ToList();
myDdl.DataSource = options;
myDdl.DataValueField = "OptionId";
myDdl.DataTextField = "OptionText";
myDdl.DataBind();
_serviceOptions is the resultset returned by calling stored procedure using L2S
The problem is, it is again encoding the & to & before rendering to the browser.
Use the pound sign £ instead of £. It works here. The £ will be converted to £ which is equal to £.
var options = (from option in _serviceOptions
select new
{
OptionId = option.OptionId,
OptionText = option.OptionText + " - " + option.Price + "£/month"
}).ToList();

How correctly assign value to field

I am trying to assign value for one edit field(not asp.net control) in asp.net application using JavaScript code. It seems that < character in value string gives problems for ASP.NET. If I remove < and > characters from value everything works fine.
Where is the problem? How to pass <> characters to the field? I don't want to use ServerSide code I want to do it on ClientSide using JS and HTML Edit box.
function loadShareBox(pageTitle) {
document.getElementById("shareHTML").value = '<a href="' + document.location.href + '" target=_blank>' + pageTitle + '</a>';
}
regards,
Tomas
try using these
< corresponds <
> corresponds >
the code would look like this
function loadShareBox(pageTitle) {
document.getElementById("shareHTML").value = '<a href="' + document.location.href + '" target=_blank>' + pageTitle + '</a>';
}
edit: ah, I think there is another problem. You are trying to insert a new element within another element. So you should create a new element and append in shareHTML.
var myLink = document.createElement("a");
myLink.setAttribute("href", "mylink");
var text = document.createTextNode("Link name");
myLink.appendChild(text);
var myElement = document.getElementById("shareHTML")
myElement.appendChild(myLink);
this should do the work

Formatting JSON in ASP.NET HttpResponse

I'm sending back a bunch of image tags via JSON in my .ashx response.
I am not sure how to format this so that the string comes back with real tags. I tried to HtmlEncode and that sort of fixed it but then I ended up with this stupid \u003c crap:
["\u003cimg src=\"http://www.sss.com/image/65.jpg\" alt=\"\"\u003e\u003c/li\u003e","\u003cimg src=\"http://www.xxx.com/image/61.jpg\" alt=\"\"\u003e\u003c/li\u003e"]
What the heck is \u003c ?
here's my code that created the JSON for response to my .ashx:
private void GetProductsJSON(HttpContext context)
{
context.Response.ContentType = "text/plain";
int i = 1;
...do some more stuff
foreach(Product p in products)
{
string imageTag = string.Format(#"<img src=""{0}"" alt=""""></li>", WebUtil.ImageUrl(p.Image, false));
images.Add(imageTag);
i++;
}
string jsonString = images.ToJSON();
context.Response.Write(HttpUtility.HtmlEncode(jsonString));
}
the toJSON is simply using the helper method outlined here:
http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx
\u003c is an escaped less-than character in unicode (Unicode character 0x003C).
The AJAX response is fine. When that string is written to the DOM, it will show up as a normal "<" character.
You are returning JSON array. Once parsed using eval("("+returnValue+")") it is in readily usable condition.
EDIT: This code is from jquery.json.js file:
var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
var meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
$.quoteString = function(string)
// Places quotes around a string, inteligently.
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
{
if (escapeable.test(string))
{
return '"' + string.replace(escapeable, function (a)
{
var c = meta[a];
if (typeof c === 'string') {
return c;
}
c = a.charCodeAt();
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
}) + '"';
}
return '"' + string + '"';
};
Hope this gives you some direction to go ahead.
all you need to do is to use javascript eval function to get a pure HTML (XML) markup on the front end.
i.e. in a ajax call to a webservice, this can be the success handler of tha call,
the service returns a complex html element:
...
success: function(msg) {$(divToBeWorkedOn).html(**eval(**msg**)**);alert(eval(msg));},
...

Resources