views:

602

answers:

12

So I totally buy into the basic tenents of ASP.NET, testability, SoC, HTML control...it's awesome. However being new to it I have a huge hang up with the markup. I know it comes from my hatred of classic ASP, and I can't help but feel like I've entered the twilight zone when I see this.

I don't know what the alternative is (can I use server controls, databinding etc...?)

+10  A: 

There are things you can do to help clean up the markup, but I agree it can get a bit tag-soupy.

  • You can make your own HTML helpers to output data using extension methods, so you can hide away some of the if/else logic, iteration, etc
  • Strongly type your views so you can do ViewData.Model.myProperty rather than (MyClasst)ViewData["foo"].myProperty

For instance this is an extension I made to make an RSS-spitter-outer :)

  public static string RSSRepeater<T>(this HtmlHelper html, IEnumerable<T> rss) where T : IRSSable
    {
        StringBuilder result = new StringBuilder();

        if (rss.Count() > 0)
        {
            foreach (IRSSable item in rss)
            {
                result.Append("<item>").Append(item.GetRSSItem().InnerXml).Append("</item>");
            }
        }

        return result.ToString();
    }

So in my front end all I have is <%=Html.RSSRepeater(mydata)%> which is much nicer.

qui
Html helpers are kind of nice, but it some cases it's almost worse to have your HTML in concatenated code instead of in the view.
John Sheehan
I agree in a way, especially when you're in an environment where front end developers need to be able to change markup easily.
qui
This is rss, though: the markup is pretty strict and well-defined.
Joel Coehoorn
+4  A: 

Avoiding tag soup reading might be helpful. Generally you can not use server controls (some might work though), there is no postback or viewstate. I don't think you can use databinding (again there might be exceptions, I'm not sure how ASP.NET MVC treats server controls in the view.) - the easiest method to "databind" something is to pass a list or array of data into the view and use foreach to build HTML out of it.

liggett78
That was a great read...still not loving it but it's better than bloated out of control server controls...I do miss databinding though...sniff sniff.
Webjedi
+6  A: 

1) Helpers reduce HTML noise
2) Partial Views to break up larger pages/reuse view code
3) Try a different rendering engine, such as Sparkline
4) REFACTOR if your view includes too many if statements.

Will
+1  A: 

Move some (not all, only in cases it makes sense) display logic (like your dates) into your model. For instance, in your example you could add a Task.DisplayDate string property that handles the .ToShortDateString() call. Then if it ever changes, you change it all in one place and it shortens up the code in the view.

HTML helpers are nice, sometimes. I don't really like having my HTML in concatenated strings or a StringBuilder in a class somewhere, but if you're doing something a lot that works with a lot of different sets of data they're not so bad.

I would also change your C# code formatting preferences to have brackets on the same line. That cuts down the clutter. Unfortunately you can't have separate settings for this between the code editor and the HTML editor, so you'll have to get used to it in your code too. It's not the worst thing in the world.

What others have said helps too: use partial views and strong-typing.

John Sheehan
A: 

If you press ctrl+z after it formats it just undoes the formatting and not the typing.

I find this helpful to keep the first bracket on the same line as the if statement

Schotime
A: 

If you're talking about the HTML from rendered controls, I'm afraid it doesn't get any better just because you've got a nice standards-based wrapper around your View in MVC. Without adapted controls, the output is still circa-1995 crappy nested table code.

Thanks, Microsoft!

John Dunagan
A: 

use server side comments <%-- comment --%> to separate blocks and increase readability. use extra line spacing to separate blocks too (SO seems to be killing off my line spacing here for some reason).

  <%-- Go through each testimonial --%>
     <% foreach (var testimonial in ViewData.Model.Testimonials) { %>

        <div class="testimonialFrame">
         <div class="testimonialHeader"><%= testimonial.summaryText %></div>


         <%-- Show video if available --%>
         <% if (string.IsNullOrEmpty(testimonial.Video.FullURL) == false) { %>

         <div  style="padding-top:12px">
                <% Html.RenderAction("YouTubeControl", "Application", new { youTubeId = testimonial.Video.FullURL }); %>
         </div>

            <% } %>

            <div class="roundedBox" style="margin-top:15px">
                <div id="txtTestimonialText" class="testimonialText paddedBox"><%= testimonial.TestimonialText %></div>
            </div>

         <div class="testimonialFooter"><%= testimonial.name %></div>
        </div>

        <% } %>
Simon_Weaver
A: 

Very occasionally use helper methods (I'm NOT talking about the extension helper methods) to write HTML code in the view itself using the Html object model. I wouldnt recomment this unless you have some wierd logic that you cant easily write in the view. As long as the code in .aspx.cs is VIEW code then its fine.

In your View's .aspx file :

 <%-- render section --%>
 <% RenderTextSection(section); %>

In your View's 'codebehind' you use HtmlGenericControl to create HTML and then the following line to write it out :

htmlControl.RenderControl(new HtmlTextWriter(Response.Output));

My full method :

protected void RenderTextSection(ProductSectionInfo item)

    {
        HtmlGenericControl sectionTextDiv = new HtmlGenericControl("div");

        bool previousHasBulletPoint = false;
        System.Web.UI.HtmlControls.HtmlControl currentContainer = sectionTextDiv;

        foreach (var txt in item.DescriptionItems)
        {
            if (!previousHasBulletPoint && txt.bp)
            {
                // start bulleted section
                currentContainer = new HtmlGenericControl("UL");
                sectionTextDiv.Controls.Add(currentContainer);
            }
            else if (previousHasBulletPoint && !txt.bp)
            {
                // exit bulleted section
                currentContainer = sectionTextDiv;
            }

            if (txt.bp)
            {
                currentContainer.Controls.Add(new HtmlGenericControl("LI")
                {
                    InnerHtml = txt.t
                });
            }
            else
            {
                currentContainer.Controls.Add(new HtmlGenericControl()
                {
                    InnerHtml = txt.t
                });
            }

            previousHasBulletPoint = txt.bp;
        }

        sectionTextDiv.RenderControl(new HtmlTextWriter(Response.Output));
    }
Simon_Weaver
Using code-behind is now frowned upon.
LaptopHeaven
The stuff that is typically **in** the code-behind (ie. event handlers) is now frowned upon, but this approach is certainly justified. Are you frowning upon it just for the sake of frowning?
JoshJordan
@josh theres a lot of that going around
Simon_Weaver
A: 

I'd suggest looking at the Velocity templating engine that MonoRails used. ASP.NET MVC models itself very closely on the MonoRails format, so using the Velocity templates is fairly easy.

Click here to learn more.

Soviut
+1  A: 

I like to make the syntax highlighting for my "<% %>" tags very similar to the background color. I use a black background and a silver-ish (don't have the specific colour on hand atm) colour for my "<% %>" tags. That plus the other suggestions here should have make your code more readable. Of course, you can always try another view engine (that's the beauty of MVC!)

anurse
+1  A: 

I would look at some of the other View engines available, I personally really like Spark view engine but there are many others out there.

Scott Hanselman did a great post looking at spark and Nhaml with some snippets of markup that you can look at to see if it fits your asthetics :)

http://www.hanselman.com/blog/TheWeeklySourceCode30SparkAndNHamlCrazyASPNETMVCViewEngines.aspx

Almond
A: 

Well now you could try out Razor (in ASP.NET MVC 3)

I just hope that the "@" won't scare you too :P

Andrei Rinea