10

I'm having fun with Razor today! Can you see what is wrong with this view and explain why it errors?

@foreach (var item in Model){

if (item.ID != PreviousOrderId){
    <div class="orderdetail">
        <div class="customer">
            <p class="strong">OrderID:</p> 
            <p>@item.ID</p>
            <p class="strong">Order Date:</p>
            <p>@String.Format("{0:g}", TimeZoneInfo.ConvertTime(item.DateInitialised, TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time")))</p>
            <p class="strong">Customer Name:</p> 
            <p>@item.WebsiteUser.Name</p>
            <p class="strong">Practice Name:</p>
            <p>@item.WebsiteUser.PracticeName</p>
            <p class="strong">Customer E-Mail:</p> 
            <p>@item.WebsiteUser.EMailAddress</p>
        </div>
   }



    <div class="detail">
        <span class="strong">Licence Key:</span><span>@item.Licence.LicenceKey</span>
        <span class="strong">Serial No:</span><span>@item.Licence.SerialNumber</span>
    </div>               

   @if (item.ID != PreviousOrderId && PreviousOrderId != 0){
    </div>
    <div class="clear"></div>
   }        

PreviousOrderId = item.ID;
}
Jon
  • 38,814
  • 81
  • 233
  • 382
  • My guess would be the missing `}` character at the end of a foreach block. Paste the entire file, and the entire error message verbatim so that we can see line numbers. – dotancohen Mar 12 '12 at 11:49
  • Maybe you can watch the syntax-coloring instead of posting a [series](http://stackoverflow.com/q/9665919/60761) here? – H H Mar 12 '12 at 11:53
  • @HenkHolterman I'm trying. I don't post here unless I'm stuck – Jon Mar 12 '12 at 11:55
  • 1
    I think van Hooijdonk has the truth of this; razor expects a logical tree; you have broken that when you split the div into pieces. – Marc Gravell Mar 12 '12 at 11:55
  • @MarcGravell I dont get why Razor is complaining as surely the @ directives are just server side identifiers so it knows when to do server side logic and in this case it should close the div. Its as if Razor is more than just a compiler like directive – Jon Mar 12 '12 at 11:57
  • @Jon razor wants everything to be cleanly nested into a tree: `@razor {... ......}` - you have broken that... basically, you might need to group outside the loop etc – Marc Gravell Mar 12 '12 at 12:01
  • 1
    @Jon to be very specific; the first block contains an unbalanced `
    ` - the last block contains an unbalanced `
    `
    – Marc Gravell Mar 12 '12 at 12:05

2 Answers2

17

You have divided <div class="orderdetail"> into two pieces. Opening tag is in first if block, closing tag is in second if block.

This is something confusing for Razor, I think.

Try to open and close your div in one if block.

adyusuf
  • 806
  • 1
  • 11
  • 27
  • That's exactly what's happening. The razor editor does not see the closing so it fails to find the } from the first if block. Then it fails to see the closing } from the foreach block for the same reason. I would not be surprised if it was just an editor issue and the view worked just fine. – Falanwe Mar 12 '12 at 11:58
  • 2
    @Falanwe It throws a YSOD with a Parser Error unfortunately. I thought it should just be editor-side as well – Jon Mar 12 '12 at 12:00
  • @Falanwe Parser Error Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. Parser Error Message: The foreach block is missing a closing "}" character. Make sure you have a matching "}" character for all the "{" characters within this block, and that none of the "}" characters are being interpreted as markup. – Jon Mar 12 '12 at 12:05
  • @Jon Did you try my solution? It will solve your issue, I think. – adyusuf Mar 12 '12 at 12:06
  • I guess the important part is "none of the "}" characters are being interpreted as markup." – Falanwe Mar 12 '12 at 12:08
  • 1
    @vanHooijdonk I can see why that would work but it won't solve the problem I have in what I'm trying to achieve – Jon Mar 12 '12 at 12:10
9

if you already are inside a code-block you dont need to @-prefix code constructs anymore...your code block starts with @foreach.

@foreach (var x in new string[] { "x", "y" ])
{
    if (userGuid != ViewBag.x)
   {
    @:<div class="orderdetail">
    <div class="customer">
        <p class="strong">OrderID:</p> 
        <p>@item.ID</p>
        <p class="strong">Order Date:</p>
        <p>@String.Format("{0:g}", TimeZoneInfo.ConvertTime(item.DateInitialised</p>
        <p class="strong">Customer Name:</p> 
        <p>@item.WebsiteUser.Name</p>
        <p class="strong">Practice Name:</p>
        <p>@item.WebsiteUser.PracticeName</p>
        <p class="strong">Customer E-Mail:</p> 
        <p>@item.WebsiteUser.EMailAddress</p>
    </div>
    }
    <div class="detail">
        <span class="strong">Licence Key:</span><span>@item.Licence.LicenceKey</span>
        <span class="strong">Serial No:</span><span>@item.Licence.SerialNumber</span>
    </div>               

if (userGuid != ViewBag.x && ViewBag.x != 0)
{
    @:</div>
    <div class="clear"></div>
}      
PreviousOrderId = item.ID;    
}
360Airwalk
  • 2,189
  • 1
  • 16
  • 13