3

I need to read the href from a LiteralControl and add some attributes to it:

Markup;

<a id="aMyAnchor" runat="server" href="bob.com">click me</a>

Here's what I tried:

string url= "bob.com";
var myAnchor = divLinkContainer.Controls
    .Cast<LiteralControl>()
    .Where(a => a.Attributes["href"]
    .Contains(url)).First();

However, LiteralControl does not have an attributes property...

NOTE: I know I can access the link directly via its id, but that's just because I made the example code simple.

EDIT:

This:

string url= "bob.com";
var myAnchor = divLinkContainer.Controls
    .Cast<HtmlAnchor>()
    .Where(a => a.HRef
    .Contains(url)).First();

results in this:

Unable to cast object of type 'System.Web.UI.LiteralControl' to type 'System.Web.UI.HtmlControls.HtmlAnchor'.

O.O
  • 11,077
  • 18
  • 94
  • 182

5 Answers5

4

Your divLinkContainer node may contain other nodes which cannot be casted to HtmlAnchor type. To select only nodes of type HtmlAnchor use Enumerable.OfType:

var myAnchor = divLinkContainer.Controls
    .OfType<HtmlAnchor>()
    .Where(a => a.HRef.Contains(url))
    .First();
Oleks
  • 31,955
  • 11
  • 77
  • 132
  • @白ジェームス: this could be done even more cleaner: `divLinkContainer.Controls.OfType().First(a => a.HRef.Contains(url))` :p – Oleks Feb 28 '12 at 20:54
  • ya, but I live in a 1024x768 world. By the way, I always get "sequence contains no elements" for myAnchor. Any idea why? Even if I remove the where portion. – O.O Feb 28 '12 at 20:57
  • @白ジェームス: you get *sequence contains no elements* because `.First()` method expects the sequence is not empty. Use `.FirstOrDefault()` if you want to get `null` if no element found. Empty sequence means there is no elements matching your criteria. – Oleks Feb 28 '12 at 21:10
  • I see. I didn't realize it before, but my markup was oversimplified in the question. – O.O Feb 28 '12 at 21:25
  • @白ジェームス: why don't you access your anchor by it's id? It is really much more easier then doing it using LINQ. But it still could be done by using LINQ if you have exact the same markup as you posted in update to your question. If the *depth* of your anchor is really unknown the only solution I see is to iterate through all child node of the child nodes etc. – Oleks Feb 28 '12 at 21:33
3
var myAnchor = divLinkContainer.Controls
    .Cast<Control>()
    .Where(a => a is HtmlAnchor).Select(a=>(HtmlAnchor)a)
    .Where(a => a.HRef.Contains(url))
    .First();

The idea is to use Cast with the most possible/relevant base class and also make sure all your controls which are going to be casted do inherit that type.

Adrian Iftode
  • 15,465
  • 4
  • 48
  • 73
  • For some reason I get "sequence contains no elements" every time, even if I remove the .contains portion and I try to get all HtmlAnchors. In the debugger they still show as LiteralControl. var test = divLinkContainer.Controls .OfType(); – O.O Feb 28 '12 at 20:55
  • If the anchors are not direct children of the divLinkContainer and you call First, then you get this exception. You'll need to find a method to get all descendants. – Adrian Iftode Feb 28 '12 at 21:06
  • Oh, yes. Each anchor has p tag as its direct parent. – O.O Feb 28 '12 at 21:11
  • I found the answer here: http://stackoverflow.com/questions/253937/recursive-control-search-with-linq You answered my original question with the information I provided. – O.O Feb 28 '12 at 21:30
1

Cast it to an HtmlAnchor instead, then you can use it's href property.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • I get an exception when I do that: Unable to cast object of type 'System.Web.UI.LiteralControl' to type 'System.Web.UI.HtmlControls.HtmlAnchor'. – O.O Feb 28 '12 at 20:23
  • Maybe because you already have declared in as LiteralControl. Modify the `protected global:: System.Web.UI.LiteralContro aMyAnchor` to `protected global::System.Web.UI.HtmlControls.HtmlAnchor aMyAnchor` in the designer.cs. But actually a `a` is mapped to HtmlAnchor if it's `runat=server`. – Tim Schmelter Feb 28 '12 at 20:27
  • Well, yes, of course. However, I stubbornly asked when using a LiteralControl. I'd like a solution using LiteralControl. – O.O Feb 28 '12 at 20:28
0

You can cast the required target object to the “HtmlAnchor” type and operate with the “HRef” property.

Mikhail
  • 9,186
  • 4
  • 33
  • 49
0

Assign href to the value property of another control and make that control hidden.

TheTechGuy
  • 16,560
  • 16
  • 115
  • 136