2013-05-07 115 views
2

我遇到了Razor2视图的一个非常奇怪的问题。下面的代码是实际代码,其中智能感知正在抛弃红色曲线,只是名称已更改。剃刀看不到我的右大括号

@model Space.ViewModels.PropertyAdminViewModel 

@{ 
    ViewBag.Title = "Create"; 
    ViewBag.UmbracoTitle = "Create Property"; 
    Layout = "../Shared/_Layout.cshtml"; 

    InitView(); 
    AnalysePreviousState(); 
    SortErrorsPerStep(); 
    GetStepToDisplay(); 
} 

<script src="../../Scripts/jquery-1.8.2.min.js"></script> 
<script src="../../Scripts/jquery.validate.min.js"></script> 
<script src="../../Scripts/jquery.validate.unobtrusive.min.js"></script> 
<script src="../../Scripts/AdminScripts.js"></script> 

@Html.ValidationSummary(ErrorMessage) 

@using (Html.BeginForm()) 
{ 
    @Html.Hidden("CurrentStep", StepToDisplay.ToString(), new { id="CurrentStep"}) 
    <input id="AddressButton" type="submit" name="@Button.AddressButton.ToString()" value="Address Details" /> 
    <input id="DetailsButton" type="submit" name="@Button.DetailsButton.ToString()" value="Details &amp; Description" /> 
    <input id="MediaButton" type="submit" name="@Button.MediaButton.ToString()" value="Images &amp; Documents" /> 


    switch (StepToDisplay) 
    { 
     case Step.Address: 
      Html.RenderPartial("_AddressDetailsForm", ViewData.Model.Address); 
      break; 
     case Step.Details: 
      Html.RenderPartial("_PropertyDetailsForm", ViewData.Model); 
      break; 
     case Step.Media: 
      Html.RenderPartial("_MediaUploadEditForm", ViewData.Model.MediaItems); 
      break; 
    } 


    <input id="BackButton" type="submit" name="@Button.BackButton.ToString()" value="Back" /> 
    <input id="NextButton" type="submit" name="@Button.NextButton.ToString()" value="Next" /> 
    <input id="FinishButton" type="submit" name="@Button.FinishButton.ToString()" value="Finish" /> 

} <-- `SQUIGGLY` 


@{ 
    private enum Button 
    { 
     None, 
     AddressButton, 
     DetailsButton, 
     MediaButton, 
     NextButton, 
     BackButton, 
     FinishButton, 
     CancelButton 
    } 

    public enum Step 
    { 
     Address, 
     Details, 
     Media, 
     UpperBound 
    } 

    private const Step AddressStep = Step.Address; 
    private const Step DetailsStep = Step.Details; 
    private const Step MediaStep = Step.Media; 
    private const Step First_Step = AddressStep; 
    private const Step Last_Step = MediaStep; 
    private const string CurrentStep = "CurrentStep"; 
    private const string DisabledAttribute = "disabled='disabled'"; 

    private string BackButtonState = string.Empty; 
    private string NextButtonState = string.Empty; 
    private string ErrorMessage = "Please correct the errors and try again."; 
    private Button ButtonPressed = Button.None; 
    private Step PreviousStepDisplayed = AddressStep; 
    private Step StepToDisplay = AddressStep; 
    private ModelStateDictionary[] StepModelState = new ModelStateDictionary[(int)Step.UpperBound]; 

    private void InitView() 
    { 
     // Create a ModelState for each individual step 
     for (int key = (int)First_Step; key <= (int)Last_Step; key++) 
     { 
      StepModelState[key] = new ModelStateDictionary(); 
     } 
    } 

    /// <summary> 
    /// Check form variables from the last HTTP_POST to figure where the wizard needs to be 
    /// Grab the current step string along with which button was pressed 
    /// </summary> 
    private void AnalysePreviousState() 
    { 
     if (!string.IsNullOrEmpty(Request[CurrentStep])) 
     { 
      PreviousStepDisplayed = (Step)Enum.Parse(typeof(Step), Request[CurrentStep], true); 
     } 

     if (!string.IsNullOrEmpty(Request[Button.FinishButton.ToString()])) 
     { 
      ButtonPressed = Button.FinishButton; 
     } 

     if (!string.IsNullOrEmpty(Request[Button.CancelButton.ToString()])) 
     { 
      ButtonPressed = Button.CancelButton; 
     } 

     if (!string.IsNullOrEmpty(Request[Button.NextButton.ToString()])) 
     { 
      ButtonPressed = Button.NextButton; 
     } 

     if (!string.IsNullOrEmpty(Request[Button.BackButton.ToString()])) 
     { 
      ButtonPressed = Button.BackButton; 
     } 

     if (!string.IsNullOrEmpty(Request[Button.AddressButton.ToString()])) 
     { 
      ButtonPressed = Button.AddressButton; 
     } 

     if (!string.IsNullOrEmpty(Request[Button.DetailsButton.ToString()])) 
     { 
      ButtonPressed = Button.DetailsButton; 
     } 

     if (!string.IsNullOrEmpty(Request[Button.MediaButton.ToString()])) 
     { 
      ButtonPressed = Button.MediaButton; 
     } 
    } 

    /// <summary> 
    /// Sort all modelstate errors into the right step 
    /// </summary> 
    private void SortErrorsPerStep() 
    { 
     foreach (KeyValuePair<string, ModelState> entry in ViewData.ModelState) 
     { 
      foreach (int key in Enum.GetValues(typeof(Step))) 
      { 
       //Compare the start of each error's key with the name of a step 
       //if they match then that error belongs to that step 
       if (entry.Key.StartsWith(((Step)key).ToString())) 
       { 
        StepModelState[key].Add(entry); 
        break; 
       } 
      } 
     } 

     ViewData.ModelState.Clear(); 
    } 

    /// <summary> 
    /// Look at the previous step to get any errors and which button was clicked 
    /// and decide which step needs to be displayed now 
    /// </summary> 
    private void GetStepToDisplay() 
    { 
     //if the user tried to jump steps or finish, display the first step that has errors 
     //this ensures that the wizard is completed in the intended sequence 
     if (ButtonPressed != Button.NextButton && ButtonPressed != Button.BackButton) 
     { 
      ErrorMessage = "There are errors in the data provided. Please correct the errors and try again."; 

      for (Step key = First_Step; key <= Last_Step; key++) 
      { 
       if (!StepModelState[(int)key].IsValid) 
       { 
        DisplayStep(key, true); 
        return; 
       } 
      } 
     } 

     //if the last step has errors and the user has not hit the back button then stay on page and show the errors 
     //user can go back through steps but not forward until errors are resolved 
     if (!StepModelState[(int)PreviousStepDisplayed].IsValid && ButtonPressed != Button.BackButton) 
     { 
      DisplayStep(PreviousStepDisplayed, true); 
      return; 
     } 

     //Otherwise move as per user request 
     Step stepToDisplay = PreviousStepDisplayed; 

     switch (ButtonPressed) 
     { 
      case Button.BackButton: 
       stepToDisplay--; 
       break; 
      case Button.NextButton: 
       stepToDisplay++; 
       break; 
      case Button.AddressButton: 
       stepToDisplay = AddressStep; 
       break; 
      case Button.DetailsButton: 
       stepToDisplay = DetailsStep; 
       break; 
      case Button.MediaButton: 
       stepToDisplay = MediaStep; 
       break; 
     } 

     stepToDisplay = (Step)Math.Max((int)stepToDisplay, (int)First_Step); 
     stepToDisplay = (Step)Math.Min((int)stepToDisplay, (int)Last_Step); 

     DisplayStep(stepToDisplay, false); 
    } 

    private void DisplayStep(Step stepToDisplay, bool displayErrors) 
    { 
     StepToDisplay = stepToDisplay; 
     BackButtonState = stepToDisplay == First_Step ? DisabledAttribute : string.Empty; 
     NextButtonState = stepToDisplay >= Last_Step ? DisabledAttribute : string.Empty; 

     //page number 

     if (displayErrors) 
     { 
      foreach (KeyValuePair<string, ModelState> entry in StepModelState[(int)stepToDisplay]) 
      { 
       ViewData.ModelState.Add(entry.Key, entry.Value); 
      } 
     } 
    } 


} 

当我将鼠标悬停在Viewbag我得到的通常的智能感知弹出,并徘徊标题解释了正常“在运行时进行评估”。

有没有人遇到过这个问题?我查看了其他问题,但他们都有代码拼写错误或真正的错误。我知道这不是一个组装参考问题,否则Intellisense不会知道Viewbag是什么。

UPDATE

它看起来像智能感知是否有问题特别动态分配。普通服务器代码不会遇到上述问题,而像Viewbag分配或指定@ {//此处代码}中的布局似乎已破坏。另请注意,这只发生在我的一个.cshtml文件中,而其他文件不受影响。

UPDATE 2 这是测试视图的结果。源文件是ASP.NET临时文件中生成的代码文件。

Compiler Error Message: CS1513: } expected 

Source Error: 

Line 259:   #line default 
Line 260:   #line hidden 
Line 261:WriteLiteral("\r\n"); 
Line 262: 

这是与上述错误在编译的临时文件中的代码:

WriteLiteral(" value=\"Finish\""); 

WriteLiteral(" /> \r\n"); 


    #line 46 "F:....Create.cshtml" 

} <-- see the brace!? It's right there so why does the compiler freak out? 

    #line default 
    #line hidden 
WriteLiteral("\r\n");    
+1

代码是否执行? – 2013-05-07 17:18:17

+2

您是否保存,关闭并重新打开文件?有时intellisense失去了它的名字的聪明部分。 – Tommy 2013-05-07 17:21:10

+0

尝试仅删除一次花括号,然后说@ ViewBag.Title =“Page”;看看它是否还能给出那种红色的波浪曲线? – Nirman 2013-05-07 19:02:42

回答

0

我不知道,你可以不写正常的C#代码到剃刀意见。

+1

不确定你的意思。你不能声明方法或类,因为视图基本上是一种方法。这就像试图在另一种方法中声明一种方法或类,这是不合法的。所以,这是“正常”的C#代码,但你必须考虑它的运行环境。如果您需要方法,您必须更改视图继承的类,然后将其作为单独的文件执行。 – 2013-05-09 18:17:12

+0

在发表这篇文章之前,我对剃刀视图语法的理解是,我可以编写任何服务器代码,只要它在{@}块中声明。并非如此。 – AutoGibbon 2013-05-09 18:55:11

0

你需要这样的:

@switch (StepToDisplay) 

它看到闸刀开关括号截至收盘到你之前的那个。您甚至可能需要将开关放在一个剃须刀代码块中@{ switch(){} }

另外,如果您使用的是ReSharper,它会突出显示它的实际代码块,并且您会看到Razor在想什么该块的结束将是。

编辑:

它应该是这样的:

@using (Html.BeginForm()) 
{ 
    // remove the @ from before the Html on this line 
    Html.Hidden("CurrentStep", StepToDisplay.ToString(), new { id="CurrentStep"}) 
    // This html causes razor to switch back to "html mode" 
    <input id="AddressButton" type="submit" name="@Button.Step1Button.ToString()"... 

    ... 

    // Add an @ here, because razor is now in Html mode 
    @switch (StepToDisplay) 
    { 
     ... 
    } 

    // Back in html mode again, so we need @'s 
    <input id="BackButton" type="submit" name="@Button.BackButton.ToString()"... 
    ... 
} 
+0

在'switch'语句之前添加'@'会得到以下结果:'@“字符后出现'Unexpected'开关'关键字。一旦进入内部代码,你就不需要在“@”前面加上“switch”这样的结构。' – AutoGibbon 2013-05-09 15:18:37

+0

@AutoGibbon - 问题在于它由于之前的html而切换回HTML模式。在第一个大括号后面的第一行不应该有'@ Html'。 – 2013-05-09 15:22:33

+0

做你的建议仍然会导致'意外的“开关”...“编译错误。它清楚地表明这不是必需的。在附注中 - 将生成的代码从临时asp.net文件放入VS2012编辑器中,可以看出生成的代码具有OP所示的错误。 – AutoGibbon 2013-05-09 16:09:20