ASP.NET. MVC 2 C#: So much whitespace
There a section of my code that is a mix between <% %>
statements and HTML ... the view source is horrible. There is so much whitespace it makes me choke with disgust.
Is there anything I can do about this?
<!-- START Content -->
<div class="divFilterWrap">
<img src="/Content/Images/filterMainCuisineHeader.gif" />
<ul>
<% int count = 1; %>
<% foreach (var filter in Model.Filter)
{ %>
<% if (filter.GroupOrder == count) {
} else { %>
<% count++; %>
</ul>
<% switch (filter.GroupLabel)
{ %>
<% case "Main Cuisine": %>
<img src="/Content/Images/filterMainCuisineHeader.gif" width="175" height="30" />
<% break; %>
<% case "Dining Style": %>
<img src="/Content/Images/fil开发者_StackOverflow中文版terDiningStyleHeader.gif" width="175" height="30" />
<% break; %>
<% case "Price Range": %>
<img src="/Content/Images/filterPriceRangeHeader.gif" width="175" height="30" />
<% break; %>
<% } %>
<ul>
<% } %>
<% if (filter.TagCount > 0) { %>
<% if (filter.TagChecked == 1) { %>
<li class="checked"><%: filter.TagLabel %> (<%: filter.TagCount %>) <span class="closeImage"><img src="/Content/Images/filterButtonClose.gif" /></span></li>
<% } else { %>
<li><%: filter.TagLabel %> (<%: filter.TagCount %>)</li>
<% } %>
<% } %>
<% } %>
</ul>
</div><!-- END Content -->
Where the C# code sits, that space is reserved when viewing source. And here is what it looks like:
<!-- START Content -->
<div class="divFilterWrap">
<img src="/Content/Images/filterMainCuisineHeader.gif" />
<ul>
<li>Coffee / Tea House (1)</li>
</ul>
<img src="/Content/Images/filterDiningStyleHeader.gif" width="175" height="30" />
<ul>
<li>Casual Dining (1)</li>
</ul>
<img src="/Content/Images/filterPriceRangeHeader.gif" width="175" height="30" />
<ul>
<li>$8 to $15 (1)</li>
</ul>
</div><!-- END Content -->
GROSS!
Turn on GZIP compression in IIS. The effects of white space in HTML are greatly reduced with GZIP compression on.
See for example: http://www.kwaree.com/blog/2009/11/27/how-to-remove-whitespace-from-html-code/
"the removal of whitespace is not a worthwhile endeavor. Any decent web server is configured to use “gzip” encoding for the serving of html documents. The whitespace is readily compressed and will be not significantly change the amount of data involved in serving the document. While the end result will be smaller, it will not be a nearly as large of a gain as casual observation would suggest."
ok, you are making a number of mistakes. The reason you have so much whitespace is that you're putting each C# code block on a new line. You don't need to do this. Have a look at my changes:
<img src="/Content/Images/filterMainCuisineHeader.gif" />
<ul>
<% int count = 1;
foreach (var filter in Model.Filter)
{
if (filter.GroupOrder == count) {
} else {
count++; %>
</ul>
<% switch (filter.GroupLabel)
{
case "Main Cuisine": %>
<img src="/Content/Images/filterMainCuisineHeader.gif" width="175" height="30" />
<% break;
case "Dining Style": %>
<img src="/Content/Images/filterDiningStyleHeader.gif" width="175" height="30" />
<% break;
case "Price Range": %>
<img src="/Content/Images/filterPriceRangeHeader.gif" width="175" height="30" />
<% break;
} %>
<ul>
<% }
if (filter.TagCount > 0) {
if (filter.TagChecked == 1) { %>
<li class="checked"><%: filter.TagLabel %> (<%: filter.TagCount %>) <span class="closeImage"><img src="/Content/Images/filterButtonClose.gif" /></span></li>
<% } else { %>
<li><%: filter.TagLabel %> (<%: filter.TagCount %>)</li>
<% }
}
} %>
</ul>
You can see how I've removed a ton of your <%
and %>
and conjoined codeblocks together
You could use an HTTP module to remove the whitespace. Mads Kristensen has one: http://madskristensen.net/post/A-whitespace-removal-HTTP-module-for-ASPNET-20.aspx
Lots of things. You could just delete the whitespace... multiple whitespaces aren't significant in either C# or HTML.
Or you could rewrite your view to use a view model DTO closely coupled to the structure of the page, so you're emitting pre-formatted fragments and rendering partial controls instead of having any complex control logic in your page code?
If you want to post your source, I'm sure there's ways to eliminate the whitespace if you really want to. But you're probably better off just ignoring it. :)
EDIT: OK, try this. Use a dedicated view model, so you can have your controller assign things like Image URLs in the controller logic instead of branching in the page code.
<img src="/Content/Images/filterMainCuisineHeader.gif" />
<ul>
<%
int count = 1;
foreach (var filter in Model.Filter) {
if (filter.GroupOrder != count) {
count++;
%></ul>
<img src="<%=filter.ImageUrl%>" width="175" height="30" />
<ul>
<%
}
if (filter.TagCount > 0) { %>
<li class="<%=filter.CssClass%>">
<%: filter.TagLabel %> (<%: filter.TagCount %>)
<span class="closeImage">
<img src="/Content/Images/filterButtonClose.gif" /></span>
</li><%
}
}
%></ul>
</div><!-- END Content -->
You'll need Model.Filter to be an IEnumerable, which looks like:
public class FilterViewData {
public int GroupOrder { get; set; }
public int TagCount { get; set; }
public string CssClass { get; set; }
public string ImageUrl { get; set; }
public string TagLabel { get; set; }
}
- something like AutoMapper might prove very useful in populating your view data objects.
In this example, you'd also create a CSS rule like:
li.unchecked span.closeImage { display: none; }
so that the closeImage span and image don't appear inside the unchecked list items.
Does that help?
Consider this example in your source:
<ul>
<% int count = 1; %>
<% foreach (var filter in Model.Filter)
That's a lot of spurious whitespace after the <ul>
(the indentation to your server tags). You could rewrite it as:
<ul>
<% int count = 1; %>
<% foreach (var filter in Model.Filter)
And adopt a style where server tags always begin on the line. IMO, not worth it though -- I'd go with @Hightechrider's solution.
Consider a few bits of constructive points of improvement:
- escaping in and out of code/HTML far too much.
<ul>
<% int count = 1;
foreach (var filter in Model.Filter)
{
if (filter.GroupOrder != count)
{
count++; %>
you've got logic in your View. Consider moving that logic back into the controller. Your Model should have a property called GroupLabelImage, and the
switch
belongs in the controller. You should then write out the image just once.all calculations should be moved to the controller.
To follow up my comment to @Alastair Pitts, (wiki because I just want to show formated example) I'm fairly certain that it's the whitespace between your HTML and the ASP.Net tags that is the real culprit, so starting with something like this is likely to look better when you view source (but it lacks something when it comes to readability in Visual Studio):
<img src="/Content/Images/filterMainCuisineHeader.gif" />
<ul><%
int count = 1;
foreach (var filter in Model.Filter) {
if (filter.GroupOrder != count)
{
}
else
{
count++;
%></ul><%
switch (filter.GroupLabel)
{
case "Main Cuisine":
%><img src="/Content/Images/filterMainCuisineHeader.gif" width="175" height="30" /><%
break;
case "Dining Style":
%><img src="/Content/Images/filterDiningStyleHeader.gif" width="175" height="30" /><%
break;
case "Price Range":
%><img src="/Content/Images/filterPriceRangeHeader.gif" width="175" height="30" /><%
break;
}
%><ul><%
}
if (filter.TagCount > 0)
{
if (filter.TagChecked == 1)
{
%><li class="checked"><%: filter.TagLabel %> (<%: filter.TagCount %>)
<span class="closeImage">
<img src="/Content/Images/filterButtonClose.gif" />
</span>
</li><%
}
else
{
%><li><%: filter.TagLabel %> (<%: filter.TagCount %>)</li><%
}
}
}
%></ul>
精彩评论