diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index dcef982992..f8fd604097 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -49,7 +49,7 @@ namespace Umbraco.Core.Services private Dictionary _importedContentTypes; private IPackageInstallation _packageInstallation; private readonly IUserService _userService; - + private static HttpClient _httpClient; public PackagingService( ILogger logger, @@ -89,7 +89,6 @@ namespace Umbraco.Core.Services /// public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId) { - using (var httpClient = new HttpClient()) using (var uow = _uowProvider.GetUnitOfWork()) { //includeHidden = true because we don't care if it's hidden we want to get the file regardless @@ -97,7 +96,11 @@ namespace Umbraco.Core.Services byte[] bytes; try { - bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult(); + if (_httpClient == null) + { + _httpClient = new HttpClient(); + } + bytes = _httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult(); } catch (HttpRequestException ex) { @@ -1746,7 +1749,7 @@ namespace Umbraco.Core.Services internal InstallationSummary InstallPackage(string packageFilePath, int userId = 0, bool raiseEvents = false) { - var metaData = GetPackageMetaData(packageFilePath); + var metaData = GetPackageMetaData(packageFilePath); if (raiseEvents) { diff --git a/src/Umbraco.Web/Editors/CanvasDesignerController.cs b/src/Umbraco.Web/Editors/CanvasDesignerController.cs index 722167d18a..8284bf0b12 100644 --- a/src/Umbraco.Web/Editors/CanvasDesignerController.cs +++ b/src/Umbraco.Web/Editors/CanvasDesignerController.cs @@ -20,9 +20,10 @@ using Umbraco.Core.Services; namespace Umbraco.Web.Editors { - + public class CanvasDesignerController : UmbracoApiController { + private static WebClient _webClient; [HttpGet] public HttpResponseMessage GetGoogleFont() @@ -35,10 +36,10 @@ namespace Umbraco.Web.Editors var googleWebFontAPIURL = string.Format("https://www.googleapis.com/webfonts/v1/webfonts?key={0}", APIKey); var response = "{}"; - using (var client = new System.Net.WebClient()) - { - response = client.DownloadString(new Uri(googleWebFontAPIURL)); - } + if (_webClient == null) + _webClient = new WebClient(); + + response = _webClient.DownloadString(new Uri(googleWebFontAPIURL)); var resp = Request.CreateResponse(); resp.Content = new StringContent(response); @@ -59,7 +60,7 @@ namespace Umbraco.Web.Editors // Prepare string parameter result string[] paramLines = paramBlock.Trim().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); - IList parameters = new List(); + IList parameters = new List(); foreach (var line in paramLines) { if (!line.Contains("@import")) @@ -121,4 +122,4 @@ namespace Umbraco.Web.Editors } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 55286d99b4..b9fcbf66e7 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -27,6 +27,8 @@ namespace Umbraco.Web.Editors [WebApi.UmbracoAuthorize] public class DashboardController : UmbracoApiController { + //we have just one instance of HttpClient shared for the entire application + private static readonly HttpClient HttpClient = new HttpClient(); //we have baseurl as a param to make previewing easier, so we can test with a dev domain from client side [ValidateAngularAntiForgeryToken] public async Task GetRemoteDashboardContent(string section, string baseUrl = "https://dashboard.umbraco.org/") @@ -54,13 +56,10 @@ namespace Umbraco.Web.Editors //content is null, go get it try { - using (var web = new HttpClient()) - { - //fetch dashboard json and parse to JObject - var json = await web.GetStringAsync(url); - content = JObject.Parse(json); - result = content; - } + //fetch dashboard json and parse to JObject + var json = await HttpClient.GetStringAsync(url); + content = JObject.Parse(json); + result = content; ApplicationContext.ApplicationCache.RuntimeCache.InsertCacheItem(key, () => result, new TimeSpan(0, 30, 0)); } @@ -93,17 +92,14 @@ namespace Umbraco.Web.Editors //content is null, go get it try { - using (var web = new HttpClient()) - { - //fetch remote css - content = await web.GetStringAsync(url); + //fetch remote css + content = await HttpClient.GetStringAsync(url); - //can't use content directly, modified closure problem - result = content; + //can't use content directly, modified closure problem + result = content; - //save server content for 30 mins - ApplicationContext.ApplicationCache.RuntimeCache.InsertCacheItem(key, () => result, new TimeSpan(0, 30, 0)); - } + //save server content for 30 mins + ApplicationContext.ApplicationCache.RuntimeCache.InsertCacheItem(key, () => result, new TimeSpan(0, 30, 0)); } catch (HttpRequestException ex) { @@ -119,12 +115,12 @@ namespace Umbraco.Web.Editors Content = new StringContent(result, Encoding.UTF8, "text/css") }; } - + [ValidateAngularAntiForgeryToken] public IEnumerable> GetDashboard(string section) { var dashboardHelper = new DashboardHelper(Services.SectionService); - return dashboardHelper.GetDashboard(section, Security.CurrentUser); + return dashboardHelper.GetDashboard(section, Security.CurrentUser); } } } diff --git a/src/Umbraco.Web/Editors/HelpController.cs b/src/Umbraco.Web/Editors/HelpController.cs index 50e6547e36..8f981d9c88 100644 --- a/src/Umbraco.Web/Editors/HelpController.cs +++ b/src/Umbraco.Web/Editors/HelpController.cs @@ -7,20 +7,18 @@ using System.Threading.Tasks; namespace Umbraco.Web.Editors { public class HelpController : UmbracoAuthorizedJsonController - { + { + private static readonly HttpClient HttpClient = new HttpClient(); public async Task> GetContextHelpForPage(string section, string tree, string baseUrl = "https://our.umbraco.com") { var url = string.Format(baseUrl + "/Umbraco/Documentation/Lessons/GetContextHelpDocs?sectionAlias={0}&treeAlias={1}", section, tree); - using (var web = new HttpClient()) - { - //fetch dashboard json and parse to JObject - var json = await web.GetStringAsync(url); - var result = JsonConvert.DeserializeObject>(json); - if (result != null) - return result; + //fetch dashboard json and parse to JObject + var json = await HttpClient.GetStringAsync(url); + var result = JsonConvert.DeserializeObject>(json); + if (result != null) + return result; - return new List(); - } + return new List(); } } diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs index 29cfe76ca2..145395e235 100644 --- a/src/Umbraco.Web/Install/InstallHelper.cs +++ b/src/Umbraco.Web/Install/InstallHelper.cs @@ -23,6 +23,7 @@ namespace Umbraco.Web.Install { internal class InstallHelper { + private static HttpClient _httpClient; private readonly UmbracoContext _umbContext; private InstallationType? _installationType; @@ -191,16 +192,18 @@ namespace Umbraco.Web.Install internal IEnumerable GetStarterKits() { + if (_httpClient == null) + { + _httpClient = new HttpClient(); + } var packages = new List(); - try { var requestUri = string.Format("https://our.umbraco.com/webapi/StarterKit/Get/?umbracoVersion={0}", UmbracoVersion.Current); using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri)) - using (var httpClient = new HttpClient()) - using (var response = httpClient.SendAsync(request).Result) + using (var response = _httpClient.SendAsync(request).Result) { packages = response.Content.ReadAsAsync>().Result.ToList(); } @@ -213,4 +216,4 @@ namespace Umbraco.Web.Install return packages; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs index dfcb441cce..4dfa793675 100644 --- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; +using System.Net; using System.Web; using System.Web.Security; using Umbraco.Core; @@ -25,6 +26,7 @@ namespace Umbraco.Web.Install.InstallSteps { private readonly HttpContextBase _http; private readonly ApplicationContext _applicationContext; + private static WebClient _webClient; public NewInstallStep(HttpContextBase http, ApplicationContext applicationContext) { @@ -80,9 +82,12 @@ namespace Umbraco.Web.Install.InstallSteps { try { - var client = new System.Net.WebClient(); + if (_webClient == null) + { + _webClient = new WebClient(); + } var values = new NameValueCollection { { "name", admin.Name }, { "email", admin.Email} }; - client.UploadValues("https://shop.umbraco.com/base/Ecom/SubmitEmail/installer.aspx", values); + _webClient.UploadValues("https://shop.umbraco.com/base/Ecom/SubmitEmail/installer.aspx", values); } catch { /* fail in silence */ } } diff --git a/src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs b/src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs index 2f8ec85075..737b04fc83 100644 --- a/src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs +++ b/src/Umbraco.Web/Media/EmbedProviders/AbstractOEmbedProvider.cs @@ -12,18 +12,20 @@ namespace Umbraco.Web.Media.EmbedProviders { //TODO: Make all Http calls async - public abstract class AbstractOEmbedProvider: IEmbedProvider + public abstract class AbstractOEmbedProvider : IEmbedProvider { + private static WebClient _webClient; + public virtual bool SupportsDimensions { get { return true; } } [ProviderSetting] - public string APIEndpoint{ get;set; } + public string APIEndpoint { get; set; } [ProviderSetting] - public Dictionary RequestParams{ get;set; } + public Dictionary RequestParams { get; set; } public abstract string GetMarkup(string url, int maxWidth, int maxHeight); @@ -51,10 +53,9 @@ namespace Umbraco.Web.Media.EmbedProviders public virtual string DownloadResponse(string url) { - using (var webClient = new WebClient()) - { - return webClient.DownloadString(url); - } + if (_webClient == null) + _webClient = new WebClient(); + return _webClient.DownloadString(url); } public virtual T GetJsonResponse(string url) where T : class @@ -79,4 +80,4 @@ namespace Umbraco.Web.Media.EmbedProviders } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs index 41daf796d6..a50b4dffbd 100644 --- a/src/Umbraco.Web/Scheduling/ScheduledTasks.cs +++ b/src/Umbraco.Web/Scheduling/ScheduledTasks.cs @@ -17,11 +17,12 @@ namespace Umbraco.Web.Scheduling internal class ScheduledTasks : RecurringTaskBase { + private static HttpClient _httpClient; private readonly ApplicationContext _appContext; private readonly IUmbracoSettingsSection _settings; private static readonly Hashtable ScheduledTaskTimes = new Hashtable(); - public ScheduledTasks(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, + public ScheduledTasks(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, ApplicationContext appContext, IUmbracoSettingsSection settings) : base(runner, delayMilliseconds, periodMilliseconds) { @@ -61,28 +62,29 @@ namespace Umbraco.Web.Scheduling private async Task GetTaskByHttpAync(string url, CancellationToken token) { - using (var wc = new HttpClient()) + if (_httpClient == null) { - if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri)) - { - wc.BaseAddress = baseUri; - } - var request = new HttpRequestMessage(HttpMethod.Get, url); - - //TODO: pass custom the authorization header, currently these aren't really secured! - //request.Headers.Authorization = AdminTokenAuthorizeAttribute.GetAuthenticationHeaderValue(_appContext); - - try - { - var result = await wc.SendAsync(request, token).ConfigureAwait(false); // ConfigureAwait(false) is recommended? http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html - return result.StatusCode == HttpStatusCode.OK; - } - catch (Exception ex) - { - LogHelper.Error("An error occurred calling web task for url: " + url, ex); - } - return false; + _httpClient = new HttpClient(); } + if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri)) + { + _httpClient.BaseAddress = baseUri; + } + var request = new HttpRequestMessage(HttpMethod.Get, url); + + //TODO: pass custom the authorization header, currently these aren't really secured! + //request.Headers.Authorization = AdminTokenAuthorizeAttribute.GetAuthenticationHeaderValue(_appContext); + + try + { + var result = await _httpClient.SendAsync(request, token).ConfigureAwait(false); // ConfigureAwait(false) is recommended? http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html + return result.StatusCode == HttpStatusCode.OK; + } + catch (Exception ex) + { + LogHelper.Error("An error occurred calling web task for url: " + url, ex); + } + return false; } public override async Task PerformRunAsync(CancellationToken token) diff --git a/src/Umbraco.Web/umbraco.presentation/keepAliveService.cs b/src/Umbraco.Web/umbraco.presentation/keepAliveService.cs index abc3425f3f..192c35a233 100644 --- a/src/Umbraco.Web/umbraco.presentation/keepAliveService.cs +++ b/src/Umbraco.Web/umbraco.presentation/keepAliveService.cs @@ -10,8 +10,9 @@ namespace umbraco.presentation [Obsolete("This is no longer used and will be removed in future versions")] public class keepAliveService { + private static WebClient _webClient; //NOTE: sender will be the umbraco ApplicationContext - public static void PingUmbraco(object sender) + public static void PingUmbraco(object sender) { if (sender == null || !(sender is ApplicationContext)) return; @@ -21,10 +22,9 @@ namespace umbraco.presentation var url = appContext.UmbracoApplicationUrl + "/ping.aspx"; try { - using (var wc = new WebClient()) - { - wc.DownloadString(url); - } + if (_webClient == null) + _webClient = new WebClient(); + _webClient.DownloadString(url); } catch(Exception ee) { @@ -32,4 +32,4 @@ namespace umbraco.presentation } } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs index b304cda0b6..488e4f06c2 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Logging; +using System.Net.Http; +using Umbraco.Core.Logging; using Umbraco.Web; namespace dashboardUtilities @@ -14,6 +15,8 @@ namespace dashboardUtilities public partial class FeedProxy : UmbracoEnsuredPage { + private static WebClient _webClient; + protected void Page_Load(object sender, EventArgs e) { try @@ -31,9 +34,10 @@ namespace dashboardUtilities && feedProxyXml.SelectSingleNode(string.Concat("//allow[@host = '", requestUri.Host, "']")) != null && requestUri.Port == 80) { - using (var client = new WebClient()) - { - var response = client.DownloadString(requestUri); + if (_webClient == null) + _webClient = new WebClient(); + + var response = _webClient.DownloadString(requestUri); if (string.IsNullOrEmpty(response) == false) { @@ -41,7 +45,7 @@ namespace dashboardUtilities Response.ContentType = Request.CleanForXss("type") ?? MediaTypeNames.Text.Xml; Response.Write(response); } - } + } else { @@ -57,4 +61,4 @@ namespace dashboardUtilities } } } -} \ No newline at end of file +} diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs index a502ef5a32..f3733d5e5a 100644 --- a/src/umbraco.cms/businesslogic/Packager/Installer.cs +++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs @@ -14,6 +14,7 @@ using umbraco.cms.businesslogic.web; using umbraco.BusinessLogic; using System.Diagnostics; using System.IO.Compression; +using System.Net; using umbraco.cms.businesslogic.template; using umbraco.interfaces; using Umbraco.Core.Events; @@ -46,6 +47,7 @@ namespace umbraco.cms.businesslogic.packager private readonly List _binaryFileErrors = new List(); private int _currentUserId = -1; + private static WebClient _webClient; public string Name { get; private set; } @@ -685,9 +687,12 @@ namespace umbraco.cms.businesslogic.packager if (Directory.Exists(IOHelper.MapPath(SystemDirectories.Packages)) == false) Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Packages)); - var wc = new System.Net.WebClient(); + if (_webClient == null) + { + _webClient = new WebClient(); + } - wc.DownloadFile( + _webClient.DownloadFile( "http://" + PackageServer + "/fetch?package=" + Package.ToString(), IOHelper.MapPath(SystemDirectories.Packages + "/" + Package + ".umb"));