Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
Anonymous
Not applicable

Getting "The name 'Html.Table' does not exist in the current context" in my custom connector project

Hi!

 

I have developed a customer connector for a web service and would like to improve error handling. For that reason I am now handling the different failure HTTP statuses that could occur. I know that the service responds with a simple HTML page in case of an error. I would like to extract the title of that page and present it to the user (e.g. authentication issues).

 

The problem I have is that the parsing of the HTML response is not possible. I get the error "The name 'Html.Table' does not exist in the current context":

 

denisthemenace_0-1601446766797.png

 

 

Here is my code:

 

shared TestSession = (server) =>
let
AuthResp = Web.Contents(server,
[RelativePath="/qcbin/authentication-point/authenticate",
ManualStatusHandling = {400,401,403,404,429,500,502,503}]
),
responseCode = Value.Metadata(AuthResp)[Response.Status],
ErrorMessage = Html.Table(AuthResp, {{"Message", "title"}})
in
if responseCode = 200 then "All good" else ErrorMessage;

 

Anyone who knows why the Function Html.Table is not available in this context?

 

EDIT: I can add that there is no way to build logic around the HTTP status code. The service has some weird implementation which returns additional information in the status code field:

 

HTTP/1.1 401 Failed to authenticate user "xxx", verify your user name and password.
Date: Wed, 30 Sep 2020 07:22:22 GMT

 

The value of 'Response.Status' is empty and I guess it's because of that additional information in the status field that prevents the SDK to extract the correct status value.

 

Thanks and best regards, Denis

1 ACCEPTED SOLUTION

I looked into the power bi code (ILSpy is great 🙂 and figured out that Html.Tables is a built in function, not a Power Query function exactly.  It uses AngleSharp.net under the covers to do the css selectors ect. basically the heavy lifting of the html manipulation / searching.  

 

The following was useful for me, and could be extended to do all the html.table function - it's pretty hacky but got the job done 🙂 

 

MyHtml.Table = (html as text, selectorRecord as any, optional three as any) as any =>
	let
		columnHeader = selectorRecord{0}{0},
		selectorList = List.Transform(Text.Split(selectorRecord{0}{1}, ">"), each Text.Trim(_)),
		eachSelect = List.Accumulate(selectorList, html, (htmlstring, c) =>
			let
				selector = if Text.Contains(c, ":") then Text.BeforeDelimiter(c, ":") else c,
				hasColonSelector = Text.Contains(c, ":"),
				startTag = "<" & selector,
				endTag = "</" & selector
			in
				if (List.Last(selectorList) = c) then
					List.Transform(List.RemoveFirstN(Text.Split(htmlstring, startTag), 1), each Text.BeforeDelimiter(Text.AfterDelimiter(_, ">"), endTag))
				else
					if Text.Contains(htmlstring, startTag) then
						Text.AfterDelimiter(
							if hasColonSelector then
								if Text.Contains(c, ":nth-of-type") then
									if Text.Contains(c, ":not") then
										let
											// hacky
											nthOfTypeNumber = try Number.FromText(Text.BetweenDelimiters(Text.Replace(c, ":not(", ""), "(", ")")) otherwise 0,
											notValue = Text.BetweenDelimiters(htmlstring, startTag, endTag, if Number.IsNaN(nthOfTypeNumber) then 0 else nthOfTypeNumber - 1),
											thisValue = Text.Combine( Text.Split(Text.Replace(htmlstring, notValue, ""), startTag) )
										in
											startTag & thisValue
									else
										let
											nthOfTypeNumber = try Number.FromText(Text.BetweenDelimiters(c, "(", ")")) otherwise 0,
											notValue = Text.BetweenDelimiters(htmlstring, startTag, endTag, if Number.IsNaN(nthOfTypeNumber) then 0 else nthOfTypeNumber - 1)
										in
											startTag & notValue
								else
									Text.BetweenDelimiters(htmlstring, startTag, endTag)
							else
								Text.AfterDelimiter(Text.BeforeDelimiter(htmlstring, endTag), startTag)
						, ">")
					else
						htmlstring
			)
	in
		#table({columnHeader}, List.Transform(eachSelect, each
			let
				htmlReplacements = {
					{ "<br />", Character.FromNumber(13) },
					{ "&nbsp;", " " }
				},
				value = List.Accumulate(htmlReplacements, _, (s, c) => Text.Trim(Text.Replace(s, c{0}, c{1})))
			in
				{ value }
		));

 

View solution in original post

4 REPLIES 4
MaddogMikeB_A_G
Frequent Visitor

Did you find out wht 'Html.Table' does not exist? 

Anonymous
Not applicable

Hi!

 

No, I did not find out why and could go on without that code. 

 

BR

I looked into the power bi code (ILSpy is great 🙂 and figured out that Html.Tables is a built in function, not a Power Query function exactly.  It uses AngleSharp.net under the covers to do the css selectors ect. basically the heavy lifting of the html manipulation / searching.  

 

The following was useful for me, and could be extended to do all the html.table function - it's pretty hacky but got the job done 🙂 

 

MyHtml.Table = (html as text, selectorRecord as any, optional three as any) as any =>
	let
		columnHeader = selectorRecord{0}{0},
		selectorList = List.Transform(Text.Split(selectorRecord{0}{1}, ">"), each Text.Trim(_)),
		eachSelect = List.Accumulate(selectorList, html, (htmlstring, c) =>
			let
				selector = if Text.Contains(c, ":") then Text.BeforeDelimiter(c, ":") else c,
				hasColonSelector = Text.Contains(c, ":"),
				startTag = "<" & selector,
				endTag = "</" & selector
			in
				if (List.Last(selectorList) = c) then
					List.Transform(List.RemoveFirstN(Text.Split(htmlstring, startTag), 1), each Text.BeforeDelimiter(Text.AfterDelimiter(_, ">"), endTag))
				else
					if Text.Contains(htmlstring, startTag) then
						Text.AfterDelimiter(
							if hasColonSelector then
								if Text.Contains(c, ":nth-of-type") then
									if Text.Contains(c, ":not") then
										let
											// hacky
											nthOfTypeNumber = try Number.FromText(Text.BetweenDelimiters(Text.Replace(c, ":not(", ""), "(", ")")) otherwise 0,
											notValue = Text.BetweenDelimiters(htmlstring, startTag, endTag, if Number.IsNaN(nthOfTypeNumber) then 0 else nthOfTypeNumber - 1),
											thisValue = Text.Combine( Text.Split(Text.Replace(htmlstring, notValue, ""), startTag) )
										in
											startTag & thisValue
									else
										let
											nthOfTypeNumber = try Number.FromText(Text.BetweenDelimiters(c, "(", ")")) otherwise 0,
											notValue = Text.BetweenDelimiters(htmlstring, startTag, endTag, if Number.IsNaN(nthOfTypeNumber) then 0 else nthOfTypeNumber - 1)
										in
											startTag & notValue
								else
									Text.BetweenDelimiters(htmlstring, startTag, endTag)
							else
								Text.AfterDelimiter(Text.BeforeDelimiter(htmlstring, endTag), startTag)
						, ">")
					else
						htmlstring
			)
	in
		#table({columnHeader}, List.Transform(eachSelect, each
			let
				htmlReplacements = {
					{ "<br />", Character.FromNumber(13) },
					{ "&nbsp;", " " }
				},
				value = List.Accumulate(htmlReplacements, _, (s, c) => Text.Trim(Text.Replace(s, c{0}, c{1})))
			in
				{ value }
		));

 

Anonymous
Not applicable

Awesome! Thanks for the insights! 😀

Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

Find out what's new and trending in the Fabric Community.