On this page

Skip to content

How to use Vue with ASP.NET Razor

TLDR

  • For integrating Vue 2 into ASP.NET Razor Pages, it is recommended to initialize the Vue instance globally in _Layout.cshtml and use mixins to extend logic for individual pages.
  • To avoid "Flash of Uncompiled Content," always use the v-cloak directive combined with CSS settings.
  • <script> tags are prohibited within Vue templates, as they will trigger compilation errors.
  • When using Vue syntax in Razor Pages, if you encounter the @ symbol (e.g., @click), you must use @@ to escape it. Additionally, avoid using Vue's @ shorthand within Tag Helper attributes.
  • When handling Ajax requests, use axios interceptors to automatically inject the RequestVerificationToken to pass Antiforgery validation.
  • If you need to retain ASP.NET Model Validation, you can use a custom TagHelper to convert backend validation attributes into the HTML attributes required by VeeValidate.

Integration Architecture for Vue and Razor

The core concept of integrating Vue into ASP.NET Razor Pages is to combine Vue's lifecycle with the Razor page structure. It is recommended to place the initialization of the Vue instance in _Layout.cshtml and utilize Vue's mixins feature, allowing individual pages (.cshtml) to inject their own data and methods.

Implementation

  1. Define a global mixins array in _Layout.cshtml.
  2. Pages push their specific pageMixin into the mixins array via @section Scripts.
  3. Finally, execute new Vue({ el: '#vueApp', mixins: mixins }) at the bottom of _Layout.cshtml.

Avoiding Flash of Uncompiled Content

When does this occur: During the initial page load, before the browser has parsed the Vue template, causing the user to see raw syntax.

  • Solution: Add v-cloak to the root element and set [v-cloak] { display: none; } in your CSS.

Integration Notes

Template Limitations

When does this occur: Writing <script> tags directly within the DOM scope rendered by Vue.

  • Pitfall: Vue templates are only responsible for UI mapping and do not allow tags with side effects.
  • Recommended practice: Move all JavaScript logic to the @section Scripts block.

Razor and Vue Syntax Conflicts

When does this occur: Using Vue's @ shorthand (e.g., @click) in Razor Pages.

  • Analysis: @ is a reserved character in Razor, and Tag Helper attributes have strict limitations on special characters.
  • Recommended practice:
    • Use @@click to escape for standard HTML attributes.
    • If the element contains Tag Helpers like asp-for, avoid the @ shorthand and use v-on:click instead to ensure correct compilation.

Alternatives to jQuery

Ajax and Security

When does this occur: Sending a POST request using axios results in a 400 Bad Request due to a missing RequestVerificationToken.

  • Recommended practice: Intercept requests in axios interceptors and read the token from the hidden field on the page to add it to the header:
javascript
axios.interceptors.request.use(
    config => {
        let token = document.querySelector('input[name="__RequestVerificationToken"]');
        if (token !== null) {
            config.headers = {
                RequestVerificationToken: token.value
            }
        }
        return config;
    },
    error => {
        return Promise.reject(error);
    }
);

Frontend Validation Integration

When does this occur: You want to retain ASP.NET Validation Attributes (e.g., [Required]) while using VeeValidate for real-time validation on the frontend.

  • Recommended practice: Create a custom TagHelper to automatically convert backend Model validation rules into v-validate attributes.

VeeValidationInputTagHelper Example: This TagHelper automatically reads the asp-for Metadata and generates the corresponding v-validate rules.

csharp
// Simplified logic to convert backend Attribute to VeeValidate rules
if (For.Metadata.ValidatorMetadata.Any(x => x is RequiredAttribute)) {
    output.Attributes.Add("v-validate", "'required'");
}

VeeValidationMessageTagHelper Example: Used to display error messages:

csharp
public override void Process(TagHelperContext context, TagHelperOutput output) {
    output.Attributes.Add("v-show", $"errors.has('{For.Name}')");
    output.Content.SetHtmlContent($"{{{{ errors.first('{For.Name}') }}}}");
}

Change Log

  • 2022-10-24 Initial documentation created.