Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Razor View Engine Quirks in VB.NET

I just downloaded the MVC 3.0 RC and I'm excited to start using it, especially the Razor view engine. However, due to a few stick in the mud type people here, we are stuck using VB.NET instead of C#.

When I started trying it out, I noticed some quirks. If you are creating a Razor view using CSHTML, you can write code like this:

@foreach(string genreName in Model.Genres)
{
    <li>@genreName</li>
}

Razor will automatically detect that the <li> text is an HTML tag and will switch out of "code mode". With a VB.NET VBHTML file, this doesn't seem to be working. It's making me put the @: keyword in front of each line like this:

@For Each genreName As String In Model.Genres
    @:<li>@genreName</li>
Next

If I don't have it there, I get a runtime error. Also, the <text></text> tags don't seem to work.

Anybody know what's going on here or whether there's a workaround?

like image 508
Shea Daniels Avatar asked Nov 12 '10 21:11

Shea Daniels


People also ask

Which namespace is used for Razor view?

The namespace for Razor Engine is System. The Razor file extension is "cshtml" for the C# language. By default, Razor View Engine encodes html tags or scripts before it's being rendered to view that avoids Cross-Site Scripting attacks.

Is Cshtml a Razor?

cshtml files are razorpages or MVC views, they does not contain any C#-written client-side code. If you wan to do so, you must use JavaScript. However, a . razor file, also know as a Razor component, can have C# written in it and run on client's browser.

What is the difference between MVC and Razor?

A Razor Page is almost the same as ASP.NET MVC's view component. It has basically the syntax and functionality same as MVC. The basic difference between Razor pages and MVC is that the model and controller code is also added within the Razor Page itself. You do not need to add code separately.


4 Answers

I would say the reason it's required in Vb.net is vb allows xml elements inline whereas c# does not.

Dim xmlMarkup = <someElement>Values</span> 

Because of this the natural parser for vb must behave differently than c# so you have to tell the parser to escape back to html by using the @. You can use @ and @:.

like image 112
Buildstarted Avatar answered Sep 20 '22 16:09

Buildstarted


As previously mentioned in comments, but not explicitly shown; prepending the text tag with @ solves the issue:

@For Each genreName As String In Model.Genres
    @<text>
        <li>@genreName</li>
    </text>
Next
like image 40
Jonathan Avatar answered Sep 23 '22 16:09

Jonathan


I just tried this in ASP.NET MVC 3 RC in a VBHTML view and it seems to work fine:

<ul>
@For Each i As Integer In Enumerable.Range(0, 5)
    @:<li>@i</li>
Next
</ul>

It renders this markup:

<ul>
    <li>0</li>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
like image 20
Eilon Avatar answered Sep 23 '22 16:09

Eilon


This doesn't use the same code as the OP but I was converting some C# code from an MVC book into VB.NET and got stuck with mixing inline HTML and VB code. This is the original C#:

@using (Html.BeginForm()) {
    @Html.ValidationSummary()
        <p>Your name: @Html.TextBoxFor(x => x.Name, new { @class = "form-control" }) </p>
        <p>Your email: @Html.TextBoxFor(x => x.Email, new { @class = "form-control" }) </p>
        <p>Your phone: @Html.TextBoxFor(x => x.Phone, new { @class = "form-control" }) </p>
        <p>Will you attend?
        @Html.DropDownListFor(x => x.WillAttend, new[] {
                new SelectListItem() {Text = "Yes, I'll be there",
                    Value = bool.TrueString},
                new SelectListItem() {Text = "No, I can't come",
                    Value = bool.FalseString}
            }, "Choose an option", new { @class = "form-control" })
        </p>
}

and these are the different ways of representing it in VB:

@Using Html.BeginForm()
    @:<p>Your name: @Html.TextBoxFor(Function(x) x.Name)</p>
    @:<p>Your email: @Html.TextBoxFor(Function(x) x.Email)</p>
    @:<p>Your phone: @Html.TextBoxFor(Function(x) x.Phone)</p>
    @:<p>Will you attend?
    @Html.DropDownListFor(Function(x) x.WillAttend, New SelectListItem() {New SelectListItem() With {.Text = "Yes", .Value = Boolean.TrueString}, New SelectListItem() With {.Text = "No", .Value = Boolean.FalseString}})
    @:</p>
End Using

@Using Html.BeginForm()
    @<text>
        <p>Your name: @Html.TextBoxFor(Function(x) x.Name)</p>
        <p>Your email: @Html.TextBoxFor(Function(x) x.Email)</p>
        <p>Your phone: @Html.TextBoxFor(Function(x) x.Phone)</p>
        <p>Will you attend?
        @Html.DropDownListFor(Function(x) x.WillAttend, New SelectListItem() {New SelectListItem() With {.Text = "Yes", .Value = Boolean.TrueString}, New SelectListItem() With {.Text = "No", .Value = Boolean.FalseString}})
        </p>
    </text>
End Using

@code
    Using Html.BeginForm()
        @:<p>Your name: @Html.TextBoxFor(Function(x) x.Name)</p>
        @:<p>Your email: @Html.TextBoxFor(Function(x) x.Email)</p>
        @:<p>Your phone: @Html.TextBoxFor(Function(x) x.Phone)</p>
        @:<p>Will you attend?
        @Html.DropDownListFor(Function(x) x.WillAttend, New SelectListItem() {New SelectListItem() With {.Text = "Yes", .Value = Boolean.TrueString}, New SelectListItem() With {.Text = "No", .Value = Boolean.FalseString}})
        @:</p>
    End Using
End Code

@code    
    Using Html.BeginForm()
        @<text>
            <p>Your name: @Html.TextBoxFor(Function(x) x.Name)</p>
            <p>Your email: @Html.TextBoxFor(Function(x) x.Email)</p>
            <p>Your phone: @Html.TextBoxFor(Function(x) x.Phone)</p>
            <p>Will you attend?
            @Html.DropDownListFor(Function(x) x.WillAttend, New SelectListItem() {New SelectListItem() With {.Text = "Yes", .Value = Boolean.TrueString}, New SelectListItem() With {.Text = "No", .Value = Boolean.FalseString}})
            </p>
        </text>
    End Using
End Code

What should be obvious from this is that when you need to include inline HTML within a code block you need to either prefix each line with a @: or enclose the HTML with an @<text></text> block. It's also obvious that this applies when you are using @Code ... End Code instead of starting a block of code with @.

p.s. Note that the @<text></text> tags are not output to the page so they won't interfere with anything

like image 26
Carl Onager Avatar answered Sep 23 '22 16:09

Carl Onager