Leonel Sanches da Silva
Leonel Sanches da Silva

Reputation: 7230

Switch statement inside Razor CSHTML

I'm developing a project in ASP.NET MVC4, Twitter.Bootstap 3.0.0 and Razor. In a View, I need to display buttons depending of a property value. Using the switch statement, the example below doesn't work (nothing is displayed):

@switch (Model.CurrentStage) { 
    case Enums.Stage.ReadyToStart:
        Html.ActionLink(Language.Start, "Start", new { id=Model.ProcessId }, new { @class = "btn btn-success" });
        break;
    case Enums.Stage.Flour:
        Html.ActionLink(Language.GoToFlour, "Details", "Flours", new { id=Model.Flour.FlourId }, new { @class = "btn btn-success" });
        break;
    ...
}

Changing a bit, using a <span> tag, the code works:

@switch (Model.CurrentStage) { 
    case Enums.Stage.ReadyToStart:
        <span>@Html.ActionLink(Language.Start, "Start", new { id=Model.ProcessId }, new { @class = "btn btn-success" })</span>
        break;
    case Enums.Stage.Flour:
        <span>@Html.ActionLink(Language.GoToFlour, "Details", "Flours", new { id=Model.Flour.FlourId }, new { @class = "btn btn-success" })</span>
        break;
    ...
}

Can someone explain why?

Thanks.

Upvotes: 20

Views: 37443

Answers (1)

Joe Enos
Joe Enos

Reputation: 40413

It's the funkiness of Razor. When you're in normal HTML and use C# code, putting something with an @ symbol on it will write the result to the page:

<p>@Html.ActionLink("whatever", "whatever"...)</p>

This is similar to the old-school <%= %>.

<p><%= SomeMethodThatReturnsSomethingThatWillBeWritten() %></p>

However, the Html.ActionLink method simply returns an MvcHtmlString object in the .NET world. In your first example, you've got a regular C# code block. So calling Html.ActionLink() from there simply executes it and returns the MvcHtmlString to nobody. In your second example, you've jumped back into the HTML context, so it writes the HTML again.

You can use the special <text> block to get back to HTML instead of using <span> or other real HTML, and it will write directly without writing the extra HTML:

case Enums.Stage.ReadyToStart:
    <text>@Html.ActionLink(Language.Start, "Start", new { id=Model.ProcessId }, new { @class = "btn btn-success" })</text>
    break;

You can also use the similar @: syntax:

case Enums.Stage.ReadyToStart:
    @:@Html.ActionLink(Language.Start, "Start", new { id=Model.ProcessId }, new { @class = "btn btn-success" })
    break;

You can read more about both here

EDIT

Actually, in this case, you don't need either one. You just need the @ symbol, which will be enough to get you back into the HTML:

case Enums.Stage.ReadyToStart:
    @Html.ActionLink(Language.Start, "Start", new { id=Model.ProcessId }, new { @class = "btn btn-success" })
    break;

Upvotes: 27

Related Questions