Handling large datasets in web applications has always been a challenge. Traditional approaches like server-side paging can sometimes feel clunky and interrupt the user experience. The Blazor Virtualization component enhances performance and responsiveness by rendering only visible elements, which significantly reduces memory and processing overhead. This article dives into the workings of the Blazor Virtualization component compared to traditional paging through practical code examples.
Blazor and the Virtualization Component
Blazor is a .NET web UI framework for building rich, interactive web applications using my favorite language, C#. Blazor empowers developers to create efficient Single Page Applications (SPAs). One of its most impressive features is the Virtualization component, because it optimizes the rendering of large data sets. Rather than loading and rendering all of the data items at once, Virtualization only displays the items currently visible to the user, dynamically adding or removing elements as the user scrolls.
Key Features
Performance optimization: Reduces DOM manipulation and rendering workload.
Responsive scrolling: Ensures smooth, fast navigation through large datasets.
Dynamic data handling: Supports filtering, searching, and sorting seamlessly.
Code Example: API-Driven Table with Filtering and Paging (without Virtualization)
This Blazor component fetches user data from a public API (https://randomuser.me/api) and displays it in a paginated and searchable table.
Key Features
Loading data dynamically from an API.
Searching through the dataset by user name or email.
Paginating the results, showing a fixed number of records per page.
Pros
Paging is a familiar navigation pattern.
Efficient for smaller datasets.
Cons
Requires user interaction for navigation (clicking Next).
Not suitable for very large datasets due to potential performance bottlenecks.
// Paginate - Next private void NextPage() { if (CanGoNext) { currentPage++; LoadPageData(); } }
// Models private class Person { public int Id { get; set; } public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; }
private class RandomUserApiResponse { public List<ApiUser> Results { get; set; } = new(); }
private class ApiUser { public Name Name { get; set; } = new(); public string Email { get; set; } = string.Empty; }
private class Name { public string First { get; set; } = string.Empty; public string Last { get; set; } = string.Empty; } }
Explanation
Initialization: OnInitializedAsync()
Fetches data from the API.
Initializes filteredPeople (the filtered dataset) and loads the first page.
2. Data Fetching: FetchDataFromApi()
Calls the API to get user data and maps it to a Person object with properties like Id, FirstName, LastName, and Email.
Handles errors by populating errorMessage if the request fails.
3. Filtering: FilterPeople()
Filters people based on the searchTerm input.
Resets the current page to the first page (currentPage = 1) after applying the filter.
4. Pagination: LoadPageData()
Calculates the data for the current page using Skip and Take LINQ methods.
5. PreviousPage and NextPage
Navigate to the previous or next page if navigation is allowed.
6. Search Event: OnSearchTermChanged()
Triggered whenever the search input changes.
Updates searchTerm and re-applies filtering.
Code Example: Virtualized Filterable Table with Scrolling
This example a filterable virtual list for displaying data fetched from an API. The main features include API integration, a virtualized list for efficient rendering of large datasets, and a live search filter.
Key Features and Workflow
1. Component Initialization
The component initializes with OnInitializedAsync, which asynchronously loads user data from an external API (https://randomuser.me/api/) using the LoadUsersAsync method.
2. Loading and Error Handling
During the loading process, a placeholder is displayed (Loading...).
If an error occurs, such as a failed API request, an error message is displayed (Error: Unable to fetch users...).
3. Search Functionality
Users can filter the displayed data by typing in a search box. The @bind="searchTerm" directive binds the search term to the searchTerm property.
The @oninput="OnSearchTermChanged" event triggers the FilterUsers method to update the filtered dataset.
4. Virtualized Rendering
The <Virtualize> component efficiently renders only the visible rows in the list. This is crucial for performance when dealing with large datasets.
Items: Binds to filteredUsers, the filtered dataset.
ItemContent: Template for rendering individual items.
EmptyContent: Fallback content displayed when no users match the search criteria.
5. Data Fetching and Transformation
Data Fetching: The API call retrieves 100 random user records.
Transformation: The raw API response is mapped to a Person object containing Id, FirstName, LastName, and Email.
Pros
Significantly reduces memory and rendering load, ideal for large datasets.
Provides a smoother, more modern user experience with continuous scrolling.
Cons
Slightly more complex to implement and debug.
Initial setup for Virtualize may require additional configuration for optimal performance.
// Fetch private async Task LoadUsersAsync() { try { users = null; // Start with null for loading state errorMessage = string.Empty; // Clear any previous errors
// api call using var httpClient = new HttpClient(); var response = await httpClient.GetAsync("https://randomuser.me/api/?results=100");
// results if (response.IsSuccessStatusCode) { var apiResponse = await response.Content.ReadFromJsonAsync<RandomUserApiResponse>(); if (apiResponse?.Results != null) { // Map API data to Person objects users = apiResponse.Results.Select((user, index) => new Person { Id = index + 1, FirstName = user.Name.First, LastName = user.Name.Last, Email = user.Email }).ToList(); } } else { errorMessage = $"Error: Unable to fetch users. (Status Code: {response.StatusCode})"; }
// Models private class Person { public int Id { get; set; } public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; } private class ApiUser { public Name Name { get; set; } = new(); public string Email { get; set; } = string.Empty; } private class UserApiResponse { public List<ApiUser> Results { get; set; } = new(); } private class Name { public string First { get; set; } = string.Empty; public string Last { get; set; } = string.Empty; } private class RandomUserApiResponse { public List<ApiUser> Results { get; set; } = new(); } }
Virtualization Component
Data Source
The Items="filteredUsers" attribute specifies the collection to be virtualized. Only the visible rows (and a small buffer of rows above and below) from filteredUsers will be rendered at any given time.
2. Item Size
The ItemSize="80" attribute indicates the estimated height (in pixels) of each item in the list. This value is used to calculate which items are currently visible within the scrollable area and to manage the placeholders (spacers) for non-rendered items.
3. Context
The Context="user" attribute provides a variable (user) representing each item in the collection when it is rendered within the ItemContent block.
4. Content Templates
ItemContent: Defines how each item in the collection is rendered. For example, each user in filteredUsers will render as a <tr> with the user’s details (Id, FirstName, LastName, and Email).
EmptyContent: Specifies the content to display if the filteredUsers collection is empty. In this case, a <tr> with a message “No users available” spanning all columns.
5. Spacer Element
The SpacerElement="tr" attribute ensures that the placeholders for items outside the visible range are rendered as <tr> elements to maintain the structure of the <table>.
6. OverscanCount
The OverscanCount property in the <Virtualize> component specifies the number of additional items to render before and after the visible set, improving smooth scrolling by preloading nearby items. Setting it to 3 means three items above and below the current viewport will be rendered, reducing lag during fast scrolling.
How It Works
Dynamic Rendering
Instead of rendering all rows in filteredUsers, the <Virtualize> component calculates the visible range of rows based on the size of the viewport and ItemSize.
Only these visible rows are rendered as <tr> elements in the DOM, significantly improving performance for large datasets.
2. Scrolling Behavior
As the user scrolls through the table, the <Virtualize> component dynamically updates the rendered rows based on the new visible range.
Non-visible items are replaced by spacer elements (<tr>), maintaining the table’s scrollable height and structure without rendering unnecessary rows.
3. Performance Benefits
This approach reduces the number of DOM elements rendered at any given time, which improves the rendering speed and responsiveness of the UI, especially when filteredUsers contains thousands of items.
Use Case
If filteredUsers contains 10,000 users:
Initially, only enough rows to fill the visible viewport (e.g., 20 rows) are rendered.
As the user scrolls down, the next set of rows (e.g., rows 21–40) are rendered dynamically.
Rows outside the visible range are replaced with spacer <tr> elements.
This behavior is especially beneficial for large tables, as it prevents performance bottlenecks associated with rendering too many rows simultaneously.
Explanation
Initialization: OnInitializedAsync()
Fetches data from the API.
Initializes filteredPeople (the filtered dataset) and loads the first page.
2. Data Fetching: FetchDataFromApi()
Calls the API to get user data and maps it to a Person object with properties like Id, FirstName, LastName, and Email.
Handles errors by populating errorMessage if the request fails.
3. Filtering: FilterPeople()
Filters people based on the searchTerm input.
Resets the current page to the first page (currentPage = 1) after applying the filter.
The Blazor Virtualization component is a game-changer for applications dealing with extensive datasets. While traditional paging still has its use cases, Virtualization offers a performance-focused alternative that enhances responsiveness and user experience. By dynamically loading only the visible data, it ensures that modern web applications remain both fast and efficient, even with demanding data requirements. Whether you’re building a dashboard, a catalog, or any data-heavy interface, Blazor Virtualization is a tool worth mastering.
{"id":"2","mode":"button","open_style":"in_modal","currency_code":"USD","currency_symbol":"$","currency_type":"decimal","blank_flag_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":500,"top_media_type":"featured_image","featured_image_url":"https:\/\/robhutton.com\/wp-content\/uploads\/Screenshot-2025-02-19-163019-100x74.png","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":false,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"robhutton.com","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"robhutton.com","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for being a supporter!","payment_confirmation_title":"robhutton.com","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":"Voluntary nature: Tips are non-refundable and given voluntarily. No goods\/services in exchange: Tipping doesn\u2019t entitle the user to any product, service, or preferential treatment. Payment processing: Mention that payments are processed securely through a third-party provider. No liability: You aren\u2019t responsible for transaction failures, fraud, or technical issues.","terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
{"id":"4","mode":"text_link","open_style":"in_modal","currency_code":"USD","currency_symbol":"$","currency_type":"decimal","blank_flag_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":500,"top_media_type":"featured_image","featured_image_url":"https:\/\/robhutton.com\/wp-content\/uploads\/Screenshot-2025-02-19-163019-100x74.png","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Like my articles? Tips are appreciated.","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for being a supporter!","payment_confirmation_title":"","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":"Voluntary nature: Tips are non-refundable and given voluntarily. No goods\/services in exchange: Tipping doesn\u2019t entitle the user to any product, service, or preferential treatment. Payment processing: Mention that payments are processed securely through a third-party provider. No liability: You aren\u2019t responsible for transaction failures, fraud, or technical issues.","terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}