ASP.NET MVC Razor <text> tag not accepting less than or equal to operators

Viewed 3115

I have a JavaScript if condition containing some comparison operators (<=, >=) inside a partial view. This JavaScript is surrounded by MVC the Razor <text> tags.

With this, my JS is dynamically loading based on the Model properties. However if I have comparison operators in the JavaScript method, it is throwing an error.

Working scenario:

    @if (Model.SomeTrueCondition)
    {
        <text>
        function JSMethod() {
            AnotherJSMethod();
            return;
        }
        </text>
    }  

Not working scenario (if I call the AnotherJSMethod() using comparison operators)

    @if (Model.SomeTrueCondition)
    {
        <text>
        function JSMethod() {
            // This if condition containing comparison operators are not being accepted!
            if ($('#aTextBox').val().length <= 0 || $('#bTextBox').val().length <= 0) {
                AnotherJSMethod();
                return;
            }
        }
        </text>
    }

I tried moving this JS method in another .js file and tried embedding the below way but I still see the same issues.

@section JavaScriptIncludes
{
   <script type="text/javascript" src="@Url.Content("/Scripts/SomeScript.js")" />
}

Getting below 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: End of file or an unexpected character was reached before the "" tag could be parsed. Elements inside markup blocks must be complete. They must either be self-closing ("<br />") or have matching end tags ("<p>Hello&lt/p>"). If you intended to display a "<" character, use the "<" HTML entity.

enter image description here

Pl. can someone tell me what am I missing here!

Feel free to correct the question/content/tags in order to reach out to right people.

4 Answers

As a workaround, you can use @Html.Raw("<=") instead of <=.

I just add this comment //> after loop block and worked for me :)

like this:

for(let i =0;i<=10;i++){//>//in some where it was working
//your code here
}//>//in some where it was working 

Workaround Options

  1. Avoid JS in Razor views altogether, and use external JS files. The @section in the question seems unnecessary. You can conditionally render scripts without it.

    I think this is the best long-term solution, since:

    • this makes your JS unobtrusive
    • you can't breakpoint JS code in a Razor view from Visual Studio, and using debugger leads to messy code.
  2. For array and string lengths, there is no need to use <= 0. Just use === 0 to check for empty.

  3. Invert your conditional directions. (Change <= to >=).

    • Pros: Fewest extra characters inserted, no warnings, least hacky.
    • Cons: Does not preserve Left-Right, which can affect readability.
  4. Append || 0>0 (|| false) to the end of your expression. I chose this Identity Law because then we don't have to worry about operator precedence. || is at the very bottom of the standard Boolean operators, and those are all below the comparison operators. You still have to watch out if you have comments between your conditionals, though.

    • Pros: Concise, preserves Left-Right, doesn't use helper function, pure JS, no warnings.
    • Cons: Looks hacky. May still have errors (see next section on how this bug works)
  5. Exclusively use @**@ Razor comments in views. This prevents comments from showing up in your final code, though.

  6. (Don't do this.) Use the @Html.Raw("<=") helper function as stated in the other answer. Despite the fact that it generates valid code in the end, it uses a Razor helper for something that should be pure JS and messes with Intellisense. Using this completely disables Intellisense for the same line, so if you have a JS syntax error, it will not warn you. (I believe in older versions of the Razor editor, it raised false warnings, but I can no longer verify this.)

Bug Behavior Information

So I did some research on how this bug works.

It occurs when all of the following conditions are met:

  • There is a <= (less than or equals) operator in the JS. It must think the = is part of a tag name or something.
    • <, <<, >, and >= do not cause problems.
  • Script is in a <text></text> context
  • There is a JS comment (line or block) somewhere between the <= and the closing </text> tag. Razor comments are ok. Exceptions are:
    • There is a > operator or template string literal (e.g. `>`) before the offending comment.
    • It cannot be in a normal string literal.

Examples

(All these are in <text> tags.)

1<=0;
// Line comments no good
/* Block comments also no good */
@* No problems with Razor comment *@
// No problem:
if (0 <= 1){}
0>0;
// Hello
if (0 <= 1){}
// Some comment here
0>0;
// No good :(

You can avoid using the <text> block that seems to cause the issue by converting your condition to JS. For example:

var condition = @Model.SomeTrueCondition.ToString().ToLower();
if (condition) {
    function JSMethod() {
        // This statement is no longer a problem if it's not in <text></text>
        if ($('#aTextBox').val().length <= 0 || $('#bTextBox').val().length <= 0) {
            AnotherJSMethod();
            return;
        }
    }
}
Related