The following program finds the value of the maximum key (represented as the Item field) in a linked list. It provides an iterative method (using a for loop) as well as a recursive method.

```using System;

namespace ConsoleTest
{
class Program
{
private static Node first;

static void Main(string[] args)
{
first = PopulateList();
ShowItems();

Console.WriteLine("Maximum value: {0}", Max());
Console.WriteLine("Maximum value recursively: {0}", RecursiveMax());

}

// Iterative version of Max.
static private int Max()
{
if (first == null)
return 0;

int max = 0;
for (Node node = first; node != null; node = node.Next)
{
if (node.Item > max)
max = node.Item;
}

return max;
}

// Recursive version of Max.
static private int RecursiveMax()
{
if (first == null)
return 0;

return RecursiveMax(first, first.Item);
}

static private int RecursiveMax(Node node, int max)
{
// base case
if (node == null)
return max;

if (node.Item > max)
max = node.Item;

return RecursiveMax(node.Next, max);
}

// ShowItems traverses all the items in the list.
static private void ShowItems()
{
for (Node node = first; node != null; node = node.Next)
{
Console.Write(node.Item.ToString() + " ");
}
Console.WriteLine();
}

// PopulateList returns a reference to the first element.
static private Node PopulateList()
{
int[] nums = { 3, 7, 4, 14, 6, 10, 13, 1 };

Node first = new Node();
Node prev = null;

foreach (int n in nums)
{
var node = new Node();
node.Item = n;

if (prev != null)
prev.Next = node;
else
first = node;

prev = node;
}

return first;
}

private class Node
{
public T Item { get; set; } // key
public Node Next { get; set; }

public override string ToString() { return (Item == null ? "null" : Item.ToString()); }
}
}
}
```

Output:

```3 7 4 14 6 10 13 1
Maximum value: 14
Maximum value recursively: 14
```