From fdcf18ef0c76787227c6e4fbda7fd05e4429e4db Mon Sep 17 00:00:00 2001 From: John Gathogo Date: Tue, 19 Jan 2021 11:08:28 +0300 Subject: [PATCH] Set the most logical config defaults for the wizard (#187) * Set the most logical config defaults plus cleanup refactor * Fix unnecessary use of this * Revert version bump Co-authored-by: John Gathogo --- src/Common/ExtensionMethods.cs | 46 ++ src/Common/UserSettingsPersistenceHelper.cs | 5 +- src/Models/ServiceConfiguration.cs | 6 +- src/Models/UserSettings.cs | 419 +++++++++++++++--- src/ODataConnectedService.csproj | 1 + src/ODataConnectedServiceWizard.cs | 193 ++++---- src/Properties/AssemblyInfo.cs | 4 +- src/ViewModels/AdvancedSettingsViewModel.cs | 59 +-- .../ConfigODataEndpointViewModel.cs | 98 +--- src/ViewModels/OperationImportsViewModel.cs | 2 +- src/Views/AdvancedSettings.xaml | 20 +- src/Views/ConfigODataEndpoint.xaml | 20 +- src/Views/ConfigODataEndpoint.xaml.cs | 147 +++--- src/source.extension.vsixmanifest | 2 +- .../Common/ExtensionMethodsTests.cs | 149 +++++++ .../ODataConnectedService.Tests.csproj | 1 + .../ODataConnectedServiceWizardTests.cs | 230 +++++----- .../ConfigOdataEndPointViewModelTests.cs | 10 +- .../Views/UserSettingsTest.cs | 97 ++-- 19 files changed, 932 insertions(+), 577 deletions(-) create mode 100644 src/Common/ExtensionMethods.cs create mode 100644 test/ODataConnectedService.Tests/Common/ExtensionMethodsTests.cs diff --git a/src/Common/ExtensionMethods.cs b/src/Common/ExtensionMethods.cs new file mode 100644 index 00000000..9035de00 --- /dev/null +++ b/src/Common/ExtensionMethods.cs @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) .NET Foundation and Contributors. All rights reserved. +// See License.txt in the project root for license information. +// +//---------------------------------------------------------------------------- + +using System; +using System.Linq; +using System.Reflection; + +namespace Microsoft.OData.ConnectedService.Common +{ + internal static class ExtensionMethods + { + /// + /// Copies public properties with matching name and type from one object to the other. + /// + /// The target. + /// The source. + public static void CopyPropertiesFrom(this object target, object source) + { + if (source == null) + { + return; + } + + var fromProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) + .Where(d => d.GetGetMethod() != null); + var toProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) + .Where(d => d.GetSetMethod() != null); + + foreach(var toProperty in toProperties) + { + var fromProperty = fromProperties.SingleOrDefault(d => + d.Name.Equals(toProperty.Name, StringComparison.Ordinal) + && toProperty.PropertyType.IsAssignableFrom(d.PropertyType)); + + if (fromProperty != null) + { + toProperty.SetValue(target, fromProperty.GetValue(source)); + } + } + } + } +} diff --git a/src/Common/UserSettingsPersistenceHelper.cs b/src/Common/UserSettingsPersistenceHelper.cs index 2ea64178..d9db84f9 100644 --- a/src/Common/UserSettingsPersistenceHelper.cs +++ b/src/Common/UserSettingsPersistenceHelper.cs @@ -36,7 +36,8 @@ public static void Save(object userSettings, string providerId, string name, Act { // note: this overwrites existing settings file if it exists stream = file.OpenFile(fileName, FileMode.Create); - using (var writer = XmlWriter.Create(stream)) + + using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) { var dcs = new DataContractSerializer(userSettings.GetType()); dcs.WriteObject(writer, userSettings); @@ -112,7 +113,7 @@ public static T Load(string providerId, string name, Action onLoaded, Conn private static string GetStorageFileName(string providerId, string name) { - return providerId + "_" + name + ".xml"; + return providerId + "." + name + ".xml"; } private static IsolatedStorageFile GetIsolatedStorageFile() diff --git a/src/Models/ServiceConfiguration.cs b/src/Models/ServiceConfiguration.cs index 8b2658c5..cb0f349b 100644 --- a/src/Models/ServiceConfiguration.cs +++ b/src/Models/ServiceConfiguration.cs @@ -39,7 +39,7 @@ internal class ServiceConfigurationV4 : ServiceConfiguration public bool EnableNamingAlias { get; set; } public bool IgnoreUnexpectedElementsAndAttributes { get; set; } public bool IncludeT4File { get; set; } - public List ExcludedOperationImports; - public List ExcludedBoundOperations; + public List ExcludedOperationImports { get; set; } + public List ExcludedBoundOperations { get; set; } } -} \ No newline at end of file +} diff --git a/src/Models/UserSettings.cs b/src/Models/UserSettings.cs index bd76f915..250cce94 100644 --- a/src/Models/UserSettings.cs +++ b/src/Models/UserSettings.cs @@ -5,147 +5,466 @@ // //---------------------------------------------------------------------------- +using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; using Microsoft.OData.ConnectedService.Common; using Microsoft.VisualStudio.ConnectedServices; +using Newtonsoft.Json; namespace Microsoft.OData.ConnectedService.Models { [DataContract] - internal class UserSettings + internal class UserSettings : INotifyPropertyChanged { - private const string Name = "Settings"; + #region Const Members + private const int MaxMruEntries = 10; - private ConnectedServiceLogger logger; + #endregion Const Members - [DataMember] - public ObservableCollection MruEndpoints { get; set; } + #region Readonly Members - [DataMember] - public string ServiceName { get; set; } + private readonly ConnectedServiceLogger logger; - [DataMember] - public string Endpoint { get; set; } + private readonly string configName; + + #endregion Readonly Members + + #region Private Members + + private ObservableCollection mruEndpoints; + + private string serviceName; + + private string endpoint; + + private string generatedFileNamePrefix; + + private bool useNamespacePrefix; + + private string namespacePrefix; + + private bool useDataServiceCollection; + + private bool makeTypesInternal; + + private bool openGeneratedFilesInIDE; + + private bool generateMultipleFiles; + + private string customHttpHeaders; + + private bool enableNamingAlias; + + private bool ignoreUnexpectedElementsAndAttributes; + + private bool includeT4File; + + private bool includeWebProxy; + + private string webProxyHost; + + private bool includeWebProxyNetworkCredentials; + + private string webProxyNetworkCredentialsUsername; + + private string webProxyNetworkCredentialsPassword; + + private string webProxyNetworkCredentialsDomain; + + private bool includeCustomHeaders; + + private List excludedOperationImports; + + private List excludedBoundOperations; + + private List excludedSchemaTypes; + + #endregion Private Members + + public event PropertyChangedEventHandler PropertyChanged; [DataMember] - public string GeneratedFileNamePrefix { get; set; } + public ObservableCollection MruEndpoints + { + get { return mruEndpoints; } + set + { + mruEndpoints = value; + OnPropertyChanged(); + } + } [DataMember] - public bool UseNamespacePrefix { get; set; } + public string ServiceName + { + get { return serviceName; } + set + { + serviceName = value; + OnPropertyChanged(); + } + } [DataMember] - public string NamespacePrefix { get; set; } + public string Endpoint + { + get { return endpoint; } + set + { + endpoint = value; + OnPropertyChanged(); + } + } [DataMember] - public bool UseDataServiceCollection { get; set; } + public string GeneratedFileNamePrefix + { + get { return generatedFileNamePrefix; } + set + { + generatedFileNamePrefix = value; + OnPropertyChanged(); + } + } [DataMember] - public bool MakeTypesInternal { get; set; } + public bool UseNamespacePrefix + { + get { return useNamespacePrefix; } + set + { + useNamespacePrefix = value; + OnPropertyChanged(); + } + } [DataMember] - public bool OpenGeneratedFilesInIDE { get; set; } + public string NamespacePrefix + { + get { return namespacePrefix; } + set + { + namespacePrefix = value; + OnPropertyChanged(); + } + } [DataMember] - public bool GenerateMultipleFiles { get; set; } + public bool UseDataServiceCollection + { + get { return useDataServiceCollection; } + set + { + useDataServiceCollection = value; + OnPropertyChanged(); + } + } [DataMember] - public string CustomHttpHeaders { get; set; } + public bool MakeTypesInternal + { + get { return makeTypesInternal; } + set + { + makeTypesInternal = value; + OnPropertyChanged(); + } + } [DataMember] - public bool EnableNamingAlias { get; set; } + public bool OpenGeneratedFilesInIDE + { + get { return openGeneratedFilesInIDE; } + set + { + openGeneratedFilesInIDE = value; + OnPropertyChanged(); + } + } [DataMember] - public bool IgnoreUnexpectedElementsAndAttributes { get; set; } + public bool GenerateMultipleFiles + { + get { return generateMultipleFiles; } + set + { + generateMultipleFiles = value; + OnPropertyChanged(); + } + } + + [IgnoreDataMember] // Do not serialize - may contain authentication tokens + public string CustomHttpHeaders + { + get { return customHttpHeaders; } + set + { + customHttpHeaders = value; + OnPropertyChanged(); + } + } [DataMember] - public bool IncludeT4File { get; set; } + public bool EnableNamingAlias + { + get { return enableNamingAlias; } + set + { + enableNamingAlias = value; + OnPropertyChanged(); + } + } [DataMember] - public bool IncludeWebProxy { get; set; } + public bool IgnoreUnexpectedElementsAndAttributes + { + get { return ignoreUnexpectedElementsAndAttributes; } + set + { + ignoreUnexpectedElementsAndAttributes = value; + OnPropertyChanged(); + } + } [DataMember] - public string WebProxyHost { get; set; } + public bool IncludeT4File + { + get { return includeT4File; } + set + { + includeT4File = value; + OnPropertyChanged(); + } + } [DataMember] - public bool IncludeWebProxyNetworkCredentials { get; set; } + public bool IncludeWebProxy + { + get { return includeWebProxy; } + set + { + includeWebProxy = value; + OnPropertyChanged(); + } + } [DataMember] - public string WebProxyNetworkCredentialsUsername { get; set; } + public string WebProxyHost + { + get { return webProxyHost; } + set + { + webProxyHost = value; + OnPropertyChanged(); + } + } [DataMember] - public string WebProxyNetworkCredentialsPassword { get; set; } + public bool IncludeWebProxyNetworkCredentials + { + get { return includeWebProxyNetworkCredentials; } + set + { + includeWebProxyNetworkCredentials = value; + OnPropertyChanged(); + } + } + + [IgnoreDataMember] // Do not serialize - security consideration + public string WebProxyNetworkCredentialsUsername + { + get { return webProxyNetworkCredentialsUsername; } + set + { + webProxyNetworkCredentialsUsername = value; + OnPropertyChanged(); + } + } + + [IgnoreDataMember] // Do not serialize - security consideration + public string WebProxyNetworkCredentialsPassword + { + get { return webProxyNetworkCredentialsPassword; } + set + { + webProxyNetworkCredentialsPassword = value; + OnPropertyChanged(); + } + } [DataMember] - public string WebProxyNetworkCredentialsDomain { get; set; } + public string WebProxyNetworkCredentialsDomain + { + get { return webProxyNetworkCredentialsDomain; } + set + { + webProxyNetworkCredentialsDomain = value; + OnPropertyChanged(); + } + } [DataMember] - public bool IncludeCustomHeaders { get; set; } + public bool IncludeCustomHeaders + { + get { return includeCustomHeaders; } + set + { + includeCustomHeaders = value; + OnPropertyChanged(); + } + } [DataMember] - public List ExcludedOperationImports { get; set; } + public List ExcludedOperationImports + { + get { return excludedOperationImports; } + set + { + excludedOperationImports = value; + OnPropertyChanged(); + } + } [DataMember] - public List ExcludedBoundOperations { get; set; } + public List ExcludedBoundOperations + { + get { return excludedBoundOperations; } + set + { + excludedBoundOperations = value; + OnPropertyChanged(); + } + } [DataMember] - public List ExcludedSchemaTypes { get; set; } + public List ExcludedSchemaTypes + { + get { return excludedSchemaTypes; } + set + { + excludedSchemaTypes = value; + OnPropertyChanged(); + } + } - public UserSettings() + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { - this.MruEndpoints = new ObservableCollection(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + /// + /// Initializes a new instance of the class. + /// + /// The logger to use. + /// The name to use for the config file. + public UserSettings(ConnectedServiceLogger logger, string configName = "Settings") + { + this.configName = configName; + this.logger = logger; + // Desired defaults + GeneratedFileNamePrefix = Constants.DefaultReferenceFileName; + NamespacePrefix = Constants.DefaultReferenceFileName; + ServiceName = Constants.DefaultServiceName; + UseDataServiceCollection = true; // To support entity and property tracking + EnableNamingAlias = true; // To force upper camel case in the event that entities are named in lower camel case + IgnoreUnexpectedElementsAndAttributes = true; // Ignore unexpected elements and attributes in the metadata document + ExcludedBoundOperations = new List(); + ExcludedOperationImports = new List(); + ExcludedSchemaTypes = new List(); + MruEndpoints = new ObservableCollection(); + UserSettingsPersistenceHelper.Load( + providerId: Constants.ProviderId, + name: configName, + onLoaded: (userSettings) => + { + // onLoaded action is currently triggered only if settings are loaded from config file + // Do this defensively all the same... + if (userSettings != null) + { + foreach (var mruEndpoint in userSettings.MruEndpoints) + { + MruEndpoints.Add(mruEndpoint); + } + } + }, + logger: logger); + } + + /// + /// Initializes a new instance of the class. + /// + /// The name to use for the config file. + [JsonConstructor] // Constructor should be used to create a class during deserialization + public UserSettings(string configName = "Settings") + : this(null, configName) + { + } + + /// + /// Saves user settings to config file. + /// public void Save() { - UserSettingsPersistenceHelper.Save(this, Constants.ProviderId, UserSettings.Name, null, this.logger); + UserSettingsPersistenceHelper.Save(this, Constants.ProviderId, configName, null, logger); } - public static UserSettings Load(ConnectedServiceLogger logger) + /// + /// Loads user settings from config file. + /// + public void Load() { var userSettings = UserSettingsPersistenceHelper.Load( - Constants.ProviderId, UserSettings.Name, null, logger) ?? new UserSettings(); - userSettings.logger = logger; + Constants.ProviderId, configName, null, logger); - return userSettings; + if (userSettings != null) + { + this.CopyPropertiesFrom(userSettings); + } } - public static void AddToTopOfMruList(ObservableCollection mruList, T item) + /// + /// Adds endpoint to the most recently used endpoints collection. + /// + /// Endpoint + public void AddMruEndpoint(string mruEndpoint) { - if (mruList == null) + if (string.IsNullOrWhiteSpace(mruEndpoint)) { return; } - var index = mruList.IndexOf(item); + var index = MruEndpoints.IndexOf(mruEndpoint); + if (index >= 0) { - // Ensure there aren't any duplicates in the list. - for (var i = mruList.Count - 1; i > index; i--) + // Remove possible duplicates + for (var i = MruEndpoints.Count - 1; index > 0 && i > index; i--) { - if (EqualityComparer.Default.Equals(mruList[i], item)) + if (MruEndpoints[i].Equals(mruEndpoint, StringComparison.Ordinal)) { - mruList.RemoveAt(i); + MruEndpoints.RemoveAt(i); } } + // Endpoint not at index 0 if (index > 0) { - // The item is in the MRU list but it is not at the top. - mruList.Move(index, 0); + MruEndpoints.Move(index, 0); } } else { - // The item is not in the MRU list, make room for it by clearing out the oldest item. - while (mruList.Count >= UserSettings.MaxMruEntries) + while (MruEndpoints.Count >= MaxMruEntries) { - mruList.RemoveAt(mruList.Count - 1); + MruEndpoints.RemoveAt(MruEndpoints.Count - 1); } - mruList.Insert(0, item); + MruEndpoints.Insert(0, mruEndpoint); } } } diff --git a/src/ODataConnectedService.csproj b/src/ODataConnectedService.csproj index 609c7a46..50822301 100644 --- a/src/ODataConnectedService.csproj +++ b/src/ODataConnectedService.csproj @@ -190,6 +190,7 @@ + diff --git a/src/ODataConnectedServiceWizard.cs b/src/ODataConnectedServiceWizard.cs index c0036bcf..94e08f0d 100644 --- a/src/ODataConnectedServiceWizard.cs +++ b/src/ODataConnectedServiceWizard.cs @@ -32,15 +32,13 @@ internal class ODataConnectedServiceWizard : ConnectedServiceWizard public ConnectedServiceProviderContext Context { get; set; } - public ODataConnectedServiceInstance ServiceInstance => this.serviceInstance ?? (this.serviceInstance = new ODataConnectedServiceInstance()); + public ODataConnectedServiceInstance ServiceInstance => serviceInstance ?? (serviceInstance = new ODataConnectedServiceInstance()); - public Version EdmxVersion => this.ConfigODataEndpointViewModel.EdmxVersion; + public Version EdmxVersion => ConfigODataEndpointViewModel.EdmxVersion; - public UserSettings UserSettings { get; } + public UserSettings UserSettings { get; internal set; } - private readonly ServiceConfigurationV4 _serviceConfig; - - public ServiceConfigurationV4 ServiceConfig { get { return _serviceConfig; } } + public ServiceConfigurationV4 ServiceConfig { get; private set; } internal string ProcessedEndpointForOperationImports; @@ -48,74 +46,73 @@ internal class ODataConnectedServiceWizard : ConnectedServiceWizard public ODataConnectedServiceWizard(ConnectedServiceProviderContext context) { - this.Context = context; - this.UserSettings = UserSettings.Load(context?.Logger); + Context = context; + // We only use most recently used endpoints from the config file saved in user's isolated storage + // The UserSettings constructor will load those endpoints + UserSettings = new UserSettings(context?.Logger); - // Since ServiceConfigurationV4 is a derived type of ServiceConfiguration. So we can deserialize a ServiceConfiguration into a ServiceConfigurationV4. - this._serviceConfig = this.Context?.GetExtendedDesignerData(); + // Since ServiceConfigurationV4 is a derived type of ServiceConfiguration, + // we can deserialize a ServiceConfiguration into a ServiceConfigurationV4. + ServiceConfig = Context?.GetExtendedDesignerData(); - ConfigODataEndpointViewModel = new ConfigODataEndpointViewModel(this.UserSettings, this); - AdvancedSettingsViewModel = new AdvancedSettingsViewModel(this.UserSettings); - SchemaTypesViewModel = new SchemaTypesViewModel(this.UserSettings); + ConfigODataEndpointViewModel = new ConfigODataEndpointViewModel(UserSettings); + AdvancedSettingsViewModel = new AdvancedSettingsViewModel(UserSettings); + SchemaTypesViewModel = new SchemaTypesViewModel(UserSettings); + OperationImportsViewModel = new OperationImportsViewModel(UserSettings); - OperationImportsViewModel = new OperationImportsViewModel(this.UserSettings); OperationImportsViewModel.PageEntering += OperationImportsViewModel_PageEntering; - SchemaTypesViewModel.PageEntering += SchemaTypeSelectionViewModel_PageEntering; SchemaTypesViewModel.PageLeaving += SchemaTypeSelectionViewModel_PageLeaving; - if (this.Context != null && this.Context.IsUpdating) + + if (Context != null && Context.IsUpdating) { - ConfigODataEndpointViewModel.Endpoint = this._serviceConfig?.Endpoint; - ConfigODataEndpointViewModel.EdmxVersion = this._serviceConfig?.EdmxVersion; - ConfigODataEndpointViewModel.ServiceName = this._serviceConfig?.ServiceName; - ConfigODataEndpointViewModel.CustomHttpHeaders = this._serviceConfig?.CustomHttpHeaders; + LoadUserSettingsFromServiceConfig(); + ConfigODataEndpointViewModel.EdmxVersion = ServiceConfig?.EdmxVersion; // Restore the main settings to UI elements. ConfigODataEndpointViewModel.PageEntering += ConfigODataEndpointViewModel_PageEntering; - // The ViewModel should always be filled otherwise if the wizard is completed without visiting this page the generated code becomes wrong AdvancedSettingsViewModel_PageEntering(AdvancedSettingsViewModel, EventArgs.Empty); - // Restore the advanced settings to UI elements. AdvancedSettingsViewModel.PageEntering += AdvancedSettingsViewModel_PageEntering; } - this.Pages.Add(ConfigODataEndpointViewModel); - this.Pages.Add(SchemaTypesViewModel); - this.Pages.Add(OperationImportsViewModel); - this.Pages.Add(AdvancedSettingsViewModel); - this.IsFinishEnabled = true; + Pages.Add(ConfigODataEndpointViewModel); + Pages.Add(SchemaTypesViewModel); + Pages.Add(OperationImportsViewModel); + Pages.Add(AdvancedSettingsViewModel); + IsFinishEnabled = true; } public override async Task GetFinishedServiceInstanceAsync() { // ensure that the data has been loaded from wizard pages and saved to UserSettings - if (this.Context.IsUpdating) + if (Context.IsUpdating) { - if (!this.OperationImportsViewModel.IsEntered) + if (!OperationImportsViewModel.IsEntered) { await OperationImportsViewModel.OnPageEnteringAsync(null).ConfigureAwait(false); await OperationImportsViewModel.OnPageLeavingAsync(null).ConfigureAwait(false); } - if (!this.SchemaTypesViewModel.IsEntered) + if (!SchemaTypesViewModel.IsEntered) { await SchemaTypesViewModel.OnPageEnteringAsync(null).ConfigureAwait(false); await SchemaTypesViewModel.OnPageLeavingAsync(null).ConfigureAwait(false); } - if (!this.AdvancedSettingsViewModel.IsEntered) + if (!AdvancedSettingsViewModel.IsEntered) { await AdvancedSettingsViewModel.OnPageEnteringAsync(null).ConfigureAwait(false); await AdvancedSettingsViewModel.OnPageLeavingAsync(null).ConfigureAwait(false); } } - this.UserSettings.Save(); - this.ServiceInstance.InstanceId = AdvancedSettingsViewModel.GeneratedFileNamePrefix; - this.ServiceInstance.Name = ConfigODataEndpointViewModel.ServiceName; - this.ServiceInstance.MetadataTempFilePath = ConfigODataEndpointViewModel.MetadataTempPath; - this.ServiceInstance.ServiceConfig = this.CreateServiceConfiguration(); + UserSettings.Save(); + ServiceInstance.InstanceId = UserSettings.GeneratedFileNamePrefix; + ServiceInstance.Name = UserSettings.ServiceName; + ServiceInstance.MetadataTempFilePath = ConfigODataEndpointViewModel.MetadataTempPath; + ServiceInstance.ServiceConfig = CreateServiceConfiguration(); return await Task.FromResult(ServiceInstance).ConfigureAwait(false); } @@ -127,50 +124,38 @@ public override async Task GetFinishedServiceInstanceA private ServiceConfiguration CreateServiceConfiguration() { ServiceConfiguration serviceConfiguration; - if (ConfigODataEndpointViewModel.EdmxVersion == Common.Constants.EdmxVersion4) + + if (ConfigODataEndpointViewModel.EdmxVersion == Constants.EdmxVersion4) { - var serviceConfigurationV4 = new ServiceConfigurationV4 - { - ExcludedOperationImports = OperationImportsViewModel.ExcludedOperationImportsNames.ToList(), - ExcludedBoundOperations = SchemaTypesViewModel.ExcludedBoundOperationsNames.ToList(), - IgnoreUnexpectedElementsAndAttributes = - AdvancedSettingsViewModel.IgnoreUnexpectedElementsAndAttributes, - EnableNamingAlias = AdvancedSettingsViewModel.EnableNamingAlias, - IncludeT4File = AdvancedSettingsViewModel.IncludeT4File, - OpenGeneratedFilesInIDE = AdvancedSettingsViewModel.OpenGeneratedFilesInIDE - }; + var serviceConfigurationV4 = new ServiceConfigurationV4(); + serviceConfigurationV4.CopyPropertiesFrom(UserSettings); + + serviceConfigurationV4.ExcludedOperationImports = OperationImportsViewModel.ExcludedOperationImportsNames.ToList(); + serviceConfigurationV4.ExcludedBoundOperations = SchemaTypesViewModel.ExcludedBoundOperationsNames.ToList(); + serviceConfiguration = serviceConfigurationV4; } else { serviceConfiguration = new ServiceConfiguration(); + + serviceConfiguration.CopyPropertiesFrom(UserSettings); } serviceConfiguration.ExcludedSchemaTypes = SchemaTypesViewModel.ExcludedSchemaTypeNames.ToList(); - serviceConfiguration.ServiceName = ConfigODataEndpointViewModel.ServiceName; - serviceConfiguration.Endpoint = ConfigODataEndpointViewModel.Endpoint; serviceConfiguration.EdmxVersion = ConfigODataEndpointViewModel.EdmxVersion; - serviceConfiguration.CustomHttpHeaders = ConfigODataEndpointViewModel.CustomHttpHeaders; - serviceConfiguration.IncludeWebProxy = ConfigODataEndpointViewModel.IncludeWebProxy; - serviceConfiguration.WebProxyHost = ConfigODataEndpointViewModel.WebProxyHost; - serviceConfiguration.IncludeWebProxyNetworkCredentials = ConfigODataEndpointViewModel.IncludeWebProxyNetworkCredentials; - serviceConfiguration.WebProxyNetworkCredentialsUsername = ConfigODataEndpointViewModel.WebProxyNetworkCredentialsUsername; - serviceConfiguration.WebProxyNetworkCredentialsPassword = ConfigODataEndpointViewModel.WebProxyNetworkCredentialsPassword; - serviceConfiguration.WebProxyNetworkCredentialsDomain = ConfigODataEndpointViewModel.WebProxyNetworkCredentialsDomain; - serviceConfiguration.IncludeCustomHeaders = ConfigODataEndpointViewModel.IncludeCustomHeaders; - serviceConfiguration.UseDataServiceCollection = AdvancedSettingsViewModel.UseDataServiceCollection; - serviceConfiguration.GeneratedFileNamePrefix = AdvancedSettingsViewModel.GeneratedFileNamePrefix; - serviceConfiguration.UseNamespacePrefix = AdvancedSettingsViewModel.UseNamespacePrefix; - serviceConfiguration.MakeTypesInternal = AdvancedSettingsViewModel.MakeTypesInternal; - serviceConfiguration.OpenGeneratedFilesInIDE = AdvancedSettingsViewModel.OpenGeneratedFilesInIDE; - serviceConfiguration.GenerateMultipleFiles = AdvancedSettingsViewModel.GenerateMultipleFiles; - - if (AdvancedSettingsViewModel.UseNamespacePrefix && !string.IsNullOrEmpty(AdvancedSettingsViewModel.NamespacePrefix)) + + return serviceConfiguration; + } + + private void LoadUserSettingsFromServiceConfig() + { + if (ServiceConfig == null) { - serviceConfiguration.NamespacePrefix = AdvancedSettingsViewModel.NamespacePrefix; + return; } - return serviceConfiguration; + UserSettings.CopyPropertiesFrom(ServiceConfig); } #region "Event Handlers" @@ -183,19 +168,9 @@ public void ConfigODataEndpointViewModel_PageEntering(object sender, EventArgs a { configOdataView.Endpoint.IsEnabled = false; configOdataView.OpenConnectedServiceJsonFileButton.IsEnabled = false; - configOdataView.OpenEndpointFileButton.IsEnabled = !this._serviceConfig.Endpoint.StartsWith("http", StringComparison.OrdinalIgnoreCase); + configOdataView.OpenEndpointFileButton.IsEnabled = !ServiceConfig.Endpoint.StartsWith("http", StringComparison.OrdinalIgnoreCase); configOdataView.ServiceName.IsEnabled = false; } - - configOdataViewModel.IncludeCustomHeaders = this._serviceConfig.IncludeCustomHeaders; - configOdataViewModel.IncludeWebProxy = this._serviceConfig.IncludeWebProxy; - configOdataViewModel.WebProxyHost = this._serviceConfig.WebProxyHost; - configOdataViewModel.IncludeWebProxyNetworkCredentials = this._serviceConfig.IncludeWebProxyNetworkCredentials; - configOdataViewModel.WebProxyNetworkCredentialsDomain = this._serviceConfig.WebProxyNetworkCredentialsDomain; - - // don't accept any credentials from the restored settings - configOdataViewModel.WebProxyNetworkCredentialsUsername = null; - configOdataViewModel.WebProxyNetworkCredentialsPassword = null; } } @@ -205,22 +180,12 @@ public void AdvancedSettingsViewModel_PageEntering(object sender, EventArgs args { if (advancedSettingsViewModel.View is AdvancedSettings advancedSettings) { - advancedSettingsViewModel.GeneratedFileNamePrefix = this._serviceConfig.GeneratedFileNamePrefix; - advancedSettings.ReferenceFileName.IsEnabled = !this.Context.IsUpdating; - advancedSettingsViewModel.UseNamespacePrefix = this._serviceConfig.UseNamespacePrefix; - advancedSettingsViewModel.NamespacePrefix = this._serviceConfig.NamespacePrefix ?? Common.Constants.DefaultReferenceFileName; - advancedSettingsViewModel.UseDataServiceCollection = this._serviceConfig.UseDataServiceCollection; - advancedSettingsViewModel.OpenGeneratedFilesInIDE = this._serviceConfig.OpenGeneratedFilesInIDE; - advancedSettingsViewModel.GenerateMultipleFiles = this._serviceConfig.GenerateMultipleFiles; - advancedSettings.GenerateMultipleFiles.IsEnabled = !this.Context.IsUpdating; - - if (this._serviceConfig.EdmxVersion == Common.Constants.EdmxVersion4) + advancedSettings.ReferenceFileName.IsEnabled = !Context.IsUpdating; + advancedSettings.GenerateMultipleFiles.IsEnabled = !Context.IsUpdating; + + if (ServiceConfig.EdmxVersion == Constants.EdmxVersion4) { - advancedSettingsViewModel.IgnoreUnexpectedElementsAndAttributes = this._serviceConfig.IgnoreUnexpectedElementsAndAttributes; - advancedSettingsViewModel.EnableNamingAlias = this._serviceConfig.EnableNamingAlias; - advancedSettingsViewModel.IncludeT4File = this._serviceConfig.IncludeT4File; - advancedSettingsViewModel.MakeTypesInternal = this._serviceConfig.MakeTypesInternal; - advancedSettings.IncludeT4File.IsEnabled = !this.Context.IsUpdating; + advancedSettings.IncludeT4File.IsEnabled = !Context.IsUpdating; } } } @@ -230,7 +195,7 @@ public void OperationImportsViewModel_PageEntering(object sender, EventArgs args { if (sender is OperationImportsViewModel operationImportsViewModel) { - if (this.ProcessedEndpointForOperationImports != ConfigODataEndpointViewModel.Endpoint) + if (ProcessedEndpointForOperationImports != UserSettings.Endpoint) { if (ConfigODataEndpointViewModel.EdmxVersion != Constants.EdmxVersion4) { @@ -245,11 +210,11 @@ public void OperationImportsViewModel_PageEntering(object sender, EventArgs args if (Context.IsUpdating) { - operationImportsViewModel.ExcludeOperationImports(this._serviceConfig?.ExcludedOperationImports ?? Enumerable.Empty()); + operationImportsViewModel.ExcludeOperationImports(ServiceConfig?.ExcludedOperationImports ?? Enumerable.Empty()); } } - this.ProcessedEndpointForOperationImports = ConfigODataEndpointViewModel.Endpoint; + ProcessedEndpointForOperationImports = UserSettings.Endpoint; } } @@ -257,7 +222,7 @@ public void SchemaTypeSelectionViewModel_PageEntering(object sender, EventArgs a { if (sender is SchemaTypesViewModel entityTypeViewModel) { - if (this.ProcessedEndpointForSchemaTypes != ConfigODataEndpointViewModel.Endpoint) + if (ProcessedEndpointForSchemaTypes != UserSettings.Endpoint) { var model = EdmHelper.GetEdmModelFromFile(ConfigODataEndpointViewModel.MetadataTempPath); var entityTypes = EdmHelper.GetSchemaTypes(model); @@ -267,12 +232,12 @@ public void SchemaTypeSelectionViewModel_PageEntering(object sender, EventArgs a if (Context.IsUpdating) { entityTypeViewModel.ExcludeSchemaTypes( - this._serviceConfig?.ExcludedSchemaTypes ?? Enumerable.Empty(), - this._serviceConfig?.ExcludedBoundOperations ?? Enumerable.Empty()); + ServiceConfig?.ExcludedSchemaTypes ?? Enumerable.Empty(), + ServiceConfig?.ExcludedBoundOperations ?? Enumerable.Empty()); } } - this.ProcessedEndpointForSchemaTypes = ConfigODataEndpointViewModel.Endpoint; + ProcessedEndpointForSchemaTypes = UserSettings.Endpoint; } } @@ -320,34 +285,34 @@ protected override void Dispose(bool disposing) { if (disposing) { - if (this.AdvancedSettingsViewModel != null) + if (AdvancedSettingsViewModel != null) { - this.AdvancedSettingsViewModel.Dispose(); - this.AdvancedSettingsViewModel = null; + AdvancedSettingsViewModel.Dispose(); + AdvancedSettingsViewModel = null; } - if (this.OperationImportsViewModel != null) + if (OperationImportsViewModel != null) { - this.OperationImportsViewModel.Dispose(); + OperationImportsViewModel.Dispose(); OperationImportsViewModel = null; } - if (this.SchemaTypesViewModel != null) + if (SchemaTypesViewModel != null) { - this.SchemaTypesViewModel.Dispose(); - this.SchemaTypesViewModel = null; + SchemaTypesViewModel.Dispose(); + SchemaTypesViewModel = null; } - if (this.ConfigODataEndpointViewModel != null) + if (ConfigODataEndpointViewModel != null) { - this.ConfigODataEndpointViewModel.Dispose(); - this.ConfigODataEndpointViewModel = null; + ConfigODataEndpointViewModel.Dispose(); + ConfigODataEndpointViewModel = null; } - if (this.serviceInstance != null) + if (serviceInstance != null) { - this.serviceInstance.Dispose(); - this.serviceInstance = null; + serviceInstance.Dispose(); + serviceInstance = null; } } } diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index 2d8190b0..9cc3cc91 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -39,8 +39,8 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.11.2.0")] -[assembly: AssemblyFileVersion("0.11.2.0")] +[assembly: AssemblyVersion("0.11.1.0")] +[assembly: AssemblyFileVersion("0.11.1.0")] [assembly: NeutralResourcesLanguageAttribute("en")] [assembly: InternalsVisibleTo("ODataConnectedService.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001003d2fbcc3c5595b4212227a5ca0fb1c45cb9c942096831420563dc169dd847a8a5fe068170bd10802dea50bc4d8342c1f8aa2ab9f27e3ceccdb21ce8c1415c3ea33eb7bc09059ca50b3e8607fa34bb9925466525ceffc3edac84ac1863afc28ef935c8db7a6430771fa41aa3de8a8d399990b02cae85e834e5d29d2cc0109b8cb")] diff --git a/src/ViewModels/AdvancedSettingsViewModel.cs b/src/ViewModels/AdvancedSettingsViewModel.cs index 016f1bc9..da23019b 100644 --- a/src/ViewModels/AdvancedSettingsViewModel.cs +++ b/src/ViewModels/AdvancedSettingsViewModel.cs @@ -15,27 +15,7 @@ namespace Microsoft.OData.ConnectedService.ViewModels { internal class AdvancedSettingsViewModel : ConnectedServiceWizardPage { - public bool UseDataServiceCollection { get; set; } - - public bool UseNamespacePrefix { get; set; } - - public string NamespacePrefix { get; set; } - - public bool EnableNamingAlias { get; set; } - - public bool IgnoreUnexpectedElementsAndAttributes { get; set; } - - public string GeneratedFileNamePrefix { get; set; } - - public bool IncludeT4File { get; set; } - - public bool MakeTypesInternal { get; set; } - - public bool OpenGeneratedFilesInIDE { get; set; } - - public bool GenerateMultipleFiles { get; set; } - - public UserSettings UserSettings { get; set; } + public UserSettings UserSettings { get; internal set; } internal bool IsEntered; @@ -45,8 +25,6 @@ public AdvancedSettingsViewModel(UserSettings userSettings) : base() this.Description = "Advanced settings for generating client proxy"; this.Legend = "Settings"; this.UserSettings = userSettings; - this.GeneratedFileNamePrefix = Common.Constants.DefaultReferenceFileName; - this.NamespacePrefix = Common.Constants.DefaultReferenceFileName; } public event EventHandler PageEntering; @@ -61,42 +39,7 @@ public override async Task OnPageEnteringAsync(WizardEnteringArgs args) public override Task OnPageLeavingAsync(WizardLeavingArgs args) { - SaveToUserSettings(); return base.OnPageLeavingAsync(args); } - - private void SaveToUserSettings() - { - if (this.UserSettings != null) - { - UserSettings.GeneratedFileNamePrefix = this.GeneratedFileNamePrefix; - UserSettings.OpenGeneratedFilesInIDE = this.OpenGeneratedFilesInIDE; - UserSettings.UseNamespacePrefix = this.UseNamespacePrefix; - UserSettings.NamespacePrefix = this.NamespacePrefix; - UserSettings.UseDataServiceCollection = this.UseDataServiceCollection; - UserSettings.MakeTypesInternal = this.MakeTypesInternal; - UserSettings.IncludeT4File = this.IncludeT4File; - UserSettings.IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes; - UserSettings.EnableNamingAlias = this.EnableNamingAlias; - UserSettings.GenerateMultipleFiles = this.GenerateMultipleFiles; - } - } - - public void LoadFromUserSettings() - { - if (UserSettings != null) - { - this.GeneratedFileNamePrefix = UserSettings.GeneratedFileNamePrefix ?? Common.Constants.DefaultReferenceFileName; - this.OpenGeneratedFilesInIDE = UserSettings.OpenGeneratedFilesInIDE; - this.UseNamespacePrefix = UserSettings.UseNamespacePrefix; - this.NamespacePrefix = UserSettings.NamespacePrefix ?? Common.Constants.DefaultReferenceFileName; - this.UseDataServiceCollection = UserSettings.UseDataServiceCollection; - this.MakeTypesInternal = UserSettings.MakeTypesInternal; - this.IncludeT4File = UserSettings.IncludeT4File; - this.IgnoreUnexpectedElementsAndAttributes = UserSettings.IgnoreUnexpectedElementsAndAttributes; - this.EnableNamingAlias = UserSettings.EnableNamingAlias; - this.GenerateMultipleFiles = UserSettings.GenerateMultipleFiles; - } - } } } diff --git a/src/ViewModels/ConfigODataEndpointViewModel.cs b/src/ViewModels/ConfigODataEndpointViewModel.cs index e5b4b656..4b9a5f0e 100644 --- a/src/ViewModels/ConfigODataEndpointViewModel.cs +++ b/src/ViewModels/ConfigODataEndpointViewModel.cs @@ -20,44 +20,20 @@ namespace Microsoft.OData.ConnectedService.ViewModels { internal class ConfigODataEndpointViewModel : ConnectedServiceWizardPage { - public string Endpoint { get; set; } - - public string ServiceName { get; set; } - public Version EdmxVersion { get; set; } public string MetadataTempPath { get; set; } - public string CustomHttpHeaders { get; set; } - - public UserSettings UserSettings { get; set; } - - public bool IncludeWebProxy { get; set; } - - public string WebProxyHost { get; set; } - - public bool IncludeWebProxyNetworkCredentials { get; set; } - - public string WebProxyNetworkCredentialsUsername { get; set; } - - public string WebProxyNetworkCredentialsPassword { get; set; } - - public string WebProxyNetworkCredentialsDomain { get; set; } - - public bool IncludeCustomHeaders { get; set; } + public UserSettings UserSettings { get; internal set; } public event EventHandler PageEntering; - public ODataConnectedServiceWizard ServiceWizard { get; set; } - - public ConfigODataEndpointViewModel(UserSettings userSettings, ODataConnectedServiceWizard serviceWizard) : base() + public ConfigODataEndpointViewModel(UserSettings userSettings) : base() { this.Title = "Configure endpoint"; this.Description = "Enter or choose an OData service endpoint to begin"; this.Legend = "Endpoint"; - this.ServiceWizard = serviceWizard; this.UserSettings = userSettings; - this.ServiceName = Constants.DefaultServiceName; } public override async Task OnPageEnteringAsync(WizardEnteringArgs args) { @@ -67,14 +43,14 @@ public override async Task OnPageEnteringAsync(WizardEnteringArgs args) } public event EventHandler PageLeaving; + public override Task OnPageLeavingAsync(WizardLeavingArgs args) { - SaveToUserSettings(); - var wizard = this.Wizard as ODataConnectedServiceWizard; - UserSettings.AddToTopOfMruList(wizard?.UserSettings?.MruEndpoints, this.Endpoint); try { this.MetadataTempPath = GetMetadata(out var version); + // Makes sense to add MRU endpoint at this point since GetMetadata manipulates UserSettings.Endpoint + UserSettings.AddMruEndpoint(UserSettings.Endpoint); this.EdmxVersion = version; PageLeaving?.Invoke(this, EventArgs.Empty); return base.OnPageLeavingAsync(args); @@ -93,28 +69,28 @@ public override Task OnPageLeavingAsync(WizardLeavingArgs internal string GetMetadata(out Version edmxVersion) { - if (string.IsNullOrEmpty(this.Endpoint)) + if (string.IsNullOrEmpty(UserSettings.Endpoint)) { throw new ArgumentNullException("OData Service Endpoint", string.Format(CultureInfo.InvariantCulture, Constants.InputServiceEndpointMsg)); } - if (this.Endpoint.StartsWith("https:", StringComparison.Ordinal) - || this.Endpoint.StartsWith("http", StringComparison.Ordinal)) + if (UserSettings.Endpoint.StartsWith("https:", StringComparison.Ordinal) + || UserSettings.Endpoint.StartsWith("http", StringComparison.Ordinal)) { - if (!this.Endpoint.EndsWith("$metadata", StringComparison.Ordinal)) + if (!UserSettings.Endpoint.EndsWith("$metadata", StringComparison.Ordinal)) { - this.Endpoint = this.Endpoint.TrimEnd('/') + "/$metadata"; + UserSettings.Endpoint = UserSettings.Endpoint.TrimEnd('/') + "/$metadata"; } } Stream metadataStream; - var metadataUri = new Uri(this.Endpoint); + var metadataUri = new Uri(UserSettings.Endpoint); if (!metadataUri.IsFile) { var webRequest = (HttpWebRequest)WebRequest.Create(metadataUri); - if (this.CustomHttpHeaders != null) + if (UserSettings.CustomHttpHeaders != null) { - var headerElements = this.CustomHttpHeaders.Split(new [] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + var headerElements = UserSettings.CustomHttpHeaders.Split(new [] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (var headerElement in headerElements) { // Trim header for empty spaces @@ -123,12 +99,15 @@ internal string GetMetadata(out Version edmxVersion) } } - if (IncludeWebProxy) + if (UserSettings.IncludeWebProxy) { - var proxy = new WebProxy(WebProxyHost); - if (IncludeWebProxyNetworkCredentials) + var proxy = new WebProxy(UserSettings.WebProxyHost); + if (UserSettings.IncludeWebProxyNetworkCredentials) { - proxy.Credentials = new NetworkCredential(WebProxyNetworkCredentialsUsername, WebProxyNetworkCredentialsPassword, WebProxyNetworkCredentialsDomain); + proxy.Credentials = new NetworkCredential( + UserSettings.WebProxyNetworkCredentialsUsername, + UserSettings.WebProxyNetworkCredentialsPassword, + UserSettings.WebProxyNetworkCredentialsDomain); } webRequest.Proxy = proxy; @@ -174,7 +153,7 @@ internal string GetMetadata(out Version edmxVersion) } catch (WebException e) { - throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Cannot access {0}", this.Endpoint), e); + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Cannot access {0}", UserSettings.Endpoint), e); } finally { @@ -182,41 +161,6 @@ internal string GetMetadata(out Version edmxVersion) } } - private void SaveToUserSettings() - { - if (this.UserSettings != null) - { - UserSettings.ServiceName = this.ServiceName; - UserSettings.Endpoint = this.Endpoint; - UserSettings.WebProxyHost = this.WebProxyHost; - UserSettings.CustomHttpHeaders = this.CustomHttpHeaders; - UserSettings.WebProxyNetworkCredentialsDomain = this.WebProxyNetworkCredentialsDomain; - UserSettings.WebProxyNetworkCredentialsPassword = this.WebProxyNetworkCredentialsPassword; - UserSettings.WebProxyNetworkCredentialsUsername = this.WebProxyNetworkCredentialsUsername; - UserSettings.IncludeCustomHeaders = this.IncludeCustomHeaders; - UserSettings.IncludeWebProxy = this.IncludeWebProxy; - UserSettings.IncludeWebProxyNetworkCredentials = this.IncludeWebProxyNetworkCredentials; - } - } - - public void LoadFromUserSettings() - { - if (this.UserSettings != null) - { - this.ServiceName = UserSettings.ServiceName ?? Constants.DefaultServiceName; - this.Endpoint = UserSettings.Endpoint; - this.WebProxyHost = UserSettings.WebProxyHost; - this.IncludeWebProxy = UserSettings.IncludeWebProxy; - this.IncludeCustomHeaders = UserSettings.IncludeCustomHeaders; - this.CustomHttpHeaders = UserSettings.CustomHttpHeaders; - this.IncludeWebProxyNetworkCredentials = UserSettings.IncludeWebProxyNetworkCredentials; - this.WebProxyNetworkCredentialsDomain = UserSettings.WebProxyNetworkCredentialsDomain; - this.WebProxyNetworkCredentialsPassword = UserSettings.WebProxyNetworkCredentialsPassword; - this.WebProxyNetworkCredentialsUsername = UserSettings.WebProxyNetworkCredentialsUsername; - this.View = new ConfigODataEndpoint { DataContext = this }; - } - } - private void DisposeStream(Stream stream) { stream?.Dispose(); diff --git a/src/ViewModels/OperationImportsViewModel.cs b/src/ViewModels/OperationImportsViewModel.cs index 50917949..d72032f4 100644 --- a/src/ViewModels/OperationImportsViewModel.cs +++ b/src/ViewModels/OperationImportsViewModel.cs @@ -29,7 +29,7 @@ internal class OperationImportsViewModel: ConnectedServiceWizardPage /// /// /// - public UserSettings UserSettings { get; set; } + public UserSettings UserSettings { get; internal set; } private long _operationImportsCount = 0; diff --git a/src/Views/AdvancedSettings.xaml b/src/Views/AdvancedSettings.xaml index 221e7604..523418ca 100644 --- a/src/Views/AdvancedSettings.xaml +++ b/src/Views/AdvancedSettings.xaml @@ -15,7 +15,7 @@ - @@ -28,33 +28,33 @@ - Use a custom namespace (It will replace the original namespace in the metadata document, unless the model has several namespaces.) - - - - Ignore unknown elements (Whether to ignore unexpected elements and attributes in the metadata document and generate the client code if any.) - Make generated types internal (Enable this if you don't want to expose the generated types outside of your assembly.) - - - diff --git a/src/Views/ConfigODataEndpoint.xaml b/src/Views/ConfigODataEndpoint.xaml index 4590586a..abf648a5 100644 --- a/src/Views/ConfigODataEndpoint.xaml +++ b/src/Views/ConfigODataEndpoint.xaml @@ -38,7 +38,7 @@ Height="20" Margin="0,5,10,5" HorizontalAlignment="Left" - Text="{Binding Path=ServiceName, Mode=TwoWay}" /> + Text="{Binding Path=UserSettings.ServiceName, Mode=TwoWay}" />