diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
index c6842513b2..a89a046252 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/contenttype.resource.js
@@ -333,7 +333,18 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
notificationsService.error(value);
});
});
- }
+ },
+
+ import: function (file) {
+ if (!file) {
+ throw "file cannot be null";
+ }
+
+ return umbRequestHelper.resourcePromise(
+ $http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "Import", { file: file })),
+ "Failed to import document type " + file
+ );
+ },
};
}
angular.module('umbraco.resources').factory('contentTypeResource', contentTypeResource);
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/import.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/import.controller.js
new file mode 100644
index 0000000000..6356d162dd
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/import.controller.js
@@ -0,0 +1,75 @@
+angular.module("umbraco")
+ .controller("Umbraco.Editors.DocumentTypes.ImportController",
+ function ($scope, contentTypeResource, navigationService, Upload, umbRequestHelper) {
+ var vm = this;
+ vm.serverErrorMessage = "";
+ vm.state = "upload";
+ vm.model = {};
+ vm.uploadStatus = "";
+
+ $scope.handleFiles = function (files, event) {
+ if (files && files.length > 0) {
+ $scope.upload(files[0]);
+ }
+ };
+
+ $scope.upload = function (file) {
+ Upload.upload({
+ url: umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "Upload"),
+ fields: {},
+ file: file
+ }).success(function (data, status, headers, config) {
+ if (data.notifications && data.notifications.length > 0) {
+
+ // set error status on file
+ vm.uploadStatus = "error";
+
+ // Throw message back to user with the cause of the error
+ vm.serverErrorMessage = data.notifications[0].message;
+ } else {
+
+ // set done status on file
+ vm.uploadStatus = "done";
+ vm.model = data;
+ vm.state = "confirm";
+ }
+ }).error(function (evt, status, headers, config) {
+
+ // set status done
+ $scope.uploadStatus = "error";
+
+ // If file not found, server will return a 404 and display this message
+ if (status === 404) {
+ $scope.serverErrorMessage = "File not found";
+ }
+ else if (status == 400) {
+ //it's a validation error
+ $scope.serverErrorMessage = evt.message;
+ }
+ else {
+ //it's an unhandled error
+ //if the service returns a detailed error
+ if (evt.InnerException) {
+ $scope.serverErrorMessage = evt.InnerException.ExceptionMessage;
+
+ //Check if its the common "too large file" exception
+ if (evt.InnerException.StackTrace && evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0) {
+ $scope.serverErrorMessage = "File too large to upload";
+ }
+
+ } else if (evt.Message) {
+ $scope.serverErrorMessage = evt.Message;
+ }
+ }
+ });
+ };
+
+ $scope.cancel = function () {
+ navigationService.hideDialog();
+ };
+
+ $scope.import = function () {
+ contentTypeResource.import(vm.model.tempFileName);
+ vm.state = "done";
+ }
+ });
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/import.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/import.html
new file mode 100644
index 0000000000..3ce790513a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/import.html
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+ To import a document type, find the '.udt' file on your computer by clicking the 'Browse' button and click 'Import' (you'll be asked for confirmation on the next screen)
+
+
+
+
+
+
>
+ cancel
+
+
+
+
+ Name :
+
+ {{vm.model.name}}
+
+
+ Alias :
+
+ {{vm.model.alias}}
+
+
+
+ Import
+
+
+
+ {{vm.model.name}} has been imported!
+
+
+
+
+
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index c90722c08c..ba721a70c4 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -361,7 +361,6 @@
-
diff --git a/src/Umbraco.Web.UI/Umbraco/dialogs/importDocumenttype.aspx b/src/Umbraco.Web.UI/Umbraco/dialogs/importDocumenttype.aspx
deleted file mode 100644
index 44280f6710..0000000000
--- a/src/Umbraco.Web.UI/Umbraco/dialogs/importDocumenttype.aspx
+++ /dev/null
@@ -1,49 +0,0 @@
-<%@ Page MasterPageFile="../masterpages/umbracoDialog.Master" Language="c#" Codebehind="importDocumenttype.aspx.cs" AutoEventWireup="false"
- Inherits="umbraco.presentation.umbraco.dialogs.importDocumentType" %>
-
-
-
-
-
-
-
-
diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs
index c864ed8f16..79079265af 100644
--- a/src/Umbraco.Web/Editors/ContentTypeController.cs
+++ b/src/Umbraco.Web/Editors/ContentTypeController.cs
@@ -1,21 +1,29 @@
using AutoMapper;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
+using System.Threading.Tasks;
using System.Web.Http;
+using System.Xml;
+using System.Xml.Linq;
using Umbraco.Core;
+using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
+using Umbraco.Web.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
+using Umbraco.Web.UI;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
using Constants = Umbraco.Core.Constants;
+using Notification = Umbraco.Web.Models.ContentEditing.Notification;
namespace Umbraco.Web.Editors
{
@@ -454,5 +462,93 @@ namespace Umbraco.Web.Editors
return response;
}
+
+ [HttpPost]
+ public HttpResponseMessage Import(string file)
+ {
+ var filePath = Path.Combine(IOHelper.MapPath(SystemDirectories.Data), file);
+ if (string.IsNullOrEmpty(file) || !System.IO.File.Exists(filePath))
+ {
+ return Request.CreateResponse(HttpStatusCode.NotFound);
+ }
+
+ var xd = new XmlDocument();
+ xd.XmlResolver = null;
+ xd.Load(filePath);
+
+ var userId = Security.GetUserId();
+ var element = XElement.Parse(xd.InnerXml);
+ Current.Services.PackagingService.ImportContentTypes(element, userId);
+
+ // Try to clean up the temporary file.
+ try
+ {
+ System.IO.File.Delete(filePath);
+ }
+ catch (Exception ex)
+ {
+ Current.Logger.Error(typeof(ContentTypeController), "Error cleaning up temporary udt file in App_Data: " + ex.Message, ex);
+ }
+
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
+
+ [HttpPost]
+ [FileUploadCleanupFilter(false)]
+ public async Task Upload()
+ {
+ if (Request.Content.IsMimeMultipartContent() == false)
+ {
+ throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
+ }
+
+ var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads");
+ //ensure it exists
+ Directory.CreateDirectory(root);
+ var provider = new MultipartFormDataStreamProvider(root);
+ var result = await Request.Content.ReadAsMultipartAsync(provider);
+
+ //must have a file
+ if (result.FileData.Count == 0)
+ {
+ throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
+ }
+
+ var model = new ContentTypeImportModel();
+ var file = result.FileData[0];
+ var fileName = file.Headers.ContentDisposition.FileName.Trim('\"');
+ var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower();
+ if (ext.InvariantEquals("udt"))
+ {
+ //TODO: Currently it has to be here, it's not ideal but that's the way it is right now
+ var tempDir = IOHelper.MapPath(SystemDirectories.Data);
+
+ //ensure it's there
+ Directory.CreateDirectory(tempDir);
+
+ model.TempFileName = "justDelete_" + Guid.NewGuid() + ".udt";
+ var tempFileLocation = Path.Combine(tempDir, model.TempFileName);
+ System.IO.File.Copy(file.LocalFileName, tempFileLocation, true);
+
+ var xd = new XmlDocument
+ {
+ XmlResolver = null
+ };
+ xd.Load(tempFileLocation);
+
+ model.Alias = xd.DocumentElement?.SelectSingleNode("//DocumentType/Info/Alias")?.FirstChild.Value;
+ model.Name = xd.DocumentElement?.SelectSingleNode("//DocumentType/Info/Name")?.FirstChild.Value;
+ }
+ else
+ {
+ model.Notifications.Add(new Notification(
+ Services.TextService.Localize("speechBubbles/operationFailedHeader"),
+ Services.TextService.Localize("media/disallowedFileType"),
+ SpeechBubbleIcon.Warning));
+ }
+
+ return model;
+
+ }
}
}
diff --git a/src/Umbraco.Web/Models/ContentTypeImportModel.cs b/src/Umbraco.Web/Models/ContentTypeImportModel.cs
new file mode 100644
index 0000000000..961476e5f0
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentTypeImportModel.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using Umbraco.Web.Models.ContentEditing;
+
+namespace Umbraco.Web.Models
+{
+ [DataContract(Name = "contentTypeImportModel")]
+ public class ContentTypeImportModel : INotificationModel
+ {
+ public ContentTypeImportModel()
+ {
+ Notifications = new List();
+ }
+
+ [DataMember(Name = "alias")]
+ public string Alias { get; set; }
+
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+
+ [DataMember(Name = "notifications")]
+ public List Notifications { get; }
+
+ [DataMember(Name = "tempFileName")]
+ public string TempFileName { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs
index 1295f32dd6..da1eae7b2c 100644
--- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs
+++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs
@@ -6,7 +6,6 @@ using System.Net.Http.Formatting;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
-using Umbraco.Core.Models.Entities;
using Umbraco.Core.Services;
using Umbraco.Web._Legacy.Actions;
using Umbraco.Web.Models.ContentEditing;
@@ -74,13 +73,7 @@ namespace Umbraco.Web.Trees
// root actions
menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionImport.Instance.Alias)), true).ConvertLegacyMenuItem(new EntitySlim
- {
- Id = int.Parse(id),
- Level = 1,
- ParentId = Constants.System.Root,
- Name = ""
- }, "documenttypes", "settings");
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionImport.Instance.Alias)), true);
menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
return menu;
}
diff --git a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs
index 9aec48825d..a0259ab247 100644
--- a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs
+++ b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs
@@ -257,12 +257,6 @@ namespace Umbraco.Web.Trees
"dialogs/sendToTranslation.aspx?id=" + nodeId + "&rnd=" + DateTime.UtcNow.Ticks,
Current.Services.TextService.Localize("actions/sendToTranslate")));
- case "UmbClientMgr.appActions().actionImport()":
- return Attempt.Succeed(
- new LegacyUrlAction(
- "dialogs/importDocumentType.aspx",
- Current.Services.TextService.Localize("actions/importDocumentType")));
-
}
return Attempt.Fail();
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index cedb362aa1..2d0dd5fde8 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -238,6 +238,7 @@
+
@@ -1284,10 +1285,6 @@
editPackage.aspx
-
- importDocumenttype.aspx
- ASPXCodeBehind
-
rollBack.aspx
@@ -1438,7 +1435,6 @@
ASPXCodeBehind
-
ASPXCodeBehind
diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs b/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs
index 729daa367a..d284da7be4 100644
--- a/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs
+++ b/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs
@@ -1,7 +1,4 @@
-using System;
-using Umbraco.Web.UI.Pages;
-
-namespace Umbraco.Web._Legacy.Actions
+namespace Umbraco.Web._Legacy.Actions
{
///
/// This action is invoked when importing a document type
@@ -32,7 +29,7 @@ namespace Umbraco.Web._Legacy.Actions
{
get
{
- return string.Format("{0}.actionImport()", ClientTools.Scripts.GetAppActions);
+ return "";
}
}
@@ -48,7 +45,7 @@ namespace Umbraco.Web._Legacy.Actions
{
get
{
- return "importDocumentType";
+ return "import";
}
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx
deleted file mode 100644
index 44280f6710..0000000000
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx
+++ /dev/null
@@ -1,49 +0,0 @@
-<%@ Page MasterPageFile="../masterpages/umbracoDialog.Master" Language="c#" Codebehind="importDocumenttype.aspx.cs" AutoEventWireup="false"
- Inherits="umbraco.presentation.umbraco.dialogs.importDocumentType" %>
-
-
-
-
-
-
-
-
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs
deleted file mode 100644
index 38f061e079..0000000000
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-using Umbraco.Core.Services;
-using System;
-using System.Linq;
-using System.Web.UI.WebControls;
-using System.Web.UI.HtmlControls;
-using System.Xml;
-using System.Xml.Linq;
-using Umbraco.Core;
-using Umbraco.Core.IO;
-using Umbraco.Web;
-using Umbraco.Web.Composing;
-
-namespace umbraco.presentation.umbraco.dialogs
-{
- ///
- /// Summary description for importDocumentType.
- ///
- public class importDocumentType : Umbraco.Web.UI.Pages.UmbracoEnsuredPage
- {
- public importDocumentType()
- {
-
- CurrentApp = Constants.Applications.Settings.ToString();
-
- }
- protected Literal FeedBackMessage;
- protected Literal jsShowWindow;
- protected Panel Wizard;
- protected HtmlTable Table1;
- protected HtmlInputHidden tempFile;
- protected HtmlInputFile documentTypeFile;
- protected Button submit;
- protected Panel Confirm;
- protected Literal dtName;
- protected Literal dtAlias;
- protected Button import;
- protected Literal dtNameConfirm;
- protected Panel done;
- private string tempFileName = "";
-
- private void Page_Load(object sender, EventArgs e)
- {
- if (!IsPostBack)
- {
- submit.Text = Services.TextService.Localize("import");
- import.Text = Services.TextService.Localize("import");
- }
- }
-
- #region Web Form Designer generated code
- override protected void OnInit(EventArgs e)
- {
- //
- // CODEGEN: This call is required by the ASP.NET Web Form Designer.
- //
- InitializeComponent();
- base.OnInit(e);
- }
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.submit.Click += new System.EventHandler(this.submit_Click);
- this.import.Click += new System.EventHandler(this.import_Click);
- this.Load += new System.EventHandler(this.Page_Load);
-
- }
- #endregion
-
- private void import_Click(object sender, EventArgs e)
- {
- var xd = new XmlDocument();
- xd.XmlResolver = null;
- xd.Load(tempFile.Value);
-
- var userId = Security.GetUserId();
-
- var element = XElement.Parse(xd.InnerXml);
- var importContentTypes = Current.Services.PackagingService.ImportContentTypes(element, userId);
- var contentType = importContentTypes.FirstOrDefault();
- if (contentType != null)
- dtNameConfirm.Text = contentType.Name;
-
- // Try to clean up the temporary file.
- try
- {
- System.IO.File.Delete(tempFile.Value);
- }
- catch(Exception ex)
- {
- Current.Logger.Error(typeof(importDocumentType), "Error cleaning up temporary udt file in App_Data: " + ex.Message, ex);
- }
-
- Wizard.Visible = false;
- Confirm.Visible = false;
- done.Visible = true;
- }
-
- private void submit_Click(object sender, EventArgs e)
- {
- tempFileName = "justDelete_" + Guid.NewGuid().ToString() + ".udt";
- var fileName = IOHelper.MapPath(SystemDirectories.Data + "/" + tempFileName);
- tempFile.Value = fileName;
-
- documentTypeFile.PostedFile.SaveAs(fileName);
-
- var xd = new XmlDocument();
- xd.XmlResolver = null;
- xd.Load(fileName);
- dtName.Text = xd.DocumentElement.SelectSingleNode("//DocumentType/Info/Name").FirstChild.Value;
- dtAlias.Text = xd.DocumentElement.SelectSingleNode("//DocumentType/Info/Alias").FirstChild.Value;
-
- Wizard.Visible = false;
- done.Visible = false;
- Confirm.Visible = true;
- }
- }
-}