ASP.NET MVC Razor Won't Accept My Valid Markup

2019-04-04 18:39发布

问题:

I like the Razor syntax a lot, but it certainly falls short of perfect. For example, I have the following block of markup.

@if (Model.FeaturedDestinations != null && Model.FeaturedDestinations.Count() > 0)
{
    int column = 0;

    foreach (var d in Model.FeaturedDestinations)
    {
        column++;
        if (column > 4)
        {
            </div>
            @{ column = 1; }
        }
        if (column == 1)
        {
            @:<div class="row-fluid">
        }
        <div class="span3">
            @RenderDestination(d)
        </div>
    }
    </div>
}

So, the editor gives me the squiggly lines indicating that I have an ending <div> tag before an opening one. I can live with that. But when I run the app, I actually get the following run-time error:

Encountered end tag "div" with no matching start tag. Are your start/end tags properly balanced?

Obviously, I cannot live with that! So is there any trick for dealing with this case? I know what I'm doing as far as the markup I want. But Razor doesn't think so and it's taking over.

And why the heck is MVC wasting cycles checking for balanced tags?

回答1:

For reasons I don't understand, the following corrected the issue:

@if (Model.FeaturedDestinations != null && Model.FeaturedDestinations.Count() > 0)
{
    int column = 0;

    foreach (var d in Model.FeaturedDestinations)
    {
        column++;

        if (column > 4)
        {
            @:</div>
            column = 1;
        }

        if (column == 1)
        {
            @:<div class="row-fluid">
        }
        <div class="span3">
            @RenderDestination(d)
        </div>
    }
    @:</div>
}

Note the addition of @: before several tags. I don't know why these are necessary--the Razor highlighting indicated that it recognized these were tags and not code.

Also, why did this make the error go away? The thing that caused the run-time error has not changed. Perhaps someone can fill in the blanks for me.



回答2:

You need to add @: in front of the tag (as identified in the marked answer). This blog entry explains the reason for that:

http://weblogs.asp.net/scottgu/archive/2010/12/15/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax.aspx

From the blog:

One of the techniques that Razor uses to implicitly identify when a code block ends is to look for tag/element content to denote the beginning of a content region.

and

Not all content container blocks start with a tag element tag, though, and there are scenarios where the Razor parser can’t implicitly detect a content block.

Razor addresses this by enabling you to explicitly indicate the beginning of a line of content by using the @: character sequence within a code block. The @: sequence indicates that the line of content that follows should be treated as a content block: