diff --git a/apps/demos/Demos/CardView/DataValidation/Angular/app/app.component.ts b/apps/demos/Demos/CardView/DataValidation/Angular/app/app.component.ts
index 4f6437f25f3f..f4b6c0b2f1c8 100644
--- a/apps/demos/Demos/CardView/DataValidation/Angular/app/app.component.ts
+++ b/apps/demos/Demos/CardView/DataValidation/Angular/app/app.component.ts
@@ -4,6 +4,7 @@ import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/
import { DxCardViewModule, DxTextAreaModule } from 'devextreme-angular';
import { lastValueFrom } from 'rxjs';
import { Employee, Service } from './app.service';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/CardView/DataValidation/React/index.tsx b/apps/demos/Demos/CardView/DataValidation/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/CardView/DataValidation/React/index.tsx
+++ b/apps/demos/Demos/CardView/DataValidation/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/CardView/DataValidation/ReactJs/index.js b/apps/demos/Demos/CardView/DataValidation/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/CardView/DataValidation/ReactJs/index.js
+++ b/apps/demos/Demos/CardView/DataValidation/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/CardView/DataValidation/Vue/index.ts b/apps/demos/Demos/CardView/DataValidation/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/CardView/DataValidation/Vue/index.ts
+++ b/apps/demos/Demos/CardView/DataValidation/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/CardView/DataValidation/jQuery/index.html b/apps/demos/Demos/CardView/DataValidation/jQuery/index.html
index ce1342832a60..9105d980d23e 100644
--- a/apps/demos/Demos/CardView/DataValidation/jQuery/index.html
+++ b/apps/demos/Demos/CardView/DataValidation/jQuery/index.html
@@ -8,6 +8,7 @@
+
diff --git a/apps/demos/Demos/CardView/WebAPIService/Angular/app/app.component.ts b/apps/demos/Demos/CardView/WebAPIService/Angular/app/app.component.ts
index ccdb0799aa75..94100f60355f 100644
--- a/apps/demos/Demos/CardView/WebAPIService/Angular/app/app.component.ts
+++ b/apps/demos/Demos/CardView/WebAPIService/Angular/app/app.component.ts
@@ -2,6 +2,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
import { DxCardViewModule, DxSelectBoxModule } from 'devextreme-angular';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/CardView/WebAPIService/React/index.tsx b/apps/demos/Demos/CardView/WebAPIService/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/CardView/WebAPIService/React/index.tsx
+++ b/apps/demos/Demos/CardView/WebAPIService/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/CardView/WebAPIService/ReactJs/index.js b/apps/demos/Demos/CardView/WebAPIService/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/CardView/WebAPIService/ReactJs/index.js
+++ b/apps/demos/Demos/CardView/WebAPIService/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/CardView/WebAPIService/Vue/index.ts b/apps/demos/Demos/CardView/WebAPIService/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/CardView/WebAPIService/Vue/index.ts
+++ b/apps/demos/Demos/CardView/WebAPIService/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/CardView/WebAPIService/jQuery/index.html b/apps/demos/Demos/CardView/WebAPIService/jQuery/index.html
index 718f0304cdef..6cece9ada40c 100644
--- a/apps/demos/Demos/CardView/WebAPIService/jQuery/index.html
+++ b/apps/demos/Demos/CardView/WebAPIService/jQuery/index.html
@@ -9,6 +9,7 @@
+
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.component.ts b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.component.ts
index b193fda9ee3d..8bfb43fa2382 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.component.ts
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.component.ts
@@ -1,17 +1,16 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
-import { HttpClient, provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
+import { HttpClient, provideHttpClient, withFetch } from '@angular/common/http';
import { lastValueFrom } from 'rxjs';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
import { DxDataGridComponent, DxDataGridModule, DxDataGridTypes } from 'devextreme-angular/ui/data-grid';
-import { antiForgeryInterceptor, AntiForgeryTokenService } from './app.service';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
}
-const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
-const URL = `${BASE_PATH}/api/DataGridBatchUpdateWebApi`;
+const URL = 'https://js.devexpress.com/Demos/NetCore/api/DataGridBatchUpdateWebApi';
let modulePrefix = '';
// @ts-ignore
@@ -30,16 +29,12 @@ if (window && window.config?.packageConfigPaths) {
export class AppComponent {
ordersStore: AspNetData.CustomStore;
- constructor(private http: HttpClient, private tokenService: AntiForgeryTokenService) {
+ constructor(private http: HttpClient) {
this.ordersStore = AspNetData.createStore({
key: 'OrderID',
loadUrl: `${URL}/Orders`,
- async onBeforeSend(_method, ajaxOptions) {
- const tokenData = await lastValueFrom(tokenService.getToken());
- ajaxOptions.xhrFields = {
- withCredentials: true,
- headers: { [tokenData.headerName]: tokenData.token },
- };
+ onBeforeSend(method, ajaxOptions) {
+ ajaxOptions.xhrFields = { withCredentials: true };
},
});
}
@@ -58,23 +53,16 @@ export class AppComponent {
changes: DxDataGridTypes.DataChange[],
component: DxDataGridComponent['instance'],
): Promise {
- try {
- await lastValueFrom(
- this.http.post(url, JSON.stringify(changes), {
- withCredentials: true,
- headers: {
- 'Content-Type': 'application/json',
- },
- }),
- );
- await component.refresh(true);
- component.cancelEditData();
- } catch (error: any) {
- const errorMessage = (typeof error?.error === 'string' && error.error)
- ? error.error
- : (error?.statusText || 'Unknown error');
- throw new Error(`Batch save failed: ${errorMessage}`);
- }
+ await lastValueFrom(
+ this.http.post(url, JSON.stringify(changes), {
+ withCredentials: true,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ }),
+ );
+ await component.refresh(true);
+ component.cancelEditData();
}
normalizeChanges(changes: DxDataGridTypes.DataChange[]): DxDataGridTypes.DataChange[] {
@@ -106,9 +94,6 @@ export class AppComponent {
bootstrapApplication(AppComponent, {
providers: [
provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }),
- provideHttpClient(
- withFetch(),
- withInterceptors([antiForgeryInterceptor]),
- ),
+ provideHttpClient(withFetch()),
],
});
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.service.ts b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.service.ts
deleted file mode 100644
index 185bed7e6c3d..000000000000
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Angular/app/app.service.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import { Injectable, inject } from '@angular/core';
-import { HttpClient, HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
-import { Observable, of, throwError } from 'rxjs';
-import { catchError, switchMap, map, shareReplay } from 'rxjs/operators';
-
-interface TokenData {
- headerName: string;
- token: string;
-}
-
-@Injectable({
- providedIn: 'root',
-})
-export class AntiForgeryTokenService {
- private BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
-
- private tokenCache$: Observable | null = null;
-
- constructor(private http: HttpClient) {}
-
- getToken(): Observable {
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
- const token = tokenMeta.getAttribute('content') || '';
- return of({ headerName, token });
- }
-
- if (!this.tokenCache$) {
- this.tokenCache$ = this.fetchToken().pipe(
- map((tokenData) => {
- this.storeTokenInMeta(tokenData);
- return tokenData;
- }),
- shareReplay({ bufferSize: 1, refCount: false }),
- catchError((error) => {
- this.tokenCache$ = null;
- return throwError(() => error);
- }),
- );
- }
-
- return this.tokenCache$;
- }
-
- private fetchToken(): Observable {
- return this.http.get(
- `${this.BASE_PATH}/api/Common/GetAntiForgeryToken`,
- {
- withCredentials: true,
- },
- ).pipe(
- catchError((error) => {
- const errorMessage = typeof error.error === 'string' ? error.error : (error.statusText || 'Unknown error');
- return throwError(() => new Error(`Failed to retrieve anti-forgery token: ${errorMessage}`));
- }),
- );
- }
-
- private storeTokenInMeta(tokenData: TokenData): void {
- const meta = document.createElement('meta');
- meta.name = 'csrf-token';
- meta.content = tokenData.token;
- meta.dataset.headerName = tokenData.headerName;
- document.head.appendChild(meta);
- }
-
- clearToken(): void {
- this.tokenCache$ = null;
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- tokenMeta.remove();
- }
- }
-}
-
-export const antiForgeryInterceptor: HttpInterceptorFn = (req, next) => {
- const tokenService = inject(AntiForgeryTokenService);
-
- if (req.method === 'GET' && req.url.includes('/GetAntiForgeryToken')) {
- return next(req);
- }
-
- if (req.method !== 'GET') {
- return tokenService.getToken().pipe(
- switchMap((tokenData) => {
- const clonedRequest = req.clone({
- setHeaders: {
- [tokenData.headerName]: tokenData.token,
- },
- });
- return next(clonedRequest);
- }),
- catchError((error: HttpErrorResponse) => {
- if (error.status === 401 || error.status === 403) {
- tokenService.clearToken();
- }
- return throwError(() => error);
- }),
- );
- }
-
- return next(req);
-};
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/App.tsx b/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/App.tsx
index 0cd9c8bf553e..0c7cbf6142f4 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/App.tsx
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/App.tsx
@@ -4,55 +4,13 @@ import type { DataGridRef, DataGridTypes } from 'devextreme-react/data-grid';
import { createStore } from 'devextreme-aspnet-data-nojquery';
import 'whatwg-fetch';
-const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
-const URL = `${BASE_PATH}/api/DataGridBatchUpdateWebApi`;
-
-async function fetchAntiForgeryToken(): Promise<{ headerName: string; token: string }> {
- try {
- const response = await fetch(`${BASE_PATH}/api/Common/GetAntiForgeryToken`, {
- method: 'GET',
- credentials: 'include',
- cache: 'no-cache',
- });
-
- if (!response.ok) {
- const errorMessage = await response.text();
- throw new Error(`Failed to retrieve anti-forgery token: ${errorMessage || response.statusText}`);
- }
-
- return await response.json();
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- throw new Error(errorMessage);
- }
-}
-
-async function getAntiForgeryTokenValue(): Promise<{ headerName: string; token: string }> {
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
- const token = tokenMeta.getAttribute('content') || '';
- return Promise.resolve({ headerName, token });
- }
-
- const tokenData = await fetchAntiForgeryToken();
- const meta = document.createElement('meta');
- meta.name = 'csrf-token';
- meta.content = tokenData.token;
- meta.dataset.headerName = tokenData.headerName;
- document.head.appendChild(meta);
- return tokenData;
-}
+const URL = 'https://js.devexpress.com/Demos/NetCore/api/DataGridBatchUpdateWebApi';
const ordersStore = createStore({
key: 'OrderID',
loadUrl: `${URL}/Orders`,
- async onBeforeSend(_method, ajaxOptions) {
- const tokenData = await getAntiForgeryTokenValue();
- ajaxOptions.xhrFields = {
- withCredentials: true,
- headers: { [tokenData.headerName]: tokenData.token },
- };
+ onBeforeSend: (method, ajaxOptions) => {
+ ajaxOptions.xhrFields = { withCredentials: true };
},
});
@@ -81,31 +39,25 @@ function normalizeChanges(changes: DataGridTypes.DataChange[]): DataGridTypes.Da
}) as DataGridTypes.DataChange[];
}
-async function sendBatchRequest(url: string, changes: DataGridTypes.DataChange[], headers: Record) {
- try {
- const response = await fetch(url, {
- method: 'POST',
- body: JSON.stringify(changes),
- headers: {
- 'Content-Type': 'application/json;charset=UTF-8',
- ...headers,
- },
- credentials: 'include',
- });
+async function sendBatchRequest(url: string, changes: DataGridTypes.DataChange[]) {
+ const result = await fetch(url, {
+ method: 'POST',
+ body: JSON.stringify(changes),
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8',
+ },
+ credentials: 'include',
+ });
- if (!response.ok) {
- const errorMessage = await response.text();
- throw new Error(`Batch save failed: ${errorMessage || response.statusText}`);
- }
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- throw new Error(errorMessage);
+ if (!result.ok) {
+ const json = await result.json();
+
+ throw json.Message;
}
}
async function processBatchRequest(url: string, changes: DataGridTypes.DataChange[], component: ReturnType) {
- const tokenData = await getAntiForgeryTokenValue();
- await sendBatchRequest(url, changes, { [tokenData.headerName]: tokenData.token });
+ await sendBatchRequest(url, changes);
await component.refresh(true);
component.cancelEditData();
}
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/index.tsx b/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/index.tsx
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/App.js b/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/App.js
index fcde2ae8ae4b..14c79c49f8e2 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/App.js
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/App.js
@@ -3,51 +3,12 @@ import DataGrid, { Column, Editing, Pager } from 'devextreme-react/data-grid';
import { createStore } from 'devextreme-aspnet-data-nojquery';
import 'whatwg-fetch';
-const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
-const URL = `${BASE_PATH}/api/DataGridBatchUpdateWebApi`;
-async function fetchAntiForgeryToken() {
- try {
- const response = await fetch(`${BASE_PATH}/api/Common/GetAntiForgeryToken`, {
- method: 'GET',
- credentials: 'include',
- cache: 'no-cache',
- });
- if (!response.ok) {
- const errorMessage = await response.text();
- throw new Error(
- `Failed to retrieve anti-forgery token: ${errorMessage || response.statusText}`,
- );
- }
- return await response.json();
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- throw new Error(errorMessage);
- }
-}
-async function getAntiForgeryTokenValue() {
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
- const token = tokenMeta.getAttribute('content') || '';
- return Promise.resolve({ headerName, token });
- }
- const tokenData = await fetchAntiForgeryToken();
- const meta = document.createElement('meta');
- meta.name = 'csrf-token';
- meta.content = tokenData.token;
- meta.dataset.headerName = tokenData.headerName;
- document.head.appendChild(meta);
- return tokenData;
-}
+const URL = 'https://js.devexpress.com/Demos/NetCore/api/DataGridBatchUpdateWebApi';
const ordersStore = createStore({
key: 'OrderID',
loadUrl: `${URL}/Orders`,
- async onBeforeSend(_method, ajaxOptions) {
- const tokenData = await getAntiForgeryTokenValue();
- ajaxOptions.xhrFields = {
- withCredentials: true,
- headers: { [tokenData.headerName]: tokenData.token },
- };
+ onBeforeSend: (method, ajaxOptions) => {
+ ajaxOptions.xhrFields = { withCredentials: true };
},
});
function normalizeChanges(changes) {
@@ -74,29 +35,22 @@ function normalizeChanges(changes) {
}
});
}
-async function sendBatchRequest(url, changes, headers) {
- try {
- const response = await fetch(url, {
- method: 'POST',
- body: JSON.stringify(changes),
- headers: {
- 'Content-Type': 'application/json;charset=UTF-8',
- ...headers,
- },
- credentials: 'include',
- });
- if (!response.ok) {
- const errorMessage = await response.text();
- throw new Error(`Batch save failed: ${errorMessage || response.statusText}`);
- }
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- throw new Error(errorMessage);
+async function sendBatchRequest(url, changes) {
+ const result = await fetch(url, {
+ method: 'POST',
+ body: JSON.stringify(changes),
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8',
+ },
+ credentials: 'include',
+ });
+ if (!result.ok) {
+ const json = await result.json();
+ throw json.Message;
}
}
async function processBatchRequest(url, changes, component) {
- const tokenData = await getAntiForgeryTokenValue();
- await sendBatchRequest(url, changes, { [tokenData.headerName]: tokenData.token });
+ await sendBatchRequest(url, changes);
await component.refresh(true);
component.cancelEditData();
}
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/index.js b/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/index.js
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/App.vue b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/App.vue
index a3aa421c640d..39ad192b13bd 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/App.vue
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/App.vue
@@ -36,55 +36,13 @@ import {
import { createStore } from 'devextreme-aspnet-data-nojquery';
import 'whatwg-fetch';
-const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
-const URL = `${BASE_PATH}/api/DataGridBatchUpdateWebApi`;
-
-async function fetchAntiForgeryToken(): Promise<{ headerName: string; token: string }> {
- try {
- const response = await fetch(`${BASE_PATH}/api/Common/GetAntiForgeryToken`, {
- method: 'GET',
- credentials: 'include',
- cache: 'no-cache',
- });
-
- if (!response.ok) {
- const errorMessage = await response.text();
- throw new Error(`Failed to retrieve anti-forgery token: ${errorMessage || response.statusText}`);
- }
-
- return await response.json();
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- throw new Error(errorMessage);
- }
-}
-
-async function getAntiForgeryTokenValue(): Promise<{ headerName: string; token: string }> {
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
- const token = tokenMeta.getAttribute('content') || '';
- return Promise.resolve({ headerName, token });
- }
-
- const tokenData = await fetchAntiForgeryToken();
- const meta = document.createElement('meta');
- meta.name = 'csrf-token';
- meta.content = tokenData.token;
- meta.dataset.headerName = tokenData.headerName;
- document.head.appendChild(meta);
- return tokenData;
-}
+const URL = 'https://js.devexpress.com/Demos/NetCore/api/DataGridBatchUpdateWebApi';
const ordersStore = createStore({
key: 'OrderID',
loadUrl: `${URL}/Orders`,
- async onBeforeSend(_method, ajaxOptions) {
- const tokenData = await getAntiForgeryTokenValue();
- ajaxOptions.xhrFields = {
- withCredentials: true,
- headers: { [tokenData.headerName]: tokenData.token },
- };
+ onBeforeSend: (method, ajaxOptions) => {
+ ajaxOptions.xhrFields = { withCredentials: true };
},
});
@@ -125,36 +83,26 @@ function normalizeChanges(changes: DxDataGridTypes.DataChange[]): DxDataGridType
async function processBatchRequest(
url: string, changes: DxDataGridTypes.DataChange[], component: DxDataGrid['instance'],
) {
- const tokenData = await getAntiForgeryTokenValue();
- await sendBatchRequest(url, changes, { [tokenData.headerName]: tokenData.token });
+ await sendBatchRequest(url, changes);
await component?.refresh(true);
component?.cancelEditData();
}
-async function sendBatchRequest(
- url: string,
- changes: DxDataGridTypes.DataChange[],
- headers: Record,
-) {
- try {
- const response = await fetch(url, {
- method: 'POST',
- body: JSON.stringify(changes),
- headers: {
- 'Content-Type': 'application/json;charset=UTF-8',
- ...headers,
- },
- credentials: 'include',
- });
+async function sendBatchRequest(url: string, changes: DxDataGridTypes.DataChange[]) {
+ const result = await fetch(url, {
+ method: 'POST',
+ body: JSON.stringify(changes),
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8',
+ },
+ credentials: 'include',
+ });
- if (!response.ok) {
- const errorMessage = await response.text();
- throw new Error(`Batch save failed: ${errorMessage || response.statusText}`);
- }
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- throw new Error(errorMessage);
+ if (!result.ok) {
+ const json = await result.json();
+
+ throw json.Message;
}
}
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/index.ts b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/index.ts
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.html b/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.html
index 5bfc9fb29a7c..b24fac16100e 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.html
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.html
@@ -10,6 +10,7 @@
+
diff --git a/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.js b/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.js
index cfb60d3753c4..b90aee3dfb31 100644
--- a/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.js
+++ b/apps/demos/Demos/DataGrid/BatchUpdateRequest/jQuery/index.js
@@ -1,51 +1,12 @@
$(() => {
- const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
- const URL = `${BASE_PATH}/api/DataGridBatchUpdateWebApi`;
-
- function fetchAntiForgeryToken() {
- const d = $.Deferred();
- $.ajax({
- url: `${BASE_PATH}/api/Common/GetAntiForgeryToken`,
- method: 'GET',
- xhrFields: { withCredentials: true },
- cache: false,
- }).done((data) => {
- d.resolve(data);
- }).fail((xhr) => {
- const error = xhr.responseJSON?.message || xhr.statusText || 'Unknown error';
- d.reject(new Error(`Failed to retrieve anti-forgery token: ${error}`));
- });
- return d.promise();
- }
-
- function getAntiForgeryTokenValue() {
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
- const token = tokenMeta.getAttribute('content');
- return $.Deferred().resolve({ headerName, token });
- }
-
- return fetchAntiForgeryToken().then((tokenData) => {
- const meta = document.createElement('meta');
- meta.name = 'csrf-token';
- meta.content = tokenData.token;
- meta.dataset.headerName = tokenData.headerName;
- document.head.appendChild(meta);
- return tokenData;
- });
- }
+ const URL = 'https://js.devexpress.com/Demos/NetCore/api/DataGridBatchUpdateWebApi';
$('#gridContainer').dxDataGrid({
dataSource: DevExpress.data.AspNet.createStore({
key: 'OrderID',
loadUrl: `${URL}/Orders`,
- async onBeforeSend(_, ajaxOptions) {
- const tokenData = await getAntiForgeryTokenValue();
- ajaxOptions.xhrFields = {
- withCredentials: true,
- headers: { [tokenData.headerName]: tokenData.token },
- };
+ onBeforeSend(method, ajaxOptions) {
+ ajaxOptions.xhrFields = { withCredentials: true };
},
}),
pager: {
@@ -65,11 +26,11 @@ $(() => {
if (e.changes.length) {
const changes = normalizeChanges(e.changes);
- e.promise = getAntiForgeryTokenValue().then((tokenData) => sendBatchRequest(`${URL}/Batch`, changes, { [tokenData.headerName]: tokenData.token }))
- .then(() => e.component.refresh(true))
- .then(() => {
+ e.promise = sendBatchRequest(`${URL}/Batch`, changes).done(() => {
+ e.component.refresh(true).done(() => {
e.component.cancelEditData();
});
+ });
}
},
columns: [{
@@ -116,19 +77,17 @@ $(() => {
});
}
- function sendBatchRequest(url, changes, headers) {
+ function sendBatchRequest(url, changes) {
const d = $.Deferred();
$.ajax(url, {
method: 'POST',
data: JSON.stringify(changes),
- headers,
- xhrFields: { withCredentials: true },
cache: false,
contentType: 'application/json',
+ xhrFields: { withCredentials: true },
}).done(d.resolve).fail((xhr) => {
- const errorMessage = xhr.responseText || xhr.statusText || 'Unknown error';
- d.reject(new Error(`Batch save failed: ${errorMessage}`));
+ d.reject(xhr.responseJSON ? xhr.responseJSON.Message : xhr.statusText);
});
return d.promise();
diff --git a/apps/demos/Demos/DataGrid/CollaborativeEditing/Angular/app/app.service.ts b/apps/demos/Demos/DataGrid/CollaborativeEditing/Angular/app/app.service.ts
index 9487ae16132e..fdeee4340dca 100644
--- a/apps/demos/Demos/DataGrid/CollaborativeEditing/Angular/app/app.service.ts
+++ b/apps/demos/Demos/DataGrid/CollaborativeEditing/Angular/app/app.service.ts
@@ -3,6 +3,7 @@ import { HubConnectionBuilder, HttpTransportType } from '@aspnet/signalr';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
import Guid from 'devextreme/core/guid';
import { Subject } from 'rxjs';
+import 'anti-forgery';
const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore/';
diff --git a/apps/demos/Demos/DataGrid/CollaborativeEditing/React/index.tsx b/apps/demos/Demos/DataGrid/CollaborativeEditing/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/DataGrid/CollaborativeEditing/React/index.tsx
+++ b/apps/demos/Demos/DataGrid/CollaborativeEditing/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/DataGrid/CollaborativeEditing/ReactJs/index.js b/apps/demos/Demos/DataGrid/CollaborativeEditing/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/DataGrid/CollaborativeEditing/ReactJs/index.js
+++ b/apps/demos/Demos/DataGrid/CollaborativeEditing/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/CollaborativeEditing/Vue/index.ts b/apps/demos/Demos/DataGrid/CollaborativeEditing/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/DataGrid/CollaborativeEditing/Vue/index.ts
+++ b/apps/demos/Demos/DataGrid/CollaborativeEditing/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.html b/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.html
index 4aa99c0ce574..bbe9ba77235e 100644
--- a/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.html
+++ b/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.html
@@ -10,6 +10,7 @@
+
diff --git a/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.js b/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.js
index b687ab6e9901..91c005ead1be 100644
--- a/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.js
+++ b/apps/demos/Demos/DataGrid/CollaborativeEditing/jQuery/index.js
@@ -7,40 +7,10 @@ $(() => {
return typeof obj;
};
- const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore';
- const url = `${BASE_PATH}/api/DataGridCollaborativeEditing/`;
+ const BASE_PATH = 'https://js.devexpress.com/Demos/NetCore/';
+ const url = `${BASE_PATH}api/DataGridCollaborativeEditing/`;
const groupId = new DevExpress.data.Guid().toString();
- function fetchAntiForgeryToken() {
- return $.ajax({
- url: `${BASE_PATH}/api/Common/GetAntiForgeryToken`,
- method: 'GET',
- xhrFields: { withCredentials: true },
- cache: false,
- }).fail((xhr) => {
- const error = xhr.responseJSON?.message || xhr.statusText || 'Unknown error';
- throw new Error(`Failed to retrieve anti-forgery token: ${error}`);
- });
- }
-
- function getAntiForgeryTokenValue() {
- const tokenMeta = document.querySelector('meta[name="csrf-token"]');
- if (tokenMeta) {
- const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
- const token = tokenMeta.getAttribute('content');
- return $.Deferred().resolve({ headerName, token });
- }
-
- return fetchAntiForgeryToken().then((tokenData) => {
- const meta = document.createElement('meta');
- meta.name = 'csrf-token';
- meta.content = tokenData.token;
- meta.dataset.headerName = tokenData.headerName;
- document.head.appendChild(meta);
- return tokenData;
- });
- }
-
const createStore = function () {
return DevExpress.data.AspNet.createStore({
key: 'ID',
@@ -48,13 +18,8 @@ $(() => {
insertUrl: url,
updateUrl: url,
deleteUrl: url,
- async onBeforeSend(_, ajaxOptions) {
+ onBeforeSend(method, ajaxOptions) {
ajaxOptions.data.groupId = groupId;
- const tokenData = await getAntiForgeryTokenValue();
- ajaxOptions.xhrFields = {
- withCredentials: true,
- headers: { [tokenData.headerName]: tokenData.token },
- };
},
});
};
@@ -94,7 +59,7 @@ $(() => {
lookup: {
dataSource: DevExpress.data.AspNet.createStore({
key: 'ID',
- loadUrl: `${BASE_PATH}/api/DataGridStatesLookup`,
+ loadUrl: `${BASE_PATH}api/DataGridStatesLookup`,
}),
displayExpr: 'Name',
valueExpr: 'ID',
@@ -125,7 +90,7 @@ $(() => {
createDataGrid('grid1', store1);
createDataGrid('grid2', store2);
- const hubUrl = `${BASE_PATH}/dataGridCollaborativeEditingHub?GroupId=${groupId}`;
+ const hubUrl = `${BASE_PATH}dataGridCollaborativeEditingHub?GroupId=${groupId}`;
const connection = new signalR.HubConnectionBuilder()
.withUrl(hubUrl, {
skipNegotiation: true,
diff --git a/apps/demos/Demos/DataGrid/CustomEditors/Angular/app/app.component.ts b/apps/demos/Demos/DataGrid/CustomEditors/Angular/app/app.component.ts
index cf8e7154b797..e909f5fd5f6c 100644
--- a/apps/demos/Demos/DataGrid/CustomEditors/Angular/app/app.component.ts
+++ b/apps/demos/Demos/DataGrid/CustomEditors/Angular/app/app.component.ts
@@ -5,6 +5,7 @@ import {
} from 'devextreme-angular';
import { createStore, CustomStore } from 'devextreme-aspnet-data-nojquery';
import { Service, Status } from './app.service';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/DataGrid/CustomEditors/React/index.tsx b/apps/demos/Demos/DataGrid/CustomEditors/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/DataGrid/CustomEditors/React/index.tsx
+++ b/apps/demos/Demos/DataGrid/CustomEditors/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/index.js b/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/index.js
+++ b/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/CustomEditors/Vue/index.ts b/apps/demos/Demos/DataGrid/CustomEditors/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/DataGrid/CustomEditors/Vue/index.ts
+++ b/apps/demos/Demos/DataGrid/CustomEditors/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/CustomEditors/jQuery/index.html b/apps/demos/Demos/DataGrid/CustomEditors/jQuery/index.html
index a55a98bd2d3e..40fbcc97d6d8 100644
--- a/apps/demos/Demos/DataGrid/CustomEditors/jQuery/index.html
+++ b/apps/demos/Demos/DataGrid/CustomEditors/jQuery/index.html
@@ -9,6 +9,7 @@
+
diff --git a/apps/demos/Demos/DataGrid/DataValidation/Angular/app/app.component.ts b/apps/demos/Demos/DataGrid/DataValidation/Angular/app/app.component.ts
index 9d9c4a17bf38..7d76a9af777b 100644
--- a/apps/demos/Demos/DataGrid/DataValidation/Angular/app/app.component.ts
+++ b/apps/demos/Demos/DataGrid/DataValidation/Angular/app/app.component.ts
@@ -5,6 +5,7 @@ import { DxDataGridModule } from 'devextreme-angular';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
import { CustomStore } from 'devextreme-angular/common/data';
import { lastValueFrom } from 'rxjs';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/DataGrid/DataValidation/React/index.tsx b/apps/demos/Demos/DataGrid/DataValidation/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/DataGrid/DataValidation/React/index.tsx
+++ b/apps/demos/Demos/DataGrid/DataValidation/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/DataGrid/DataValidation/ReactJs/index.js b/apps/demos/Demos/DataGrid/DataValidation/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/DataGrid/DataValidation/ReactJs/index.js
+++ b/apps/demos/Demos/DataGrid/DataValidation/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/DataValidation/Vue/index.ts b/apps/demos/Demos/DataGrid/DataValidation/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/DataGrid/DataValidation/Vue/index.ts
+++ b/apps/demos/Demos/DataGrid/DataValidation/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/DataValidation/jQuery/index.html b/apps/demos/Demos/DataGrid/DataValidation/jQuery/index.html
index 752e249e4c93..3e76c24f2be5 100644
--- a/apps/demos/Demos/DataGrid/DataValidation/jQuery/index.html
+++ b/apps/demos/Demos/DataGrid/DataValidation/jQuery/index.html
@@ -9,6 +9,7 @@
+
diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/Angular/app/app.service.ts b/apps/demos/Demos/DataGrid/NewRecordPosition/Angular/app/app.service.ts
index 08214f719547..92f1d74e51f8 100644
--- a/apps/demos/Demos/DataGrid/NewRecordPosition/Angular/app/app.service.ts
+++ b/apps/demos/Demos/DataGrid/NewRecordPosition/Angular/app/app.service.ts
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { createStore } from 'devextreme-aspnet-data-nojquery';
+import 'anti-forgery';
const url = 'https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi';
diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/React/index.tsx b/apps/demos/Demos/DataGrid/NewRecordPosition/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/DataGrid/NewRecordPosition/React/index.tsx
+++ b/apps/demos/Demos/DataGrid/NewRecordPosition/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/index.js b/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/index.js
+++ b/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/Vue/index.ts b/apps/demos/Demos/DataGrid/NewRecordPosition/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/DataGrid/NewRecordPosition/Vue/index.ts
+++ b/apps/demos/Demos/DataGrid/NewRecordPosition/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/jQuery/index.html b/apps/demos/Demos/DataGrid/NewRecordPosition/jQuery/index.html
index a0f77e72b188..80f233380917 100644
--- a/apps/demos/Demos/DataGrid/NewRecordPosition/jQuery/index.html
+++ b/apps/demos/Demos/DataGrid/NewRecordPosition/jQuery/index.html
@@ -10,6 +10,7 @@
+
diff --git a/apps/demos/Demos/DataGrid/WebAPIService/Angular/app/app.component.ts b/apps/demos/Demos/DataGrid/WebAPIService/Angular/app/app.component.ts
index af0cf71eb0cc..50b1bd2fe0d3 100644
--- a/apps/demos/Demos/DataGrid/WebAPIService/Angular/app/app.component.ts
+++ b/apps/demos/Demos/DataGrid/WebAPIService/Angular/app/app.component.ts
@@ -2,6 +2,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { DxDataGridModule } from 'devextreme-angular';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/DataGrid/WebAPIService/React/index.tsx b/apps/demos/Demos/DataGrid/WebAPIService/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/DataGrid/WebAPIService/React/index.tsx
+++ b/apps/demos/Demos/DataGrid/WebAPIService/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/DataGrid/WebAPIService/ReactJs/index.js b/apps/demos/Demos/DataGrid/WebAPIService/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/DataGrid/WebAPIService/ReactJs/index.js
+++ b/apps/demos/Demos/DataGrid/WebAPIService/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/WebAPIService/Vue/index.ts b/apps/demos/Demos/DataGrid/WebAPIService/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/DataGrid/WebAPIService/Vue/index.ts
+++ b/apps/demos/Demos/DataGrid/WebAPIService/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/WebAPIService/jQuery/index.html b/apps/demos/Demos/DataGrid/WebAPIService/jQuery/index.html
index cf35723e0b3b..99a5103e9184 100644
--- a/apps/demos/Demos/DataGrid/WebAPIService/jQuery/index.html
+++ b/apps/demos/Demos/DataGrid/WebAPIService/jQuery/index.html
@@ -9,6 +9,7 @@
+
diff --git a/apps/demos/Demos/Diagram/WebAPIService/Angular/app/app.component.ts b/apps/demos/Demos/Diagram/WebAPIService/Angular/app/app.component.ts
index d6f45cc0d2d0..b4a389eac656 100644
--- a/apps/demos/Demos/Diagram/WebAPIService/Angular/app/app.component.ts
+++ b/apps/demos/Demos/Diagram/WebAPIService/Angular/app/app.component.ts
@@ -2,6 +2,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { DxDiagramModule } from 'devextreme-angular';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/Diagram/WebAPIService/React/index.tsx b/apps/demos/Demos/Diagram/WebAPIService/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/Diagram/WebAPIService/React/index.tsx
+++ b/apps/demos/Demos/Diagram/WebAPIService/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/Diagram/WebAPIService/ReactJs/index.js b/apps/demos/Demos/Diagram/WebAPIService/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/Diagram/WebAPIService/ReactJs/index.js
+++ b/apps/demos/Demos/Diagram/WebAPIService/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/Diagram/WebAPIService/Vue/index.ts b/apps/demos/Demos/Diagram/WebAPIService/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/Diagram/WebAPIService/Vue/index.ts
+++ b/apps/demos/Demos/Diagram/WebAPIService/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/Diagram/WebAPIService/jQuery/index.html b/apps/demos/Demos/Diagram/WebAPIService/jQuery/index.html
index d47612c98952..a63ee0885155 100644
--- a/apps/demos/Demos/Diagram/WebAPIService/jQuery/index.html
+++ b/apps/demos/Demos/Diagram/WebAPIService/jQuery/index.html
@@ -11,6 +11,7 @@
+
diff --git a/apps/demos/Demos/FileUploader/CustomDropzone/Angular/app/app.component.ts b/apps/demos/Demos/FileUploader/CustomDropzone/Angular/app/app.component.ts
index ade4ef3575cd..bd0e58f9125f 100644
--- a/apps/demos/Demos/FileUploader/CustomDropzone/Angular/app/app.component.ts
+++ b/apps/demos/Demos/FileUploader/CustomDropzone/Angular/app/app.component.ts
@@ -1,6 +1,7 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { DxFileUploaderModule, DxProgressBarModule } from 'devextreme-angular';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/FileUploader/CustomDropzone/React/index.tsx b/apps/demos/Demos/FileUploader/CustomDropzone/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/FileUploader/CustomDropzone/React/index.tsx
+++ b/apps/demos/Demos/FileUploader/CustomDropzone/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/FileUploader/CustomDropzone/ReactJs/index.js b/apps/demos/Demos/FileUploader/CustomDropzone/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/FileUploader/CustomDropzone/ReactJs/index.js
+++ b/apps/demos/Demos/FileUploader/CustomDropzone/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/FileUploader/CustomDropzone/Vue/index.ts b/apps/demos/Demos/FileUploader/CustomDropzone/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/FileUploader/CustomDropzone/Vue/index.ts
+++ b/apps/demos/Demos/FileUploader/CustomDropzone/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/FileUploader/CustomDropzone/jQuery/index.html b/apps/demos/Demos/FileUploader/CustomDropzone/jQuery/index.html
index 5e1c7621f23e..f47268cb3af3 100644
--- a/apps/demos/Demos/FileUploader/CustomDropzone/jQuery/index.html
+++ b/apps/demos/Demos/FileUploader/CustomDropzone/jQuery/index.html
@@ -8,6 +8,7 @@
+
diff --git a/apps/demos/Demos/FileUploader/FileUploading/Angular/app/app.component.ts b/apps/demos/Demos/FileUploader/FileUploading/Angular/app/app.component.ts
index 8a64af0fe763..8d4c92606301 100644
--- a/apps/demos/Demos/FileUploader/FileUploading/Angular/app/app.component.ts
+++ b/apps/demos/Demos/FileUploader/FileUploading/Angular/app/app.component.ts
@@ -1,6 +1,7 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, Pipe, PipeTransform, provideZoneChangeDetection } from '@angular/core';
import { DxCheckBoxModule, DxFileUploaderModule, DxSelectBoxModule } from 'devextreme-angular';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/FileUploader/FileUploading/React/index.tsx b/apps/demos/Demos/FileUploader/FileUploading/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/FileUploader/FileUploading/React/index.tsx
+++ b/apps/demos/Demos/FileUploader/FileUploading/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/FileUploader/FileUploading/ReactJs/index.js b/apps/demos/Demos/FileUploader/FileUploading/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/FileUploader/FileUploading/ReactJs/index.js
+++ b/apps/demos/Demos/FileUploader/FileUploading/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/FileUploader/FileUploading/Vue/index.ts b/apps/demos/Demos/FileUploader/FileUploading/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/FileUploader/FileUploading/Vue/index.ts
+++ b/apps/demos/Demos/FileUploader/FileUploading/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/FileUploader/FileUploading/jQuery/index.html b/apps/demos/Demos/FileUploader/FileUploading/jQuery/index.html
index 6afecda61def..d9347f931020 100644
--- a/apps/demos/Demos/FileUploader/FileUploading/jQuery/index.html
+++ b/apps/demos/Demos/FileUploader/FileUploading/jQuery/index.html
@@ -8,6 +8,7 @@
+
diff --git a/apps/demos/Demos/FileUploader/Validation/Angular/app/app.component.ts b/apps/demos/Demos/FileUploader/Validation/Angular/app/app.component.ts
index 53bf2ed15ebc..7b686a377245 100644
--- a/apps/demos/Demos/FileUploader/Validation/Angular/app/app.component.ts
+++ b/apps/demos/Demos/FileUploader/Validation/Angular/app/app.component.ts
@@ -1,6 +1,7 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { DxFileUploaderModule } from 'devextreme-angular';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/FileUploader/Validation/React/index.tsx b/apps/demos/Demos/FileUploader/Validation/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/FileUploader/Validation/React/index.tsx
+++ b/apps/demos/Demos/FileUploader/Validation/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/FileUploader/Validation/ReactJs/index.js b/apps/demos/Demos/FileUploader/Validation/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/FileUploader/Validation/ReactJs/index.js
+++ b/apps/demos/Demos/FileUploader/Validation/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/FileUploader/Validation/Vue/index.ts b/apps/demos/Demos/FileUploader/Validation/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/FileUploader/Validation/Vue/index.ts
+++ b/apps/demos/Demos/FileUploader/Validation/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/FileUploader/Validation/jQuery/index.html b/apps/demos/Demos/FileUploader/Validation/jQuery/index.html
index e0791306bc99..7980b4b8140a 100644
--- a/apps/demos/Demos/FileUploader/Validation/jQuery/index.html
+++ b/apps/demos/Demos/FileUploader/Validation/jQuery/index.html
@@ -8,6 +8,7 @@
+
diff --git a/apps/demos/Demos/Scheduler/SignalRService/Angular/app/app.component.ts b/apps/demos/Demos/Scheduler/SignalRService/Angular/app/app.component.ts
index 09c682e01734..6872c0c8e5fe 100644
--- a/apps/demos/Demos/Scheduler/SignalRService/Angular/app/app.component.ts
+++ b/apps/demos/Demos/Scheduler/SignalRService/Angular/app/app.component.ts
@@ -3,6 +3,7 @@ import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/
import { HubConnectionBuilder, HttpTransportType } from '@aspnet/signalr';
import { DxSchedulerModule } from 'devextreme-angular';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/Scheduler/SignalRService/React/index.tsx b/apps/demos/Demos/Scheduler/SignalRService/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/Scheduler/SignalRService/React/index.tsx
+++ b/apps/demos/Demos/Scheduler/SignalRService/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/Scheduler/SignalRService/ReactJs/index.js b/apps/demos/Demos/Scheduler/SignalRService/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/Scheduler/SignalRService/ReactJs/index.js
+++ b/apps/demos/Demos/Scheduler/SignalRService/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/Scheduler/SignalRService/Vue/index.ts b/apps/demos/Demos/Scheduler/SignalRService/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/Scheduler/SignalRService/Vue/index.ts
+++ b/apps/demos/Demos/Scheduler/SignalRService/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/Scheduler/SignalRService/jQuery/index.html b/apps/demos/Demos/Scheduler/SignalRService/jQuery/index.html
index 05efb69d3344..4d2fdc94b32f 100644
--- a/apps/demos/Demos/Scheduler/SignalRService/jQuery/index.html
+++ b/apps/demos/Demos/Scheduler/SignalRService/jQuery/index.html
@@ -11,6 +11,7 @@
+
diff --git a/apps/demos/Demos/Scheduler/WebAPIService/Angular/app/app.component.ts b/apps/demos/Demos/Scheduler/WebAPIService/Angular/app/app.component.ts
index 45fa4bdc19ee..985368ed3181 100644
--- a/apps/demos/Demos/Scheduler/WebAPIService/Angular/app/app.component.ts
+++ b/apps/demos/Demos/Scheduler/WebAPIService/Angular/app/app.component.ts
@@ -2,6 +2,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { DxSchedulerModule } from 'devextreme-angular';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/Scheduler/WebAPIService/React/index.tsx b/apps/demos/Demos/Scheduler/WebAPIService/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/Scheduler/WebAPIService/React/index.tsx
+++ b/apps/demos/Demos/Scheduler/WebAPIService/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/Scheduler/WebAPIService/ReactJs/index.js b/apps/demos/Demos/Scheduler/WebAPIService/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/Scheduler/WebAPIService/ReactJs/index.js
+++ b/apps/demos/Demos/Scheduler/WebAPIService/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/Scheduler/WebAPIService/Vue/index.ts b/apps/demos/Demos/Scheduler/WebAPIService/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/Scheduler/WebAPIService/Vue/index.ts
+++ b/apps/demos/Demos/Scheduler/WebAPIService/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/Scheduler/WebAPIService/jQuery/index.html b/apps/demos/Demos/Scheduler/WebAPIService/jQuery/index.html
index b1ecc91affd6..75a96c2532c4 100644
--- a/apps/demos/Demos/Scheduler/WebAPIService/jQuery/index.html
+++ b/apps/demos/Demos/Scheduler/WebAPIService/jQuery/index.html
@@ -9,6 +9,7 @@
+
diff --git a/apps/demos/Demos/TreeList/WebAPIService/Angular/app/app.component.ts b/apps/demos/Demos/TreeList/WebAPIService/Angular/app/app.component.ts
index 958d3133825b..2cdd581856b1 100644
--- a/apps/demos/Demos/TreeList/WebAPIService/Angular/app/app.component.ts
+++ b/apps/demos/Demos/TreeList/WebAPIService/Angular/app/app.component.ts
@@ -2,6 +2,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
import * as AspNetData from 'devextreme-aspnet-data-nojquery';
import { DxTreeListModule, DxTreeListTypes } from 'devextreme-angular/ui/tree-list';
+import 'anti-forgery';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
diff --git a/apps/demos/Demos/TreeList/WebAPIService/React/index.tsx b/apps/demos/Demos/TreeList/WebAPIService/React/index.tsx
index 8acbec4b6179..c3dd8a22d1a9 100644
--- a/apps/demos/Demos/TreeList/WebAPIService/React/index.tsx
+++ b/apps/demos/Demos/TreeList/WebAPIService/React/index.tsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(
,
diff --git a/apps/demos/Demos/TreeList/WebAPIService/ReactJs/index.js b/apps/demos/Demos/TreeList/WebAPIService/ReactJs/index.js
index b853e0be8242..9a65de6bddfc 100644
--- a/apps/demos/Demos/TreeList/WebAPIService/ReactJs/index.js
+++ b/apps/demos/Demos/TreeList/WebAPIService/ReactJs/index.js
@@ -1,5 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
+// eslint-disable-next-line import/no-unresolved
+import 'anti-forgery';
ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/TreeList/WebAPIService/Vue/index.ts b/apps/demos/Demos/TreeList/WebAPIService/Vue/index.ts
index 684d04215d72..ac840e87baee 100644
--- a/apps/demos/Demos/TreeList/WebAPIService/Vue/index.ts
+++ b/apps/demos/Demos/TreeList/WebAPIService/Vue/index.ts
@@ -1,4 +1,5 @@
import { createApp } from 'vue';
import App from './App.vue';
+import 'anti-forgery';
createApp(App).mount('#app');
diff --git a/apps/demos/Demos/TreeList/WebAPIService/jQuery/index.html b/apps/demos/Demos/TreeList/WebAPIService/jQuery/index.html
index 16d8f4cbc7ea..85d9e6f9ea33 100644
--- a/apps/demos/Demos/TreeList/WebAPIService/jQuery/index.html
+++ b/apps/demos/Demos/TreeList/WebAPIService/jQuery/index.html
@@ -9,6 +9,7 @@
+
diff --git a/apps/demos/configs/Angular/config.js b/apps/demos/configs/Angular/config.js
index daf8948d74f5..f56c8b8f61d8 100644
--- a/apps/demos/configs/Angular/config.js
+++ b/apps/demos/configs/Angular/config.js
@@ -155,8 +155,10 @@ window.config = {
'npm:': '../../../../node_modules/',
'bundles:': '../../../../bundles/',
'externals:': '../../../../bundles/externals/',
+ 'anti-forgery:': '../../../../shared/anti-forgery/',
},
map: {
+ 'anti-forgery': 'anti-forgery:fetch-override.js',
'ts': 'npm:plugin-typescript/lib/plugin.js',
'typescript': 'npm:typescript/lib/typescript.js',
'jszip': 'npm:jszip/dist/jszip.min.js',
diff --git a/apps/demos/configs/React/config.js b/apps/demos/configs/React/config.js
index 82e22347d2f7..2688620b623c 100644
--- a/apps/demos/configs/React/config.js
+++ b/apps/demos/configs/React/config.js
@@ -46,9 +46,11 @@ window.config = {
'npm:': '../../../../node_modules/',
'bundles:': '../../../../bundles/',
'externals:': '../../../../bundles/externals/',
+ 'anti-forgery:': '../../../../shared/anti-forgery/',
},
defaultExtension: 'js',
map: {
+ 'anti-forgery': 'anti-forgery:fetch-override.js',
'ts': 'npm:plugin-typescript/lib/plugin.js',
'typescript': 'npm:typescript/lib/typescript.js',
'jszip': 'npm:jszip/dist/jszip.min.js',
diff --git a/apps/demos/configs/ReactJs/config.js b/apps/demos/configs/ReactJs/config.js
index 82e22347d2f7..2688620b623c 100644
--- a/apps/demos/configs/ReactJs/config.js
+++ b/apps/demos/configs/ReactJs/config.js
@@ -46,9 +46,11 @@ window.config = {
'npm:': '../../../../node_modules/',
'bundles:': '../../../../bundles/',
'externals:': '../../../../bundles/externals/',
+ 'anti-forgery:': '../../../../shared/anti-forgery/',
},
defaultExtension: 'js',
map: {
+ 'anti-forgery': 'anti-forgery:fetch-override.js',
'ts': 'npm:plugin-typescript/lib/plugin.js',
'typescript': 'npm:typescript/lib/typescript.js',
'jszip': 'npm:jszip/dist/jszip.min.js',
diff --git a/apps/demos/configs/Vue/config.js b/apps/demos/configs/Vue/config.js
index b8211d96ac1f..06b13cbec754 100644
--- a/apps/demos/configs/Vue/config.js
+++ b/apps/demos/configs/Vue/config.js
@@ -44,8 +44,10 @@ window.config = {
'npm:': '../../../../node_modules/',
'bundles:': '../../../../bundles/',
'externals:': '../../../../bundles/externals/',
+ 'anti-forgery:': '../../../../shared/anti-forgery/',
},
map: {
+ 'anti-forgery': 'anti-forgery:fetch-override.js',
'vue': 'npm:vue/dist/vue.esm-browser.js',
'@vue/shared': 'npm:@vue/shared/dist/shared.cjs.prod.js',
'vue-loader': 'npm:dx-systemjs-vue-browser/index.js',
diff --git a/apps/demos/shared/anti-forgery/fetch-override.js b/apps/demos/shared/anti-forgery/fetch-override.js
new file mode 100644
index 000000000000..010ae61d6627
--- /dev/null
+++ b/apps/demos/shared/anti-forgery/fetch-override.js
@@ -0,0 +1,100 @@
+import ajax from 'devextreme/core/utils/ajax';
+import { Deferred } from 'devextreme/core/utils/deferred';
+
+const sendRequestOrig = ajax.sendRequest;
+const fetchOrig = fetch;
+let antiForgeryGettingPromise = null;
+
+async function fetchAntiForgeryToken() {
+ try {
+ const response = await fetchOrig('https://js.devexpress.com/Demos/NetCore/api/Common/GetAntiForgeryToken', {
+ method: 'GET',
+ // credentials: 'include',
+ cache: 'no-cache',
+ });
+
+ if (!response.ok) {
+ const errorMessage = await response.text();
+ throw new Error(`Failed to retrieve anti-forgery token: ${errorMessage || response.statusText}`);
+ }
+
+ return await response.json();
+ } catch (error) {
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
+ throw new Error(errorMessage);
+ }
+}
+
+async function getAntiForgeryTokenValue() {
+ const tokenMeta = document.querySelector('meta[name="csrf-token"]');
+
+ if (tokenMeta) {
+ const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
+ const token = tokenMeta.getAttribute('content') || '';
+
+ return Promise.resolve({ headerName, token });
+ }
+
+ if (!antiForgeryGettingPromise) {
+ antiForgeryGettingPromise = fetchAntiForgeryToken();
+ }
+
+ const tokenData = await antiForgeryGettingPromise;
+ const meta = document.createElement('meta');
+
+ meta.name = 'csrf-token';
+ meta.content = tokenData.token;
+ meta.dataset.headerName = tokenData.headerName;
+ document.head.appendChild(meta);
+ antiForgeryGettingPromise = null;
+
+ return tokenData;
+}
+
+ajax.sendRequest = (options) => {
+ const deferred = typeof Deferred !== 'undefined' ? new Deferred() : (() => {
+ let resolve;
+ let reject;
+ // eslint-disable-next-line spellcheck/spell-checker
+ const promise = new Promise((res, rej) => { resolve = res; reject = rej; });
+ return { promise: () => promise, resolve, reject };
+ })();
+
+ getAntiForgeryTokenValue().then(({ headerName, token }) => {
+ options.headers = {
+ [headerName]: token,
+ ...(options.headers || {}),
+ };
+
+ options.xhrFields = {
+ // withCredentials: true,
+ };
+
+ sendRequestOrig(options).then(
+ (result) => {
+ deferred.resolve(result);
+ if (result.success) {
+ deferred.resolve(result);
+ } else {
+ deferred.reject(result);
+ }
+ },
+ (e) => deferred.reject(e),
+ );
+ });
+
+ return deferred.promise();
+};
+
+window.fetch = async (url, options = {}) => {
+ const { headerName, token } = await getAntiForgeryTokenValue();
+
+ options.headers = {
+ [headerName]: token,
+ ...(options.headers || {}),
+ };
+
+ // options.credentials = 'include';
+
+ return fetchOrig(url, options);
+};
diff --git a/apps/demos/shared/anti-forgery/jquery-override.js b/apps/demos/shared/anti-forgery/jquery-override.js
new file mode 100644
index 000000000000..6b6f33d241b1
--- /dev/null
+++ b/apps/demos/shared/anti-forgery/jquery-override.js
@@ -0,0 +1,91 @@
+/* global $, DevExpress */
+const orig$ = $;
+const ajaxSendRequestOrig = DevExpress.utils.ajax.sendRequest;
+let antiForgerySettingPromise = null;
+
+function fetchAntiForgeryToken() {
+ const d = orig$.Deferred();
+
+ orig$.ajax({
+ url: 'https://js.devexpress.com/Demos/NetCore/api/Common/GetAntiForgeryToken',
+ method: 'GET',
+ // xhrFields: { withCredentials: true },
+ cache: false,
+ }).done((data) => {
+ d.resolve(data);
+ }).fail((xhr) => {
+ const error = xhr.responseJSON?.message || xhr.statusText || 'Unknown error';
+ d.reject(new Error(`Failed to retrieve anti-forgery token: ${error}`));
+ });
+
+ return d.promise();
+}
+
+function getAntiForgeryTokenValue() {
+ const tokenMeta = document.querySelector('meta[name="csrf-token"]');
+ if (tokenMeta) {
+ const headerName = tokenMeta.dataset.headerName || 'RequestVerificationToken';
+ const token = tokenMeta.getAttribute('content');
+ return orig$.Deferred().resolve({ headerName, token });
+ }
+
+ return fetchAntiForgeryToken().then((tokenData) => {
+ const meta = document.createElement('meta');
+ meta.name = 'csrf-token';
+ meta.content = tokenData.token;
+ meta.dataset.headerName = tokenData.headerName;
+ document.head.appendChild(meta);
+ return tokenData;
+ });
+}
+
+async function setAntiForgery() {
+ const originalAjax = orig$.ajax;
+ const tokenData = await getAntiForgeryTokenValue();
+
+ // eslint-disable-next-line no-global-assign
+ $ = orig$;
+ antiForgerySettingPromise = null;
+
+ $.ajax = (url, options) => {
+ if (typeof url !== 'string') {
+ // eslint-disable-next-line no-param-reassign
+ options = url;
+ } else {
+ options.url = url;
+ }
+
+ options.headers = { [tokenData.headerName]: tokenData.token, ...(options.headers || {}) };
+ options.xhrFields = {
+ // withCredentials: true,
+ ...(options.xhrFields || {}),
+ };
+
+ return originalAjax.call(this, options);
+ };
+
+ DevExpress.utils.ajax.sendRequest = (options) => {
+ options.headers = {
+ [tokenData.headerName]: tokenData.token,
+ ...(options.headers || {}),
+ };
+
+ options.xhrFields = {
+ // withCredentials: true,
+ ...(options.xhrFields || {}),
+ };
+
+ return ajaxSendRequestOrig(options);
+ };
+}
+
+// eslint-disable-next-line no-global-assign
+$ = (...args) => orig$(async () => {
+ if (!antiForgerySettingPromise) {
+ antiForgerySettingPromise = setAntiForgery();
+ }
+
+ await antiForgerySettingPromise;
+
+ return $(...args);
+});