Eric Schoonover
Eric Schoonover

Reputation: 48392

MVC XHTML Compliance Question

I have a model being populated by my data layer and then I have a partial view which is rendering an instance of that model.

<li class="<%= td.Active ? "youarehere" : string.Empty %> <%= i == ViewData.Model.Count() - 1 ? "last" : string.Empty %>">

The problem is that class="" is invalid XHTML and I will need more complex logic to output the class attribute. What would be the proper way to go about this using ASP.NET MVC. Should the logic live in the view or the model?

I'm just starting out with MVC and I guess I'm still struggling on where exactly to draw the lines as far as where I put logic and what is an acceptable amount of logic for each layer to contain.

Upvotes: 1

Views: 291

Answers (3)

Eric Schoonover
Eric Schoonover

Reputation: 48392

Alright, so based on Phil's input this is what I have done. It works. Please add a comment if there is any useful feedback that anyone has.

  1. I created a HtmlHelper extension method called GenerateAttribute.

    public static string GenerateAttribute(this HtmlHelper hh,
                                           string name,
                                           Func<string> valueFunc)
    { 
        string value = valueFunc().Trim();
        if (!string.IsNullOrEmpty(value))
            return string.Format("{0}=\"{1}\"", name, value);
        return string.Empty;
    }
    
  2. From my View I call Html.GenerateAttribute, passing it a lambda expression that generates the value. The GenerateAttribute method will then return the full attribute (name="val") if the value is not string.Empty.

    <li <%= Html.GenerateAttribute("class", () => string.Format("{0} {1}", td.Active ? "youarehere" : string.Empty, i == ViewData.Model.Count() - 1 ? "last" : string.Empty)) %>>
    

Upvotes: 0

oglester
oglester

Reputation: 6670

An additional thing for this code would be to move the calculation work to a either the controller or the code-behind.

i.e. replace

<li <%= Html.GenerateAttribute("class", 
   () => string.Format("{0} {1}", td.Active 
     ? "youarehere" : string.Empty, 
   i == ViewData.Model.Count() - 1 
     ? "last" : string.Empty)) %>>

with something like

<%= Html.ListItem( ViewData.Model.Value, 
       GetItemCssClass(i, ViewData.Model.Count()) ) %>

and GetItemCssClass could be in code-behind.

Upvotes: 1

Haacked
Haacked

Reputation: 59001

I'd probably implement the code to render that class attribute in a helper method. Either one specific to this view, or one slightly more generic. That way you have less code in your view and it could handle whether or not to even render the class attribute in the case there's nothing to render.

Upvotes: 4

Related Questions