I am really new to using HTMLAgilityPack. I have the following HTML document :
<a href="https://twitter.com/RedGiantNews" target="_blank"><img
src="http://image.e.redgiant.com/lib/998.png" width="24" border="0"
alt="Twitter" title="Twitter" class="smImage"></a><a
href="https://www.facebook.com/RedGiantSoftware" target="_blank"><img
src="http://image.e.redgiant.com/lib/db5.png" width="24" border="0"
alt="Facebook" title="Facebook" class="smImage"></a>
http://click.e.redgiant.com/?qs=d2ad061f
<a href="https://www.instagram.com/redgiantnews/" target="_blank"><img
src="http://image.e.redgiant.com/aa10-f8747e56f06d.png" width="24"
border="0" alt="Instagram" title="Instagram" class="smImage"></a>
I am trying to remove all images, i mean all nodes(if this is the right word) of <img....> from the html file. I tried the below code from another solution on StackOverflow but in vain as it returns the same HTMl as above :
var sb = new StringBuilder();
doc.LoadHtml(inputHTml);
foreach (var node in doc.DocumentNode.ChildNodes)
{
if (node.Name != "img" && node.Name!="a")
{
sb.Append(node.InnerHtml);
}
}
static string OutputHtml = #"<a href=""https://twitter.com/RedGiantNews"" target=""_blank""><img
src=""http://image.e.redgiant.com/lib/998.png"" width=""24"" border=""0""
alt=""Twitter"" title=""Twitter"" class=""smImage""></a><a
href = ""https://www.facebook.com/RedGiantSoftware"" target=""_blank""><img
src = ""http://image.e.redgiant.com/lib/db5.png"" width=""24"" border=""0""
alt=""Facebook"" title=""Facebook"" class=""smImage""></a>
<a href = ""https://www.instagram.com/redgiantnews/"" target=""_blank""><img
src = ""http://image.e.redgiant.com/aa10-f8747e56f06d.png"" width=""24""
border=""0"" alt=""Instagram"" title=""Instagram"" class=""smImage""></a>";
I removed the floating link (http://click.e.redgiant.com/?qs=d2ad061f) from the original html string.
Approach One:
public static string RemoveAllImageNodes(string html)
{
try
{
HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
document.LoadHtml(html);
var nodes = document.DocumentNode.SelectNodes("//img");
foreach (var node in nodes)
{
node.Remove();
//node.Attributes.Remove("src"); //This only removes the src Attribute from <img> tag
}
html = document.DocumentNode.OuterHtml;
return html;
}
catch (Exception ex)
{
throw ex;
}
}
Approach Two:
public static string RemoveAllImageNodes(string html)
{
try
{
HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
document.LoadHtml(html);
if (document.DocumentNode.InnerHtml.Contains("<img"))
{
foreach (var eachNode in document.DocumentNode.SelectNodes("//img"))
{
eachNode.Remove();
//eachNode.Attributes.Remove("src"); //This only removes the src Attribute from <img> tag
}
}
html = document.DocumentNode.OuterHtml;
return html;
}
catch (Exception ex)
{
throw ex;
}
}
OutPut Html:
Output Html - After removing only the "src" attributes from "img" tag(s):
<img width="24" border="0" alt="Twitter" title="Twitter" class="smImage">
<img width="24" border="0" alt="Facebook" title="Facebook" class="smImage">
<img width="24" border="0" alt="Instagram" title="Instagram" class="smImage">
This is my ASP.NET form. I want to add invisible recaptcha to it with server side validation. Can someone please help?
I can do client side validation but it doesnt use secret key. My another questions is Do we need secret key for invisible recaptcha?
Please see serverside code that i used for google recaptcha but it is not working for Invisible recaptcha. I am getting this error : -
reCAPTCHA Error: missing-input-response: Not Valid Recaptcha
<div id="ContactFormDiv" runat="server">
<div class="form-row form-required">
<asp:Label ID="YourNameLabel" runat="server" AssociatedControlID="YourNameTextBox"> Your Name:</asp:Label>
<asp:TextBox ID="YourNameTextBox" runat="server" CssClass="form300" MaxLength="150"></asp:TextBox>
</div>
<div class="form-row form-required">
<div id='recaptcha' class="g-recaptcha"
data-sitekey="site key"
data-callback="onSubmit"
data-size="invisible">
</div>
</div>
<div class="form-row-buttons">
<asp:Button ID="SendMessageButton" ClientIDMode="Static" runat="server" Text="Send Message" CssClass="buttonPositive"
CausesValidation="True" OnClick="SendMessageButton_Click" />
</div>
</div>
Javascript Code
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js" async defer></script>
Serverside Code
public class MyObject
{
public string success { get; set; }
}
public static string ReCaptcha_Key = "------------------Site Key-----------------";
public static string ReCaptcha_Secret = "--------------Secret Key ---------------";
public bool ValidateReCaptcha()
{
bool Valid = false;
//start building recaptch api call
var sb = new StringBuilder();
//Getting Response String Append to Post Method
string Response = Request["g-recaptcha-response"];
string url = "https://www.google.com/recaptcha/api/siteverify?secret=" + ReCaptcha_Secret + "&response=" + Response;
sb.Append(url);
//make the api call and determine validity
using (var client = new WebClient())
{
var uri = sb.ToString();
var json = client.DownloadString(uri);
var serializer = new DataContractJsonSerializer(typeof(RecaptchaApiResponse));
var ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
var result = serializer.ReadObject(ms) as RecaptchaApiResponse;
//--- Check if we are able to call api or not.
if (result == null)
{
lblmsg.Text = "Captcha was unable to make the api call";
}
else // If Yes
{
//api call contains errors
if (result.ErrorCodes != null)
{
if (result.ErrorCodes.Count > 0)
{
foreach (var error in result.ErrorCodes)
{
lblmsg.Text = "reCAPTCHA Error: " + error;
}
}
}
else //api does not contain errors
{
if (!result.Success) //captcha was unsuccessful for some reason
{
lblmsg.Text = "Captcha did not pass, please try again.";
}
else //---- If successfully verified. Do your rest of logic.
{
lblmsg.Text = "Captcha cleared ";
Valid = true;
}
}
}
}
return Valid;
}
public bool temp = true;
protected void SendMessageButton_Click(object sender, EventArgs e)
{
temp = ValidateReCaptcha();
if (temp == false)
{
lblmsg.Text = "Not Valid Recaptcha";
lblmsg.ForeColor = System.Drawing.Color.Red;
}
else
{
lblmsg.Text = "Successful";
lblmsg.ForeColor = System.Drawing.Color.Green;
}
Page.Validate();
if (this.Page.IsValid == true && temp == true)
{ //Page and invisible recaptcha is valid }
}
I am getting this error : -
reCAPTCHA Error: missing-input-response: Not Valid Recaptcha
This is how I implemented the working sample:
-- Client Side (Refer to Google Documentation )
<head>
<!-- Google Invisible Captcha -->
<script src='https://www.google.com/recaptcha/api.js'/>
<script>
function onSubmit(token) {
document.getElementById("htmlForm").submit();
}
</script>
</head>
<body>
<form id="htmlForm" action="Default.aspx" method="post">
<input name="txtName" />
<input name="txtEmailAddress" />
<button class="g-recaptcha btn btn-default"
data-sitekey="-------------------Site key--------------"
data-callback="onSubmit">
Submit Request
</button>
</form>
</body>
-- Server Side (keeps secret Key)
public static bool IsValidCaptcha()
{
var secret = "--------------Secret Key ---------------";
var req =
(HttpWebRequest)
WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=" + secret + "&response=" + HttpContext.Current.Request.Form["g-recaptcha-response"]);
using (var wResponse = req.GetResponse())
{
using (StreamReader readStream = new StreamReader(wResponse.GetResponseStream()))
{
string responseFromServer = readStream.ReadToEnd();
if (!responseFromServer.Contains("\"success\": false"))
return true;
}
}
return false;
}
I also have similar problem and it looks like it is harder to find any decent example. However, I saw that you have set
data-callback="onSubmit"
but I didn't see where you have defined that method. Is it there? Could that be what are you missing?
Having trouble understanding this error below in vs.net.
I'm trying to grab a logged in user account on the domain and allow them to be able to edit their phone number.
Another guy setup the AD Access, but I can't event get a logged in user name.
Pasted the code VS.NET errors on every time with the exception that I found in an online article and worked for everyone else except me.
I've verified it works using powershell but I could use some help.
THANKS!!!
//parse the current user's logon name as search key
string sFilter = String.Format(
"(&(objectClass=user)(objectCategory=person)(sAMAccountName={0}))",
User.Identity.Name.Split(new char[] { '\\' })[1]
);
Exception User-Unhandled
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
<%# Import Namespace="System.DirectoryServices.ActiveDirectory" %>
<%# Import Namespace="System.DirectoryServices.AccountManagement" %>
<!DOCTYPE html>
<head>
<script language="c#" runat="server">
static string adsPath = "LDAP://dc=DOMAIN,dc=com";
private void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
{
SearchResult sr = FindCurrentUser(new string[] { "allowedAttributesEffective" });
if (sr == null)
{
msg.Text = "User not found...";
return;
}
int count = sr.Properties["allowedAttributesEffective"].Count;
if (count > 0)
{
int i = 0;
string[] effectiveAttributes = new string[count];
foreach (string attrib in sr.Properties["allowedAttributesEffective"])
{
effectiveAttributes[i++] = attrib;
}
sr = FindCurrentUser(effectiveAttributes);
foreach (string key in effectiveAttributes)
{
string val = String.Empty;
if (sr.Properties.Contains(key))
{
val = sr.Properties[key][0].ToString();
}
GenerateControls(key, val, parent);
}
}
}
else
{
UpdateControls();
}
}
private SearchResult FindCurrentUser(string[] attribsToLoad)
{
//parse the current user's logon name as search key
string sFilter = String.Format(
"(&(objectClass=user)(objectCategory=person)(sAMAccountName={0}))",
User.Identity.Name.Split(new char[] { '\\' })[1]
);
DirectoryEntry searchRoot = new DirectoryEntry(
adsPath,
null,
null,
AuthenticationTypes.Secure
);
using (searchRoot)
{
DirectorySearcher ds = new DirectorySearcher(
searchRoot,
sFilter,
attribsToLoad,
SearchScope.Subtree
);
ds.SizeLimit = 1;
return ds.FindOne();
}
}
private void GenerateControls(string attrib, string val, Control parent)
{
parent.Controls.Add(new LiteralControl("<div>"));
TextBox t = new TextBox();
t.ID = "c_" + attrib;
t.Text = val;
t.CssClass = "txt";
Label l = new Label();
l.Text = attrib;
l.AssociatedControlID = t.ID;
l.CssClass = "lbl";
parent.Controls.Add(l);
parent.Controls.Add(t);
parent.Controls.Add(new LiteralControl("</div>"));
}
private void UpdateControls()
{
SearchResult sr = FindCurrentUser(new string[] { "cn" });
if (sr != null)
{
using (DirectoryEntry user = sr.GetDirectoryEntry())
{
foreach (string key in Request.Form.AllKeys)
{
if (key.StartsWith("c_"))
{
string attrib = key.Split(new char[] { '_' })[1];
string val = Request.Form[key];
if (!String.IsNullOrEmpty(val))
{
Response.Output.Write("Updating {0} to {1}<br>", attrib, val);
user.Properties[attrib].Value = val;
}
}
}
user.CommitChanges();
}
}
btnSubmit.Visible = false;
Response.Output.Write("<br><br>< Back", Request.Url);
}
</script>
<style>
.lbl
{
margin-left: 25px;
clear: left;
width: 250px;
}
.txt
{
width: 250px;
}
</style>
</head>
<body>
<form id="main" runat="server">
Data for user:
<%=User.Identity.Name%>
<br>
<br>
<asp:Label ID="msg" runat="server" />
<asp:Panel ID="parent" runat="server" />
<asp:Button ID="btnSubmit" runat="server" Text="Update" />
</form>
</body>
</html>
I have a problem as I am new in html agility pack. What I'm looking for is function from the page. The code below. I want to just take out a function named getDirections then replace start koniec and then repaste it into webpage again, then display it in my app. One question again, is there need to create two html files? Firt static, which never changes, just to load code, and second to display it? As I have to always replace start koniec? Thanks for help and advice!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Find directions</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script type="text/javascript">
var map = null;
var end;
var start;
function getMap()
{
map = new Microsoft.Maps.Map(document.getElementById('myMap'), {credentials: ''});
alert('');
getDirections();
}
function getDirections()
{
start= 'start'; end= 'koniec';
map.getCredentials(callRouteService);
}
function callRouteService(credentials)
{
var routeRequest = 'http://dev.virtualearth.net/REST/v1/Routes?wp.0=' + start + '&wp.1=' + end + '&routePathOutput=Points&output=json&jsonp=routeCallback&key=' + credentials;
var mapscript = document.createElement('script');
mapscript.type = 'text/javascript';
mapscript.src = routeRequest;
document.getElementById('myMap').appendChild(mapscript);
}
function routeCallback(result)
{
var output = document.getElementById("output");
if (output)
{
while (output.hasChildNodes()) {
output.removeChild(output.lastChild);
}
var resultsHeader = document.createElement("h5");
var resultsList = document.createElement("ol");
output.appendChild(resultsHeader);
output.appendChild(resultsList);
}
if (result && result.resourceSets && result.resourceSets.length > 0 && result.resourceSets[0].resources && result.resourceSets[0].resources.length > 0)
{
//resultsHeader.innerHTML = "Bing Maps REST Route API <br/> Route from " + result.resourceSets[0].resources[0].routeLegs[0].startLocation.name + " to " + result.resourceSets[0].resources[0].routeLegs[0].endLocation.name;
var resultsListItem = null;
//for (var i = 0; i < result.resourceSets[0].resources[0].routeLegs[0].itineraryItems.length; ++i)
//{
//resultsListItem = document.createElement("li");
//resultsList.appendChild(resultsListItem);
//resultStr = result.resourceSets[0].resources[0].routeLegs[0].itineraryItems[i].instruction.text;
//resultsListItem.innerHTML = resultStr;
//}
var bbox = result.resourceSets[0].resources[0].bbox;
var viewBoundaries = Microsoft.Maps.LocationRect.fromLocations(new Microsoft.Maps.Location(bbox[0], bbox[1]), new Microsoft.Maps.Location(bbox[2], bbox[3]));
map.setView({ bounds: viewBoundaries});
var routeline = result.resourceSets[0].resources[0].routePath.line; var routepoints = new Array();
for (var i = 0; i < routeline.coordinates.length; i++)
{
routepoints[i]=new Microsoft.Maps.Location(routeline.coordinates[i][0], routeline.coordinates[i][1]);
}
var routeshape = new Microsoft.Maps.Polyline(routepoints, {strokeColor:new Microsoft.Maps.Color(200,0,0,200)});
var startPushpinOptions = {anchor: new Microsoft.Maps.Point(10, 32) };
var startPin= new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(routeline.coordinates[0][0], routeline.coordinates[0][1]), startPushpinOptions);
var endPushpinOptions = {anchor: new Microsoft.Maps.Point(10, 32)};
var endPin= new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(routeline.coordinates[routeline.coordinates.length-1][0], routeline.coordinates[routeline.coordinates.length-1][1]), endPushpinOptions);
map.entities.push(startPin);
map.entities.push(endPin);
map.entities.push(routeshape);
}
else
{
if (typeof(result.errorDetails) != 'undefined')
{
resultsHeader.innerHTML = result.errorDetails[0];
}
alert("No Route found");
}
}
</script>
</head>
<body onload="getMap();">
<div id='myMap' style="position:relative; width:400px; height:400px;"></div>
<div id="output"></div>
</body>
</html>
I have the following code in my MasterPageBase.cs file:
protected override void OnLoad(EventArgs e)
{
string url = Request.Path;
var page = _ContentPageRepository.GetContentPageByUrl(url, ConfigurationManager.GetSiteID());
if (page != null)
{
PageBase.SetTitle(page.Title);
PageBase.SetDescription(page.Description);
PageBase.SetKeywords(page.Keywords);
}
else
{
this.ProcessSiteMap();
}
this.AddGACode();
base.OnLoad(e);
}
I need this.AddGACode(); to get added to the head section of the page, but when I view the source of the page as I am running the solution, I see that this is adding it to the body section of the page.
I have tried Page.Header.Controls.Add(AddGACode()); and get the following errors:
The best overloaded method match has some invalid arguments and cannot convert from 'void' to 'System.Web.UI.Control'
What can I do to get this code added to the head? TIA
EDIT: Request to see the AddGACode method:
private void AddGACode()
{
var gaCode = SiteManager.GetSite().GoogleAnalyticsCode;
if (!String.IsNullOrEmpty(gaCode) && Response.StatusCode == 200)
{
if (!ConfigurationManager.EnableUniversalGATracking)
{
ClientScriptManager cs = Page.ClientScript;
StringBuilder csText = new StringBuilder();
csText.Append("<script type=\"text/javascript\">");
csText.Append(String.Format("var _gaq = _gaq || []; _gaq.push(['_setAccount', '{0}']); ", gaCode));
csText.Append("_gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();");
csText.Append("</script>");
cs.RegisterClientScriptBlock(GetType(), "GACode", csText.ToString());
}
else
{
ClientScriptManager cs = Page.ClientScript;
StringBuilder csText = new StringBuilder();
csText.Append("<!-- Universal GA Code --><script type=\"text/javascript\">");
csText.Append(String.Concat("(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '", gaCode, " ', 'auto'); ga('send', 'pageview');"));
csText.Append("</script>");
cs.RegisterClientScriptBlock(GetType(), "GACode", csText.ToString());
}
}
}
EDIT:
This code is in the AddGACode method. There is still this.AddGACode(); in the OnLoad of the page that seems to duplicate the code with this edit, but both codes will disappear if I delete this.AddGACode(); from OnLoad
ClientScriptManager cs = Page.ClientScript;
StringBuilder csText = new StringBuilder();
csText.Append("<!-- Universal GA Code --><script type=\"text/javascript\">");
csText.Append(String.Concat("(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '", gaCode, " ', 'auto'); ga('send', 'pageview');"));
csText.Append("</script>");
cs.RegisterClientScriptBlock(GetType(), "GACode", csText.ToString());
LiteralControl lc = new LiteralControl(csText.ToString());
Page.Header.Controls.Add(lc);
This adds the script into the head tag:
LiteralControl lt = new LiteralControl("<script type='text/javascript'>alert('test');</script>");
Header.Controls.Add(lt);
UPDATE
LiteralControl lt = new LiteralControl(AddGACode());
Header.Controls.Add(lt);
...
private string AddGACode()
{
var result = string.Empty;
var gaCode = SiteManager.GetSite().GoogleAnalyticsCode;
if (!String.IsNullOrEmpty(gaCode) && Response.StatusCode == 200)
{
StringBuilder csText = new StringBuilder();
csText.Append("<script type=\"text/javascript\">");
if (!ConfigurationManager.EnableUniversalGATracking)
{
csText.Append(String.Format("var _gaq = _gaq || []; _gaq.push(['_setAccount', '{0}']); ", gaCode));
csText.Append("_gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();");
}
else
{
csText.Append(String.Concat("(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '", gaCode, " ', 'auto'); ga('send', 'pageview');"));
}
csText.Append("</script>");
result = csText.ToString();
}
return result;
}
I'd keep your markup, in this instance your ga scripts, on mastpage itself. In the head tag add two literals, gaGaq and gaUniversal an then use you logic to contol the visibility of them.
<head runat="server"><script type="text\javascript">
<asp:Literal id="gaGaq" runat="server">
<!-- Put you gaq code here-->
<!-- Keep {0} as a place holder for gaqCode -->
</script>
</asp:Literal>
<asp:Literal id="gaUniveral" runat="server">
<script type="text\javascrtip">
<!-- Put you universal code here-->
<!-- Keep {0} as a place holder for gaqCode -->
</script>
</asp:Literal>
</head>
C#
private void AddGACode()
{
var gaCode = SiteManager.GetSite().GoogleAnalyticsCode;
if (!String.IsNullOrEmpty(gaCode) && Response.StatusCode == 200)
{
if(ConfigurationManager.EnableUniversalGATracking)
{
//Set gaCode
gaUniversal.Text = string.Fomat(gaUniveral.Text, gaCode);
}
else
{
//Set gaCode
gaGaq.Text = string.Format(ga.Text, gaCode);
}
gaUniversal.Visible = ConfigurationManager.EnableUniversalGATracking;
gaGaq.Visible = !ConfigurationManager.EnableUniversalGATracking;
}
else
{
//Hide Both literals if no gaCode
gaUniversal.Visible = gaGaq.Visible = false;
}
}
You could also look at putting all this into a custom control. If you're interested in taking that route I wrote a blog article on exactly that for the gaq style google analytics so I could drop it onto my many asp.net websites. The code in that article owuld need to be modified to suite your needs but should be enough to get you stared.