1

I'm finding myself hardcoding html into C#. It's usually on a data-driven pages. The content of the page and url change but the physical page does not change. As it stands now, I have snippets of hardcoded HTML sprinkled throughout the UI. It's usually navigation html, but not always.

In most cases there is logic wrapped around the html. An exampled would selecting the current tab.

It feels dirty - there must be a more elegant solution.

Maybe using the settings file? Database? The database seems a little overkill and add a couple layers of abstraction that does not have value, at least in my application.

Update

I've provided two sample methods. The application is written on the ASP.NET MVC 2 framework.

Example one:

    /// <summary>
    /// Gets the album sub navigation.
    /// </summary>
    /// <returns></returns>
    public string GetAlbumSubNavigation()
    {
        StringBuilder builder = new StringBuilder();
        IDictionary<string, string> links = new Dictionary<string, string>
                                                {
                                                    {"all",  @"<li><a {2} href=""/{0}/albums/addphotos/{1}"">All</a></li>"},
                                                    {"bytags",  @"<li><a {2} href=""/{0}/albums/tags/{1}"">Tags</a></li>"},
                                                    {"bysearching", @"<li><a {2} href=""/{0}/albums/searchphotos/{1}"">Search</a></li>"}
                                                };

        builder.AppendLine(@"<ul style=""text-align: right; margin-bottom: 40px;"" class=""hyperlinks"" id=""subviewlinks"">");
        foreach (KeyValuePair<string, string> keyValuePair in links)
        {
            string youarehere = (string.Equals(PartialViewName, keyValuePair.Key,
                                               StringComparison.InvariantCultureIgnoreCase)
                                     ? "class=\"youarehere\""
                                     : string.Empty);
            builder.AppendLine(string.Format(keyValuePair.Value, Authorization.Owner.Username, Album.AlbumId,
                                             youarehere));
        }
        builder.AppendLine(@"</ul>");
        return builder.ToString();
    }

Example two:

    /// <summary>
    /// Gets the photo detail links.
    /// </summary>
    /// <param name="media">The media.</param>
    /// <param name="isAuthenticated">if set to <c>true</c> [is authenticated].</param>
    /// <returns></returns>
    public static string GetPhotoDetailLinks(Media media, bool isAuthenticated)
    {
        IUserUrlService userUrlService = GetUserUrlService();
        ITagService tagService = DependencyInjection.Resolve<ITagService>();

        const string perminateLinkFormat = @"<li><a href=""{0}"" title=""{1}"" >permalink</a></li>";
        string perminateLink = string.Format(perminateLinkFormat, userUrlService.UserUrl(media.Owner.Username, "photos/show/" + media.MediaId), media.Title);

        string html = @"<ul>
                    <li>
                    <span>";
        html += (isAuthenticated ? @"<a id=""editlink""  href=""{0}/photos/edit/{1}"">edit</a>" : string.Empty);
        html += @"</span>            
                </li>";
        html += "{2}";
        html += @"          
                </li>
                 {3}  
                 {5}                  
                <li><span><a href=""{0}/comments/leave/{1}"">comments ({4})</a></span> 
            </ul>";

        string tags = string.Empty;
        if (!string.IsNullOrEmpty(media.Tags))
        {
            const string tagFormat = @"<li><span>tags:</span> {0}</li>";
            string renderedTags = tagService.HyperlinkTheTags(media.Tags, media.Owner.Username);
            tags = string.Format(tagFormat, renderedTags);
        }

        string date = GetDate(media);

        string content = string.Format(html, userUrlService.UserRoot(media.Owner.Username), HttpUtility.HtmlEncode(media.MediaId.ToString()), date, tags, media.CommentCount, perminateLink);
        return content;
    }
Chuck Conway
  • 16,287
  • 11
  • 58
  • 101

3 Answers3

1

Take a look at specifying your HTML as a template and substituting content at runtime through template variables. See this post for some ideas using T4 or XSLT: C# template engine.

Community
  • 1
  • 1
Ed Power
  • 8,310
  • 3
  • 36
  • 42
1

Depending on why you are accessing the HTML, the following can help either reduce the degree of hardcoding, or at least put it somewhere more manageable:

  1. Master-pages.
  2. User-controls.
  3. Resources.
  4. Writing XHTML with an XmlWriter.
  5. Writing XML with an XmlWriter (or otherwise) and then processing with XSLT (whether on the server or the client).

Its worth noting, that if you use master-pages, you can change which master page is used from the C#. Likewise user-controls can be loaded dynamically (perhaps as a control that loads in a programmatically selected control).

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • Resources might work... I'm not interested in XML. It's replacing one problem with another... It's ASP.NET MVC, so no controls. – Chuck Conway Aug 30 '10 at 22:24
0

As it stands now, I have snippets of hardcoded HTML sprinkled throughout the UI. It's usually navigation html, but not always.

If you're using Asp.Net, the answer is probably to use Master Pages.

Any sort of special groups of code showing up all over the place should be encapsulated into a User Control.

Brian
  • 25,523
  • 18
  • 82
  • 173
  • They've been encapsulated and centralized in C# classes... I have to think about the Usercontrols. That might work. I was thinking something more along the lines of a string MVC-esk templating engine, I don't know if such a thing exists. – Chuck Conway Aug 30 '10 at 22:29
  • My answer is more geared towards webforms than MVC. – Brian Aug 30 '10 at 22:51