问题
I was working on an ASP.NET MVC template today, and after staring at all those fluorescent yellow %
tags for long enough, I basically decided I had had enough, so I painstakingly modified my ascx file to look like this:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<% if (Model == null)
{ %>
<%= ViewData.ModelMetadata.NullDisplayText %>
<% }
else if (ViewData.TemplateInfo.TemplateDepth > 1)
{ %>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<% }
else
{ %>
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(
pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm)))
{ %>
<% if (prop.HideSurroundingHtml)
{ %>
<%= Html.Display(prop.PropertyName) %>
<% }
else
{ %>
<% if (!String.IsNullOrEmpty(prop.GetDisplayName()))
{ %>
<span class="display-label">
<%= prop.GetDisplayName() %>
</span>
<% } %>
<span class="display-field">
<%= Html.Display(prop.PropertyName) %>
</span>
<% } %>
<% } %>
<% } %>
Ahh readability at last. The only problem is, it takes way to long to do this by hand. I need a way to automate this. Some kind of code formatting solution. Perhaps a macro or a Visual Studio add-in or ...? What do you advise?
Update
I'm now planning to refactor out most of the logic from my markup (see Mike's answer below), but in the mean time, I came up with a more manageable way to format ascx files that have a mixture of code and html. The code is a little more spread out this way, but it's much easier to format the code like this in the first place, and it's much easier to work with as well.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
if (Model == null)
{
%>
<%= ViewData.ModelMetadata.NullDisplayText %>
<%
}
else if (ViewData.TemplateInfo.TemplateDepth > 1)
{
%>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<%
}
else
{
%>
<%
foreach (var prop in ViewData.ModelMetadata.Properties.Where(
pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm)))
{
if (prop.HideSurroundingHtml)
{
%>
<%= Html.Display(prop.PropertyName) %>
<%
}
else
{
%>
<div class="display-row">
<%
if (!String.IsNullOrEmpty(prop.GetDisplayName()))
{
%>
<div class="display-label">
<%= prop.GetDisplayName() %>
</div>
<%
}
%>
<div class="display-field">
<%= Html.Display(prop.PropertyName) %>
</div>
</div>
<%
}
}
}
%>
回答1:
I believe your "tag soup" pain is actually a symptom of a different problem: you're feeling it because you've got logic in your view. Views should be very lightweight, with little or no logic. Your logic should be in your controllers, which can decide to render different views depending on the logic. Or you can put the logic into helpers.
See this article by Rob Conery
回答2:
With proper view model (and optionally, with spark view engine), there is no tag soup.
Particularly, if templates are used.
Can't tell much about this example (even less - to sort it out), but for me - usually it's all about sense of tidiness and ability to structure things properly.
"I'm looking for a code formatting solution." => then you must check out spark. It 'htmlifies' your views even if they do contain logic.
Your example in it (without restructuring anything) =>
<var nullText="ViewData.ModelMetadata.NullDisplayText"
templateDepth="ViewData.TemplateInfo.TemplateDepth"
simpleDisplayText="ViewData.ModelMetadata.SimpleDisplayText"
props="ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))"
m="ViewData.Model"/>
<if condition="m==null">
${nullText}
</if>
<elseif condition="templateDepth>1">
${simpleDisplayText}
</elseif>
<else>
<for each="var prop in props">
<if condition="prop.HideSurroundingHtml">
${Html.Display(prop.PropertyName)}
</if>
<else>
<span if="!string.IsNullOrEmpty(prop.GetDisplayName()" class="display-field">
${prop.GetDisplayName()}
</span>
<span class="display-field">
${Html.Display(prop.ProperyName)}
</span>
</else>
</for>
</else>
Might be wrong somewhere, but you got the idea.
回答3:
For our current project, we cleaned up all the if-elses somewhat by writing an HTML helper:
public static void WriteIf(this HtmlHelper helper, bool condition, string truePart, string falsePart)
{
helper.ViewContext.HttpContext.Response.Write(condition ? truePart : falsePart);
}
and then in the HTML, you would say:
<% Html.WriteIf(Model.IsTrue(), "TrueText", "FalseText"); %>
来源:https://stackoverflow.com/questions/2248772/dealing-with-asp-net-mvc-tag-soup