diff --git a/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/CollectionTable.tsx b/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/CollectionTable.tsx
index 22e9df44f3a305d0afba8489d84b309f03a090e4..06eb4ccc88338cf23a2b30ce6754695be4338c0f 100644
--- a/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/CollectionTable.tsx
+++ b/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/CollectionTable.tsx
@@ -31,7 +31,7 @@ import { t, styled } from '@superset-ui/core';
 import Button from 'src/components/Button';
 import Icons from 'src/components/Icons';
 import Fieldset from './Fieldset';
-import { recurseReactClone } from './utils';
+import { recurseReactClone } from '../utils';
 
 interface CRUDCollectionProps {
   allowAddItem?: boolean;
diff --git a/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/Fieldset.tsx b/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/Fieldset.tsx
index 3d93f37ba5cadac7c9ec9261f95bc74ad9f0539c..eebff01d4241f399c76037338994ae42e98ac694 100644
--- a/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/Fieldset.tsx
+++ b/superset-frontend/src/features/mitmDatasets/MitMDatasetModal/Fieldset.tsx
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { ReactNode, PureComponent } from 'react';
+import { PureComponent, ReactNode } from 'react';
 import { Form } from 'src/components/Form';
 
-import { recurseReactClone } from './utils';
+import { recurseReactClone } from '../utils';
 import Field from './Field';
 
 interface FieldsetProps {
diff --git a/superset-frontend/src/features/mitmDatasets/UploadMitMDatasetModal/index.tsx b/superset-frontend/src/features/mitmDatasets/UploadMitMDatasetModal/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a08d2a1d0fc6b570f91492b588c280fb8242a6c2
--- /dev/null
+++ b/superset-frontend/src/features/mitmDatasets/UploadMitMDatasetModal/index.tsx
@@ -0,0 +1,192 @@
+import { FunctionComponent, useEffect, useState } from 'react';
+import { MITM } from '../types';
+import withToasts from '../../../components/MessageToasts/withToasts';
+import Modal from '../../../components/Modal';
+import { ClientErrorObject, SupersetTheme, t } from '@superset-ui/core';
+import {
+  antDModalNoPaddingStyles,
+  antDModalStyles,
+  formStyles,
+} from '../../databases/UploadDataModel/styles';
+import { Form, Input, Select, Upload } from 'antd-v5';
+import { AsyncActionResult, useExternalService } from '../asyncExternalService';
+import { Button } from '../../../components';
+import { InboxOutlined, UploadOutlined } from '@ant-design/icons';
+
+interface UploadMitMDatasetModalProps {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+  onHide: () => void;
+  show: boolean;
+  allowedExtensions: string[];
+  mitm: MITM;
+}
+
+interface UploadMitMDatasetRequestFormData {
+  mitm: MITM;
+  datasetName: string;
+  mitmZip: File | Blob;
+}
+
+const UploadMitMDatasetModal: FunctionComponent<
+  UploadMitMDatasetModalProps
+> = ({ addDangerToast, addSuccessToast, onHide, show, allowedExtensions }) => {
+  const { asyncAction } = useExternalService();
+
+  // const [mitm, setMitm] = useState<MITM | null>(null);
+  // const [datasetName, setDatasetName] = useState<string | null>(null);
+  // const [fileList, setFileList] = useState<UploadFile[]>([]);
+  const [isLoading, setIsLoading] = useState<boolean>(false);
+  const [error, setError] = useState<ClientErrorObject>();
+
+  const [form] = Form.useForm();
+
+  const onSuccess = (
+    r: AsyncActionResult,
+    {
+      mitm,
+      datasetName,
+    }: Pick<UploadMitMDatasetRequestFormData, 'mitm' | 'datasetName'>,
+  ) => {
+    addSuccessToast(t('Successfully uploaded \"%s\" (%s)', datasetName, mitm));
+  };
+  const onFailure = (error: ClientErrorObject) => {
+    setError(error);
+  };
+
+  useEffect(() => {
+    addDangerToast(t('An error occurred when attempting to upload: %s', error));
+  }, [error]);
+
+  const clearModal = () => {
+    // setDatasetName(null);
+    // setMitm(null);
+    // setFileList([]);
+    setIsLoading(false);
+    form.resetFields();
+  };
+
+  const makeRequest = ({
+    datasetName,
+    mitm,
+    mitmZip,
+  }: UploadMitMDatasetRequestFormData) => {
+    const formData = new FormData();
+    formData.append('dataset_name', datasetName);
+    formData.append('mitm', String(mitm));
+    formData.append('mitm_zip', mitmZip);
+
+    setIsLoading(true);
+    asyncAction({
+      endpoint: '/api/v1/mitm_dataset/upload/',
+      headers: { 'Content-Type': 'multipart/form-data' },
+      postPayload: formData,
+    })
+      .then(r => {
+        console.log(r);
+        onSuccess(r, { datasetName, mitm });
+      })
+      .catch(onFailure)
+      .finally(() => setIsLoading(false));
+  };
+
+  const onFinish = (values: any) => {
+    const fields = form.getFieldsValue();
+
+    const mitmZip = fields.fileList[0]?.originFileObj;
+
+    const mitm = fields.mitm as MITM;
+    makeRequest({ datasetName: fields.datasetName, mitm, mitmZip });
+  };
+
+  const onClose = () => {
+    clearModal();
+    onHide();
+  };
+
+  const extractFileList = (e: any) => {
+    console.log('Upload event:', e);
+    if (Array.isArray(e)) {
+      return e;
+    }
+    return e?.fileList;
+  };
+
+  return (
+    <Modal
+      css={(theme: SupersetTheme) => [
+        antDModalNoPaddingStyles,
+        antDModalStyles(theme),
+        formStyles(theme),
+      ]}
+      primaryButtonLoading={isLoading}
+      name="database"
+      data-test="upload-modal"
+      onHandledPrimaryAction={form.submit}
+      onHide={onClose}
+      width="500px"
+      primaryButtonName="Upload"
+      centered
+      show={show}
+      title="Upload MitM Dataset"
+    >
+      <Form form={form} onFinish={onFinish}>
+        <Form.Item
+          name="datasetName"
+          label="Dataset Name"
+          rules={[{ required: true }]}
+        >
+          <Input />
+        </Form.Item>
+        <Form.Item
+          name="mitm"
+          label="MitM Name"
+          rules={[{ required: true }, { enum: [MITM.MAED] }]}
+        >
+          <Select
+            placeholder="Select the MitM Name"
+            allowClear
+            options={[{ name: 'MAED', value: 'MAED' }]}
+          ></Select>
+        </Form.Item>
+        <Form.Item
+          name="upload"
+          label="Upload"
+          valuePropName="fileList"
+          getValueFromEvent={extractFileList}
+          extra="longgggggggggggggggggggggggggggggggggg"
+        >
+          <Upload
+            name="logo"
+            accept=".zip,.maed,.mitm"
+            customRequest={() => false}
+          >
+            <Button icon={<UploadOutlined />}>Click to upload</Button>
+          </Upload>
+        </Form.Item>
+        <Form.Item label="Dragger">
+          <Form.Item
+            name="dragger"
+            valuePropName="fileList"
+            getValueFromEvent={extractFileList}
+            noStyle
+          >
+            <Upload.Dragger name="files">
+              <p className="ant-upload-drag-icon">
+                <InboxOutlined />
+              </p>
+              <p className="ant-upload-text">
+                Click or drag file to this area to upload
+              </p>
+              <p className="ant-upload-hint">
+                Support for a single or bulk upload.
+              </p>
+            </Upload.Dragger>
+          </Form.Item>
+        </Form.Item>
+      </Form>
+    </Modal>
+  );
+};
+
+export default withToasts(UploadMitMDatasetModal);
diff --git a/superset-frontend/src/features/mitmDatasets/asyncExternalService.ts b/superset-frontend/src/features/mitmDatasets/asyncExternalService.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7296040a08cd5d46b8e81daaa3769d18e1ca1a6a
--- /dev/null
+++ b/superset-frontend/src/features/mitmDatasets/asyncExternalService.ts
@@ -0,0 +1,146 @@
+import {
+  ClientErrorObject,
+  getClientErrorObject,
+  JsonObject,
+  logging,
+  parseErrorJson,
+  RequestConfig,
+  SupersetClient,
+  SupersetError,
+} from '@superset-ui/core';
+import {useAsyncEventHandling} from "../../middleware/asyncEvent";
+
+const extServiceCallApiEndpoint = '/api/v1/ext_service/call';
+
+export enum ExternalService {
+  MitMService = 'mitm_service',
+}
+
+type AsyncJobMetadata = {
+  id?: string | null;
+  channel_id: string;
+  job_id: string;
+  user_id?: string;
+  status: string;
+  errors?: SupersetError[];
+  result_url: string | null;
+  task_id?: string; // my addition
+};
+
+const JOB_STATUS = {
+  PENDING: 'pending',
+  RUNNING: 'running',
+  ERROR: 'error',
+  DONE: 'done',
+};
+
+const fetchJsonResult = async (
+  asyncEvent: AsyncJobMetadata, // & { result_url: string }
+): Promise<{
+  status: 'success' | 'error';
+  data: JsonObject | ClientErrorObject;
+}> => {
+  try {
+    const { json } = await SupersetClient.get({
+      endpoint: String(asyncEvent.result_url),
+    });
+    return { status: 'success', data: 'result' in json ? json.result : json };
+  } catch (response) {
+    const err = await getClientErrorObject(response);
+    return { status: 'error', data: err };
+  }
+};
+
+export type AsyncActionResult = {
+  status: string;
+  lastEvent: AsyncJobMetadata;
+};
+
+const {addListener, removeListener} = useAsyncEventHandling()
+
+export const waitForAsyncData = async (asyncResponse: AsyncJobMetadata) =>
+  new Promise<AsyncActionResult | JsonObject>((resolve, reject) => {
+    const jobId = asyncResponse.job_id;
+    const listener = async (asyncEvent: AsyncJobMetadata) => {
+      switch (asyncEvent.status) {
+        case JOB_STATUS.DONE: {
+          if ('result_url' in asyncEvent) {
+            let { data, status } = await fetchJsonResult(asyncEvent);
+            if (status === 'success') {
+              resolve(data);
+            } else {
+              reject(data);
+            }
+          } else {
+            resolve({
+              status: JOB_STATUS.DONE,
+              lastEvent: asyncEvent,
+            } as AsyncActionResult);
+          }
+          break;
+        }
+        case JOB_STATUS.ERROR: {
+          const err = parseErrorJson(asyncEvent);
+          reject(err);
+          break;
+        }
+        default: {
+          logging.warn('received event with status', asyncEvent.status);
+        }
+      }
+      removeListener(jobId);
+    };
+    addListener(jobId, listener);
+  });
+
+
+export const asyncCall = async (requestConfig: RequestConfig) => {
+  return SupersetClient.post({
+    ...requestConfig,
+  }).then(
+    ({ response, json }) =>
+      new Promise<AsyncActionResult | JsonObject>((resolve, reject) => {
+        {
+          if (response.status === 202) {
+            const jm: AsyncJobMetadata = json;
+            waitForAsyncData(jm).then(resolve).catch(reject);
+          } else {
+            const err = parseErrorJson(json);
+            reject(err);
+          }
+        }
+      }),
+  );
+};
+
+export const asyncAction = async (
+  requestConfig: RequestConfig,
+): Promise<AsyncActionResult> => {
+  return asyncCall(requestConfig);
+};
+
+type CallExternalServiceProps = {
+  extService: ExternalService;
+  path: string;
+  payload?: JsonObject | FormData | undefined;
+};
+
+export const callExternalService = async ({
+  extService,
+  path,
+  payload,
+}: CallExternalServiceProps) => {
+  const endpoint =
+    extServiceCallApiEndpoint + '/' + String(extService) + '/' + path;
+  const contentType =
+    payload instanceof FormData ? 'multipart/form-data' : 'application/json';
+  return asyncCall({
+    endpoint,
+    headers: { 'Content-Type': contentType },
+    postPayload: payload,
+  });
+};
+
+export const useExternalService  = () => {
+  return {asyncCall, asyncAction, callExternalService}
+}
diff --git a/superset-frontend/src/features/mitmDatasets/types.ts b/superset-frontend/src/features/mitmDatasets/types.ts
index a81dc5f14e5e765b754b4b8fc81d989ec364a6cf..132de6df1a00ccd0027e5cd2b74f748367546557 100644
--- a/superset-frontend/src/features/mitmDatasets/types.ts
+++ b/superset-frontend/src/features/mitmDatasets/types.ts
@@ -25,3 +25,7 @@ export interface MitMDataset
   slices?: Array<Slice>;
   dashboards?: Array<Dashboard>;
 }
+
+export enum MITM {
+  MAED = 'MAED'
+}
diff --git a/superset-frontend/src/features/mitmDatasets/utils/index.js b/superset-frontend/src/features/mitmDatasets/utils/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..be1972cd19480d7bd4617ceeaded09838818c37a
--- /dev/null
+++ b/superset-frontend/src/features/mitmDatasets/utils/index.js
@@ -0,0 +1,24 @@
+import {Children, cloneElement} from "react";
+
+export function recurseReactClone(children, type, propExtender) {
+  /**
+   * Clones a React component's children, and injects new props
+   * where the type specified is matched.
+   */
+  return Children.map(children, child => {
+    let newChild = child;
+    if (child && child.type.name === type.name) {
+      newChild = cloneElement(child, propExtender(child));
+    }
+    if (newChild && newChild.props.children) {
+      newChild = cloneElement(newChild, {
+        children: recurseReactClone(
+          newChild.props.children,
+          type,
+          propExtender,
+        ),
+      });
+    }
+    return newChild;
+  });
+}
diff --git a/superset-frontend/src/middleware/asyncEvent.ts b/superset-frontend/src/middleware/asyncEvent.ts
index 0512e6817b32bd062154106fc79a00b8566b1de2..7bcf76f7f4cb7b6a0b2c6cf2f7c83b1a685c75ce 100644
--- a/superset-frontend/src/middleware/asyncEvent.ts
+++ b/superset-frontend/src/middleware/asyncEvent.ts
@@ -18,13 +18,13 @@
  */
 import {
   ensureIsArray,
-  isFeatureEnabled,
   FeatureFlag,
-  makeApi,
-  SupersetClient,
-  logging,
   getClientErrorObject,
+  isFeatureEnabled,
+  logging,
+  makeApi,
   parseErrorJson,
+  SupersetClient,
   SupersetError,
 } from '@superset-ui/core';
 import getBootstrapData from 'src/utils/getBootstrapData';
@@ -76,6 +76,10 @@ const removeListener = (id: string) => {
   delete listenersByJobId[id];
 };
 
+export const useAsyncEventHandling = () => {
+  return { addListener, removeListener };
+};
+
 const fetchCachedData = async (
   asyncEvent: AsyncEvent,
 ): Promise<CachedDataResponse> => {
diff --git a/superset-frontend/src/pages/MitMDatasetCreation/index.tsx b/superset-frontend/src/pages/MitMDatasetCreation/index.tsx
index 8387a05fb1feafc4d0cb989423fee683cc910e2a..bc504cb99e03676e7c9912491b404db6c04460cb 100644
--- a/superset-frontend/src/pages/MitMDatasetCreation/index.tsx
+++ b/superset-frontend/src/pages/MitMDatasetCreation/index.tsx
@@ -1,16 +1,15 @@
 import {useParams} from "react-router-dom";
-import {Reducer, useEffect, useReducer, useState} from "react";
-import Header from "../../features/datasets/AddDataset/Header";
+import {FunctionComponent, Reducer, useEffect, useReducer, useState} from "react";
 import {
   MDSActionType,
   MDSReducerActionType,
 
 } from '../../features/mitmDatasets/AddMitMDataset/types';
-import {datasetReducer} from "../DatasetCreation";
-import useDatasetsList from "../../features/datasets/hooks/useDatasetLists";
 import {t} from "@superset-ui/core";
 import {MitMDatasetObject} from "../../features/mitmDatasets/types";
+import withToasts from 'src/components/MessageToasts/withToasts';
 
+// @ts-ignore
 const prevUrl =
   '/mitm_dataset/list/?pageIndex=0&sortColumn=changed_on_delta_humanized&sortOrder=desc';
 
@@ -39,13 +38,19 @@ export function mitmDatasetReducer(
   }
 }
 
-export default function AddMitMDataset() {
+interface AddMitMDatasetProps {
+  addDangerToast: (msg: string) => void;
+  addSuccessToast: (msg: string) => void;
+}
+
+const AddMitMDataset: FunctionComponent<AddMitMDatasetProps> = ({ addDangerToast,
+                                                                  addSuccessToast }: AddMitMDatasetProps) => {
+  // @ts-ignore
   const [dataset, setDataset] = useReducer<
     Reducer<Partial<MitMDatasetObject> | null, MDSReducerActionType>
   >(mitmDatasetReducer, null);
   const [editPageIsVisible, setEditPageIsVisible] = useState(false);
 
-  
   const { datasetId: id } = useParams<{ datasetId: string }>();
   useEffect(() => {
     if (!Number.isNaN(parseInt(id, 10))) {
@@ -53,13 +58,15 @@ export default function AddMitMDataset() {
     }
   }, [id]);
   const CREATE_DATASET_TEXT = t('You are trying to add a MitM Dataset.');
-  
+
   return (
     <div>
       <h2>AddMitMDatasetPage</h2>
       <p>{dataset}</p>
       <p>{CREATE_DATASET_TEXT}</p>
-      {"editpageisvisible: " + editPageIsVisible}
+      {'editpageisvisible: ' + editPageIsVisible}
     </div>
   );
-}
+};
+
+export default withToasts(AddMitMDataset);
diff --git a/superset-frontend/src/pages/MitMDatasetList/index.tsx b/superset-frontend/src/pages/MitMDatasetList/index.tsx
index 9646caf3f078815dc17ab542db140bf4233661fb..a455f621adc9f97e08c7dd541174175ffbbfde2a 100644
--- a/superset-frontend/src/pages/MitMDatasetList/index.tsx
+++ b/superset-frontend/src/pages/MitMDatasetList/index.tsx
@@ -49,6 +49,7 @@ import {
 } from 'src/features/mitmDatasets/constants';
 import { ModifiedInfo } from 'src/components/AuditInfo';
 import MitMDatasetModal from "../../features/mitmDatasets/MitMDatasetModal";
+import UploadMitMDatasetModal from "../../features/mitmDatasets/UploadMitMDatasetModal";
 
 const Actions = styled.div`
   color: ${({ theme }) => theme.colors.grayscale.base};
@@ -115,7 +116,10 @@ const MitMDatasetList: FunctionComponent<MitMDatasetListProps> = ({
   const [datasetCurrentlyEditing, setDatasetCurrentlyEditing] =
     useState<MitMDataset | null>(null);
 
+
+
   const [importingDataset, showImportModal] = useState<boolean>(false);
+  const [uploadModalOpen, setUploadModalOpen] = useState<boolean>(false);
   const [preparingExport, setPreparingExport] = useState<boolean>(false);
 
   const openDatasetImportModal = () => {
@@ -420,6 +424,20 @@ const MitMDatasetList: FunctionComponent<MitMDatasetListProps> = ({
       buttonStyle: 'primary',
     });
 
+    buttonArr.push({
+      name: (
+        <Tooltip
+          id="upload-tooltip"
+          title={t('Upload dataset')}
+          placement="bottomRight"
+        >
+          <Icons.Import data-test="upload-button" />
+        </Tooltip>
+      ),
+      buttonStyle: 'link',
+      onClick: () => setUploadModalOpen(true),
+    })
+
     buttonArr.push({
       name: (
         <Tooltip
@@ -486,6 +504,12 @@ const MitMDatasetList: FunctionComponent<MitMDatasetListProps> = ({
   return (
     <>
       <SubMenu {...menuData} />
+      <UploadMitMDatasetModal
+        addDangerToast={addDangerToast}
+        addSuccessToast={addSuccessToast}
+        show={uploadModalOpen}
+        onHide={() => setUploadModalOpen(false)}
+      />
       {datasetCurrentlyDeleting && (
         <DeleteModal
           description={
@@ -573,6 +597,7 @@ const MitMDatasetList: FunctionComponent<MitMDatasetListProps> = ({
         show={importingDataset}
         onHide={closeDatasetImportModal}
       />
+
       {preparingExport && <Loading />}
     </>
   );
diff --git a/superset/customization/external_service_support/forwardable_request.py b/superset/customization/external_service_support/forwardable_request.py
index 45aec016911cc660c5db1985a1717b2e6179522f..da737e990d527938f754abc9b38305de44b9db4c 100644
--- a/superset/customization/external_service_support/forwardable_request.py
+++ b/superset/customization/external_service_support/forwardable_request.py
@@ -38,6 +38,7 @@ class ForwardableRequest(pydantic.BaseModel):
         if request.content_encoding == 'multipart/form-data':
             form_data = request.form.to_dict()
             files = {}
+            td = None
             if len(request.files) > 0 and save_files:
                 td = tempfile.mkdtemp(prefix='forwarded_request')
                 for n, f in request.files.items():
diff --git a/superset/views/mitm/views.py b/superset/views/mitm/views.py
index b7b92d530f44ef6e562c7ecd149decf901873df8..d2badb42ded863e8c020a3b72e75212c44f2c1c2 100644
--- a/superset/views/mitm/views.py
+++ b/superset/views/mitm/views.py
@@ -20,3 +20,4 @@ class MitMDatasetView(BaseSupersetView):
     def list(self) -> FlaskResponse:
         return super().render_app_template()
 
+