views:

50

answers:

3

I have an ASP.NET web app that retrieves a JSON collection and outputs the content of the collection, via LINQ to a StringBuilder that has a lot of table and other tags in HTML, with my data pieces interspersed.

This is what I mean:

 sb.AppendFormat(@"
<table cellpadding=""0"" class=""TableStyle"" style=""width: 70%; height: 100%;"" cellspacing=""5"">
    <tr>
        <td class=""PicHolder"" style=""width: 151px"" rowspan=""2"">
        <a href=""http://twitter.com/{0}"" target=""_blank""><img height=""45px"" width=""45px"" src=""{1}"" alt=""{4}""></td>
        <td style=""width: 100%; height: 36px;"" class=""LinkTitleCell"" valign=""top"">
        <span class=""BoldText"" style=""height: 23px"">
        <a href=""{2}"" target=""_blank""><span class=""HyperLinks"">{6}</span></a></span></ br><span class=""NormText""> 
    </tr>
    <tr>
        <td style=""width: 100%; height: 10px;"" class=""MentionedXTimes"" valign=""top"">
        <span class=""NormText"">Mentioned {3} time(s).</span></td>
    </tr>
    <tr>
        <td style=""width: 151px"" class=""UserName""><span class=""UserName""><img height=""1"" src=""spacer.gif"" width=""1"" />{4}:</span></td>
        <td style=""height: 23%; width: 100%"" class=""WhatUserSaid"" valign=""top"">
        {5}</td>
    </tr>
    <tr>
        <td style=""width: 151px"" class=""UserName"">Info:</td>
        <td style=""height: 24px; width: 100%"" class=""LinkTitleCell"" valign=""top""><span class=""NormText"">{7}</span></td>
    </tr>
    <tr>
        <td style=""height: 9px; width: 151px""></td>
        <td class=""LinkGreen"" style=""height: 9px; width: 100%"" valign=""top"">{2}</td>
    </tr>
    <tr>
        <td style=""height: 9px; width: 151px"">&nbsp;</td>
        <td class=""TableSpacer"" style=""height: 9px; width: 100%"" valign=""top"">&nbsp;</td>
    </tr>

</table>", 


count.First.userName, count.First.imgURL, newdata, count.Count, count.First.userName, count.First.txtDesc, (title != string.Empty) ? title2 : newdata, metaDesc2);

You can see all of the {0} and {1} data place holders I am using in the code above, and the reference to the data required at the end of the StringBuilder method call.

I want to be able to separate the HTML from my app so that I can edit it more easily without having to escape all of the "" quote marks.

So I need a template that has place holder for where my data goes. This is a noob question and I know exactly what want but not how to implement it.

Any help much appreciated!

A: 

Perhaps it's better to return the data as json to the browser and there use jqGrid or jQuery template.

Grz, Kris.

XIII
You could create a control if you want which emits the template. however that's server side while the template will be used by javascript meaning client side.It's not the ajax control toolkit. Since recenlty Microsoft decided to invest into jQuery. The templating engine is one of such efforts and it has some great potential. Try it out in this situation and I'm sure you'll succeed.
XIII
I was thinking more along the lines of a DataGrid and if you know about that?
AlexW
I'll try it out, sounds very interesting :)
AlexW
+2  A: 

I'm getting some bad vibes here, like you're building the entire page or at least a very large part of it inside a single stringbuilder for output. This is a very bad thing to do.

If you want to "accumlate" your page string like this, you should write to the Response object directly instead. The StringBuilder forces you to keep all that html in memory on your server for every request, and memory use like this on a web server just won't scale well when you have many requests going at once. Even worse, there's a chance of these stringbuilders ending up on the Large Object Heap. If that happens it could ultimately cause OutOfMemoryExceptions. By contrast, the Response object buffers your html as you write it, and so you only use memory per request up to the size of the buffer. That will scale/perform much better.

Even better, though, is if you work with ASP.Net to make this happen rather than against it. That solves both the scaling problem and your "templating" problem. For example, I'll show you a better way to adapt just a small snippet of the html you posted. First write your .aspx markup like this:

<table cellpadding="0" class="TableStyle" style="width: 70%; height: 100%;" cellspacing="5">
<tr>
    <td class="PicHolder" style="width: 151px" rowspan="2">
    <asp:HyperLink runat="server" ID="TwitterLink" target="_blank">
    <asp:Image runat="server" ID="TwitterLinkImage" Height="45px" Width="45px"/>
    </asp:HyperLink></td>
    ...
</tr>

And then use code like this in your .cs code-behind:

TwitterLink.NavigateUrl = "http://twitter.com/" + count.First.userName;
TwitterLinkImage.ImageUrl = count.First.imgURL;
TwitterLinkImage.AlternateText = newdata;

There you go. Clean separation of markup and code/data that's more readable, avoids all the messy escaping, and will perform even better than your stringbuilder. If you have a lot of records that are exactly the same and you still want fine control over your HTML output, use an <asp:Repeater> control and set up markup like this in it's ItemTemplate. Then c# code will go in the repeater's ItemDatabound event.

Joel Coehoorn
Thanks Joel that's great. My only problem now is calling my 'template' recursively from within a foreach loop... hmmm.
AlexW
@AlexW Use an asp:repeater control instead of a foreach loop. You use the template by handling the repeater's ItemDataBound event.
Joel Coehoorn
+1  A: 

As with most things there are a number of ways of doing it; from the pure code behind which you have as your original question through to the pure client side / jquery templating.

Another option would be to have a user control with the html part of the output in. This could have an associated property with the data object assigned to it. You could then access the data in the html you would put somethihng like:

<%= MyClass.Property %>

Where ever you want that value to appear in the html.

So what I'd look to do (not tested as don't have VS installed on this machine) is the following:

  • create a class which will store the data which you will be receiving in json format
  • Create the user control
  • Specifiy a property on the control which takes an instance of your class defined above
  • Add the control onto your aspx page
  • In the code behind of the aspx page set the retrieval and parsing of the json data in the Page_Load event.
  • Still in the Page_Load; assign the newly created instance of the object to the usercontrol property

Once this is done when the page renders the user control can access the data and display it through the mechanism (bit of code) above.

Hope this helps, been doing a lot of MVC stuff recently so my Web Forms is a little rusty :-)

If this doesn't make much sense, I appologise in advance and if you let me know I will try and update the post with some more code examples to try and make it make more sense :-)

WestDiscGolf
@WestDiscGolf thanks for that. Where I'm struggling is that I'm using a foreach loop to iterate through LINQ objects, and I want the iterations to be visible in the WebUserControl.Also I'm still confused by WebUserControl and how I go about inserting values iteratively, and then displaying it on my .aspx main page. Please help, it's much appreciated here!
AlexW
I'd say iterating over them manually can be a bit painful. I'd go with Joel's suggestion and put the template in a repeater and set the datasource of that to be your collection.
WestDiscGolf