From 7994f5c326080d7e5ab155d2f253798ee8724a72 Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle Date: Mon, 4 Apr 2022 14:47:54 +0200 Subject: [PATCH] Add nullability to Web.Website, Sqlite & SqlServer --- .../SqlLocalDbDatabaseProviderMetadata.cs | 2 +- .../SqlServerDistributedLockingMechanism.cs | 15 +++- .../Services/SqlServerSyntaxProvider.cs | 10 +-- .../SqliteDatabaseProviderMetadata.cs | 2 +- .../SqliteDistributedLockingMechanism.cs | 15 +++- ...itePreferDeferredTransactionsConnection.cs | 3 + .../Services/SqliteSyntaxProvider.cs | 22 ++--- src/Umbraco.Core/Models/ContentTypeBase.cs | 2 +- .../Models/ContentTypeCompositionBase.cs | 2 +- src/Umbraco.Core/Models/IContentTypeBase.cs | 2 +- src/Umbraco.Core/Models/IMemberType.cs | 2 +- .../Models/MemberPropertyModel.cs | 2 +- src/Umbraco.Core/Models/MemberType.cs | 4 +- src/Umbraco.Core/Models/PropertyCollection.cs | 4 +- src/Umbraco.Core/Routing/IPublishedRouter.cs | 2 +- src/Umbraco.Core/Routing/PublishedRouter.cs | 2 +- .../BackOfficeExternalLoginProviderErrors.cs | 2 +- .../FaultHandling/RetryPolicyFactory.cs | 8 +- .../EndpointRouteBuilderExtensions.cs | 4 +- .../IMemberSignInManagerExternalLogins.cs | 2 +- .../RedirectToUmbracoPageResult.cs | 16 ++-- .../ActionResults/UmbracoPageResult.cs | 11 ++- .../Controllers/RenderNoContentController.cs | 2 +- .../Controllers/SurfaceController.cs | 4 +- .../Controllers/UmbExternalLoginController.cs | 22 ++--- .../Controllers/UmbLoginController.cs | 2 +- .../Controllers/UmbLoginStatusController.cs | 2 +- .../Controllers/UmbProfileController.cs | 18 ++--- .../Controllers/UmbRegisterController.cs | 10 +-- .../UmbTwoFactorLoginController.cs | 16 ++-- .../UmbracoBuilderExtensions.cs | 2 +- .../Extensions/HtmlHelperRenderExtensions.cs | 80 ++++++++++--------- .../Extensions/LinkGeneratorExtensions.cs | 12 +-- .../BasicAuthenticationMiddleware.cs | 8 +- .../Models/MemberModelBuilderBase.cs | 6 +- .../Models/NoNodesViewModel.cs | 2 +- .../Models/ProfileModel.cs | 8 +- .../Models/ProfileModelBuilder.cs | 12 +-- .../Models/RegisterModel.cs | 10 +-- .../Models/RegisterModelBuilder.cs | 6 +- .../Routing/ControllerActionSearcher.cs | 18 ++--- .../Routing/IControllerActionSearcher.cs | 2 +- .../Routing/IPublicAccessRequestHandler.cs | 2 +- .../Routing/NotFoundSelectorPolicy.cs | 6 +- .../Routing/PublicAccessRequestHandler.cs | 22 ++--- .../Routing/UmbracoRouteValueTransformer.cs | 36 ++++----- .../Routing/UmbracoRouteValuesFactory.cs | 8 +- .../Security/MemberAuthenticationBuilder.cs | 6 +- .../Security/MemberExternalLoginsBuilder.cs | 2 +- .../ViewEngines/ProfilingViewEngine.cs | 2 +- 50 files changed, 245 insertions(+), 215 deletions(-) diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlLocalDbDatabaseProviderMetadata.cs b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlLocalDbDatabaseProviderMetadata.cs index 84e784731f..1741b8ffe1 100644 --- a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlLocalDbDatabaseProviderMetadata.cs +++ b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlLocalDbDatabaseProviderMetadata.cs @@ -37,7 +37,7 @@ public class SqlLocalDbDatabaseProviderMetadata : IDatabaseProviderMetadata public bool RequiresServer => false; /// - public string ServerPlaceholder => null; + public string? ServerPlaceholder => null; /// public bool RequiresCredentials => false; diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDistributedLockingMechanism.cs b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDistributedLockingMechanism.cs index d85ef56e3b..7c8effb2b3 100644 --- a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDistributedLockingMechanism.cs +++ b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDistributedLockingMechanism.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DistributedLocking; using Umbraco.Cms.Core.DistributedLocking.Exceptions; +using Umbraco.Cms.Core.Exceptions; using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Extensions; @@ -114,7 +115,12 @@ public class SqlServerDistributedLockingMechanism : IDistributedLockingMechanism private void ObtainReadLock() { - IUmbracoDatabase db = _parent._scopeAccessor.Value.AmbientScope.Database; + IUmbracoDatabase? db = _parent._scopeAccessor.Value.AmbientScope?.Database; + + if (db is null) + { + throw new PanicException("Could not find a database"); + } if (!db.InTransaction) { @@ -141,7 +147,12 @@ public class SqlServerDistributedLockingMechanism : IDistributedLockingMechanism private void ObtainWriteLock() { - IUmbracoDatabase db = _parent._scopeAccessor.Value.AmbientScope.Database; + IUmbracoDatabase? db = _parent._scopeAccessor.Value.AmbientScope?.Database; + + if (db is null) + { + throw new PanicException("Could not find a database"); + } if (!db.InTransaction) { diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerSyntaxProvider.cs b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerSyntaxProvider.cs index 9efb97fd6e..a4fc33d98c 100644 --- a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerSyntaxProvider.cs @@ -63,7 +63,7 @@ namespace Umbraco.Cms.Persistence.SqlServer.Services Azure = 5 } - public override DatabaseType GetUpdatedDatabaseType(DatabaseType current, string connectionString) + public override DatabaseType GetUpdatedDatabaseType(DatabaseType current, string? connectionString) { var setting = _globalSettings.Value.DatabaseFactoryServerVersion; var fromSettings = false; @@ -289,7 +289,7 @@ where tbl.[name]=@0 and col.[name]=@1;", tableName, columnName) return result > 0; } - public override string FormatColumnRename(string tableName, string oldName, string newName) + public override string FormatColumnRename(string? tableName, string? oldName, string? newName) { return string.Format(RenameColumn, tableName, oldName, newName); } @@ -412,7 +412,7 @@ where tbl.[name]=@0 and col.[name]=@1;", tableName, columnName) #region Sql Inspection - private static SqlInspectionUtilities _sqlInspector; + private static SqlInspectionUtilities? _sqlInspector; private static SqlInspectionUtilities SqlInspector => _sqlInspector ?? (_sqlInspector = new SqlInspectionUtilities()); @@ -421,13 +421,13 @@ where tbl.[name]=@0 and col.[name]=@1;", tableName, columnName) private readonly Func _getSqlText; private readonly Action _setSqlText; private readonly Func _getSqlRhs; - private readonly Action _setSqlFinal; + private readonly Action _setSqlFinal; public SqlInspectionUtilities() { (_getSqlText, _setSqlText) = ReflectionUtilities.EmitFieldGetterAndSetter("_sql"); _getSqlRhs = ReflectionUtilities.EmitFieldGetter("_rhs"); - _setSqlFinal = ReflectionUtilities.EmitFieldSetter("_sqlFinal"); + _setSqlFinal = ReflectionUtilities.EmitFieldSetter("_sqlFinal"); } public string GetSqlText(Sql sql) => _getSqlText(sql); diff --git a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDatabaseProviderMetadata.cs b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDatabaseProviderMetadata.cs index 07e6db8b8f..0b684551c7 100644 --- a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDatabaseProviderMetadata.cs +++ b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDatabaseProviderMetadata.cs @@ -34,7 +34,7 @@ public class SqliteDatabaseProviderMetadata : IDatabaseProviderMetadata public bool RequiresServer => false; /// - public string ServerPlaceholder => null; + public string? ServerPlaceholder => null; /// public bool RequiresCredentials => false; diff --git a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDistributedLockingMechanism.cs b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDistributedLockingMechanism.cs index c8c34603ab..646bc3107c 100644 --- a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDistributedLockingMechanism.cs +++ b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteDistributedLockingMechanism.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DistributedLocking; using Umbraco.Cms.Core.DistributedLocking.Exceptions; +using Umbraco.Cms.Core.Exceptions; using Umbraco.Cms.Infrastructure.Persistence; using Umbraco.Cms.Infrastructure.Scoping; using Umbraco.Extensions; @@ -112,7 +113,12 @@ public class SqliteDistributedLockingMechanism : IDistributedLockingMechanism // Mostly no-op just check that we didn't end up ReadUncommitted for real. private void ObtainReadLock() { - IUmbracoDatabase db = _parent._scopeAccessor.Value.AmbientScope.Database; + IUmbracoDatabase? db = _parent._scopeAccessor.Value.AmbientScope?.Database; + + if (db is null) + { + throw new PanicException("no database was found"); + } if (!db.InTransaction) { @@ -124,7 +130,12 @@ public class SqliteDistributedLockingMechanism : IDistributedLockingMechanism // lock occurs for entire database as opposed to row/table. private void ObtainWriteLock() { - IUmbracoDatabase db = _parent._scopeAccessor.Value.AmbientScope.Database; + IUmbracoDatabase? db = _parent._scopeAccessor.Value.AmbientScope?.Database; + + if (db is null) + { + throw new PanicException("no database was found"); + } if (!db.InTransaction) { diff --git a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqlitePreferDeferredTransactionsConnection.cs b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqlitePreferDeferredTransactionsConnection.cs index e4cee692a2..4e126056d6 100644 --- a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqlitePreferDeferredTransactionsConnection.cs +++ b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqlitePreferDeferredTransactionsConnection.cs @@ -1,5 +1,6 @@ using System.Data; using System.Data.Common; +using System.Diagnostics.CodeAnalysis; using Microsoft.Data.Sqlite; namespace Umbraco.Cms.Persistence.Sqlite.Services; @@ -40,6 +41,7 @@ public class SqlitePreferDeferredTransactionsConnection : DbConnection protected override DbCommand CreateDbCommand() => new CommandWrapper(_inner.CreateCommand()); + [AllowNull] public override string ConnectionString { get => _inner.ConnectionString; @@ -67,6 +69,7 @@ public class SqlitePreferDeferredTransactionsConnection : DbConnection public override void Prepare() => _inner.Prepare(); + [AllowNull] public override string CommandText { get => _inner.CommandText; diff --git a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteSyntaxProvider.cs b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteSyntaxProvider.cs index cc9d1ff279..be6f013f26 100644 --- a/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteSyntaxProvider.cs +++ b/src/Umbraco.Cms.Persistence.Sqlite/Services/SqliteSyntaxProvider.cs @@ -127,7 +127,7 @@ public class SqliteSyntaxProvider : SqlSyntaxProviderBase public override string GetSpecialDbType(SpecialDbType dbType, int customSize) => GetSpecialDbType(dbType); /// - public override bool TryGetDefaultConstraint(IDatabase db, string tableName, string columnName, + public override bool TryGetDefaultConstraint(IDatabase db, string? tableName, string columnName, out string constraintName) { // TODO: SQLite @@ -135,8 +135,8 @@ public class SqliteSyntaxProvider : SqlSyntaxProviderBase return false; } - public override string GetFieldNameForUpdate(Expression> fieldSelector, - string tableAlias = null) + public override string GetFieldNameForUpdate(Expression> fieldSelector, + string? tableAlias = null) { var field = ExpressionHelper.FindProperty(fieldSelector).Item1 as PropertyInfo; var fieldName = GetColumnName(field!); @@ -151,7 +151,7 @@ public class SqliteSyntaxProvider : SqlSyntaxProviderBase } /// - protected override string FormatSystemMethods(SystemMethods systemMethod) + protected override string? FormatSystemMethods(SystemMethods systemMethod) { // TODO: SQLite switch (systemMethod) @@ -181,7 +181,7 @@ public class SqliteSyntaxProvider : SqlSyntaxProviderBase } public override string GetColumn(DatabaseType dbType, string tableName, string columnName, string columnAlias, - string referenceName = null, bool forInsert = false) + string? referenceName = null, bool forInsert = false) { if (forInsert) { @@ -409,16 +409,16 @@ public class SqliteSyntaxProvider : SqlSyntaxProviderBase private class SqliteMaster { - public string Type { get; set; } - public string Name { get; set; } - public string Sql { get; set; } + public string Type { get; set; } = null!; + public string Name { get; set; } = null!; + public string Sql { get; set; } = null!; } private class IndexMeta { - public string TableName { get; set; } - public string IndexName { get; set; } - public string ColumnName { get; set; } + public string TableName { get; set; } = null!; + public string IndexName { get; set; } = null!; + public string ColumnName { get; set; } = null!; public bool IsUnique { get; set; } } } diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 958caa7235..bf7cd0d8e3 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -301,7 +301,7 @@ namespace Umbraco.Cms.Core.Models /// /// Alias of the PropertyType /// Returns True if a PropertyType with the passed in alias exists, otherwise False - public abstract bool PropertyTypeExists(string alias); + public abstract bool PropertyTypeExists(string? alias); /// public abstract bool AddPropertyGroup(string alias, string name); diff --git a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs index d7f137046b..18dc1189f2 100644 --- a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs @@ -209,7 +209,7 @@ namespace Umbraco.Cms.Core.Models /// /// Alias of the PropertyType /// Returns True if a PropertyType with the passed in alias exists, otherwise False - public override bool PropertyTypeExists(string alias) => CompositionPropertyTypes.Any(x => x.Alias == alias); + public override bool PropertyTypeExists(string? alias) => CompositionPropertyTypes.Any(x => x.Alias == alias); /// public override bool AddPropertyGroup(string alias, string name) => AddAndReturnPropertyGroup(alias, name) != null; diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index 000660c54f..eb3d4489d4 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -126,7 +126,7 @@ namespace Umbraco.Cms.Core.Models /// /// Alias of the PropertyType /// Returns True if a PropertyType with the passed in alias exists, otherwise False - bool PropertyTypeExists(string alias); + bool PropertyTypeExists(string? alias); /// /// Adds the property type to the specified property group (creates a new group if not found and a name is specified). diff --git a/src/Umbraco.Core/Models/IMemberType.cs b/src/Umbraco.Core/Models/IMemberType.cs index d18b61ed98..324601efde 100644 --- a/src/Umbraco.Core/Models/IMemberType.cs +++ b/src/Umbraco.Core/Models/IMemberType.cs @@ -10,7 +10,7 @@ /// /// PropertyType Alias of the Property to check /// - bool MemberCanEditProperty(string propertyTypeAlias); + bool MemberCanEditProperty(string? propertyTypeAlias); /// /// Gets a boolean indicating whether a Property is visible on the Members profile. diff --git a/src/Umbraco.Core/Models/MemberPropertyModel.cs b/src/Umbraco.Core/Models/MemberPropertyModel.cs index cd23d01a5d..f6d06956e5 100644 --- a/src/Umbraco.Core/Models/MemberPropertyModel.cs +++ b/src/Umbraco.Core/Models/MemberPropertyModel.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.Models public class MemberPropertyModel { [Required] - public string? Alias { get; set; } + public string Alias { get; set; } = null!; //NOTE: This has to be a string currently, if it is an object it will bind as an array which we don't want. // If we want to have this as an 'object' with a true type on it, we have to create a custom model binder diff --git a/src/Umbraco.Core/Models/MemberType.cs b/src/Umbraco.Core/Models/MemberType.cs index cb74bd7e57..ab420b5a8b 100644 --- a/src/Umbraco.Core/Models/MemberType.cs +++ b/src/Umbraco.Core/Models/MemberType.cs @@ -88,9 +88,9 @@ namespace Umbraco.Cms.Core.Models /// /// PropertyType Alias of the Property to check /// - public bool MemberCanEditProperty(string propertyTypeAlias) + public bool MemberCanEditProperty(string? propertyTypeAlias) { - return _memberTypePropertyTypes.TryGetValue(propertyTypeAlias, out var propertyProfile) && propertyProfile.IsEditable; + return propertyTypeAlias is not null && _memberTypePropertyTypes.TryGetValue(propertyTypeAlias, out var propertyProfile) && propertyProfile.IsEditable; } /// diff --git a/src/Umbraco.Core/Models/PropertyCollection.cs b/src/Umbraco.Core/Models/PropertyCollection.cs index 9a8daac0c4..49b392ba67 100644 --- a/src/Umbraco.Core/Models/PropertyCollection.cs +++ b/src/Umbraco.Core/Models/PropertyCollection.cs @@ -142,13 +142,13 @@ namespace Umbraco.Cms.Core.Models { get { - return this.FirstOrDefault(x => x.Alias?.InvariantEquals(propertyType.Alias) ?? false); + return this.FirstOrDefault(x => x.Alias.InvariantEquals(propertyType.Alias)); } } public bool TryGetValue(string propertyTypeAlias, [MaybeNullWhen(false)] out IProperty property) { - property = this.FirstOrDefault(x => x.Alias?.InvariantEquals(propertyTypeAlias) ?? false); + property = this.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); return property != null; } diff --git a/src/Umbraco.Core/Routing/IPublishedRouter.cs b/src/Umbraco.Core/Routing/IPublishedRouter.cs index 5de826d222..a3c041768f 100644 --- a/src/Umbraco.Core/Routing/IPublishedRouter.cs +++ b/src/Umbraco.Core/Routing/IPublishedRouter.cs @@ -47,6 +47,6 @@ namespace Umbraco.Cms.Core.Routing /// content matched we want to run the request through the last chance finders. /// /// - Task UpdateRequestAsync(IPublishedRequest request, IPublishedContent publishedContent); + Task UpdateRequestAsync(IPublishedRequest request, IPublishedContent? publishedContent); } } diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs index aa852c10d7..87ef468cd5 100644 --- a/src/Umbraco.Core/Routing/PublishedRouter.cs +++ b/src/Umbraco.Core/Routing/PublishedRouter.cs @@ -226,7 +226,7 @@ namespace Umbraco.Cms.Core.Routing } /// - public async Task UpdateRequestAsync(IPublishedRequest request, IPublishedContent publishedContent) + public async Task UpdateRequestAsync(IPublishedRequest request, IPublishedContent? publishedContent) { // store the original (if any) IPublishedContent? content = request.PublishedContent; diff --git a/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs b/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs index 42903d2b64..c79fa87429 100644 --- a/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs +++ b/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Security { } - public BackOfficeExternalLoginProviderErrors(string authenticationType, IEnumerable errors) + public BackOfficeExternalLoginProviderErrors(string? authenticationType, IEnumerable errors) { AuthenticationType = authenticationType; Errors = errors ?? Enumerable.Empty(); diff --git a/src/Umbraco.Infrastructure/Persistence/FaultHandling/RetryPolicyFactory.cs b/src/Umbraco.Infrastructure/Persistence/FaultHandling/RetryPolicyFactory.cs index 6a4e257af7..41f2337644 100644 --- a/src/Umbraco.Infrastructure/Persistence/FaultHandling/RetryPolicyFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/FaultHandling/RetryPolicyFactory.cs @@ -9,10 +9,10 @@ namespace Umbraco.Cms.Infrastructure.Persistence.FaultHandling /// public static class RetryPolicyFactory { - public static RetryPolicy GetDefaultSqlConnectionRetryPolicyByConnectionString(string connectionString) + public static RetryPolicy GetDefaultSqlConnectionRetryPolicyByConnectionString(string? connectionString) { //Is this really the best way to determine if the database is an Azure database? - return connectionString.Contains("database.windows.net") + return connectionString?.Contains("database.windows.net") ?? false ? GetDefaultSqlAzureConnectionRetryPolicy() : GetDefaultSqlConnectionRetryPolicy(); } @@ -32,10 +32,10 @@ namespace Umbraco.Cms.Infrastructure.Persistence.FaultHandling return retryPolicy; } - public static RetryPolicy GetDefaultSqlCommandRetryPolicyByConnectionString(string connectionString) + public static RetryPolicy GetDefaultSqlCommandRetryPolicyByConnectionString(string? connectionString) { //Is this really the best way to determine if the database is an Azure database? - return connectionString.Contains("database.windows.net") + return connectionString?.Contains("database.windows.net") ?? false ? GetDefaultSqlAzureCommandRetryPolicy() : GetDefaultSqlCommandRetryPolicy(); } diff --git a/src/Umbraco.Web.Common/Extensions/EndpointRouteBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/EndpointRouteBuilderExtensions.cs index a8afeccdbb..7c0c382818 100644 --- a/src/Umbraco.Web.Common/Extensions/EndpointRouteBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/EndpointRouteBuilderExtensions.cs @@ -127,13 +127,13 @@ namespace Umbraco.Extensions this IEndpointRouteBuilder endpoints, Type controllerType, string rootSegment, - string areaName, + string? areaName, string defaultAction = "Index", bool includeControllerNameInRoute = true, object? constraints = null) { // If there is an area name it's a plugin controller, and we should use the area name instead of surface - string prefixPathSegment = areaName.IsNullOrWhiteSpace() ? "Surface" : areaName; + string prefixPathSegment = areaName.IsNullOrWhiteSpace() ? "Surface" : areaName!; endpoints.MapUmbracoRoute( controllerType, diff --git a/src/Umbraco.Web.Common/Security/IMemberSignInManagerExternalLogins.cs b/src/Umbraco.Web.Common/Security/IMemberSignInManagerExternalLogins.cs index 20fe99b30a..558fd8d86b 100644 --- a/src/Umbraco.Web.Common/Security/IMemberSignInManagerExternalLogins.cs +++ b/src/Umbraco.Web.Common/Security/IMemberSignInManagerExternalLogins.cs @@ -14,6 +14,6 @@ namespace Umbraco.Cms.Web.Common.Security Task UpdateExternalAuthenticationTokensAsync(ExternalLoginInfo externalLogin); Task ExternalLoginSignInAsync(ExternalLoginInfo loginInfo, bool isPersistent, bool bypassTwoFactor = false); Task GetTwoFactorAuthenticationUserAsync(); - Task TwoFactorSignInAsync(string provider, string code, bool isPersistent, bool rememberClient); + Task TwoFactorSignInAsync(string? provider, string? code, bool isPersistent, bool rememberClient); } } diff --git a/src/Umbraco.Web.Website/ActionResults/RedirectToUmbracoPageResult.cs b/src/Umbraco.Web.Website/ActionResults/RedirectToUmbracoPageResult.cs index 62d0dc7a10..0997b92a5c 100644 --- a/src/Umbraco.Web.Website/ActionResults/RedirectToUmbracoPageResult.cs +++ b/src/Umbraco.Web.Website/ActionResults/RedirectToUmbracoPageResult.cs @@ -17,11 +17,11 @@ namespace Umbraco.Cms.Web.Website.ActionResults /// public class RedirectToUmbracoPageResult : IActionResult, IKeepTempDataResult { - private IPublishedContent _publishedContent; + private IPublishedContent? _publishedContent; private readonly QueryString _queryString; private readonly IPublishedUrlProvider _publishedUrlProvider; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private string _url; + private string? _url; /// /// Initializes a new instance of the class. @@ -47,10 +47,10 @@ namespace Umbraco.Cms.Web.Website.ActionResults /// /// Initializes a new instance of the class. /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, IPublishedUrlProvider publishedUrlProvider, IUmbracoContextAccessor umbracoContextAccessor) + public RedirectToUmbracoPageResult(IPublishedContent? publishedContent, IPublishedUrlProvider publishedUrlProvider, IUmbracoContextAccessor umbracoContextAccessor) { _publishedContent = publishedContent; - Key = publishedContent.Key; + Key = publishedContent?.Key ?? Guid.Empty; _publishedUrlProvider = publishedUrlProvider; _umbracoContextAccessor = umbracoContextAccessor; } @@ -58,10 +58,10 @@ namespace Umbraco.Cms.Web.Website.ActionResults /// /// Initializes a new instance of the class. /// - public RedirectToUmbracoPageResult(IPublishedContent publishedContent, QueryString queryString, IPublishedUrlProvider publishedUrlProvider, IUmbracoContextAccessor umbracoContextAccessor) + public RedirectToUmbracoPageResult(IPublishedContent? publishedContent, QueryString queryString, IPublishedUrlProvider publishedUrlProvider, IUmbracoContextAccessor umbracoContextAccessor) { _publishedContent = publishedContent; - Key = publishedContent.Key; + Key = publishedContent?.Key ?? Guid.Empty; _queryString = queryString; _publishedUrlProvider = publishedUrlProvider; _umbracoContextAccessor = umbracoContextAccessor; @@ -97,7 +97,7 @@ namespace Umbraco.Cms.Web.Website.ActionResults public Guid Key { get; } - private IPublishedContent PublishedContent + private IPublishedContent? PublishedContent { get { @@ -107,7 +107,7 @@ namespace Umbraco.Cms.Web.Website.ActionResults } // need to get the URL for the page - _publishedContent = _umbracoContextAccessor.GetRequiredUmbracoContext().Content.GetById(Key); + _publishedContent = _umbracoContextAccessor.GetRequiredUmbracoContext().Content?.GetById(Key); return _publishedContent; } diff --git a/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs b/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs index 8c98a177bc..29fe9eaf60 100644 --- a/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs +++ b/src/Umbraco.Web.Website/ActionResults/UmbracoPageResult.cs @@ -32,7 +32,7 @@ namespace Umbraco.Cms.Web.Website.ActionResults /// public async Task ExecuteResultAsync(ActionContext context) { - UmbracoRouteValues umbracoRouteValues = context.HttpContext.Features.Get(); + UmbracoRouteValues? umbracoRouteValues = context.HttpContext.Features.Get(); if (umbracoRouteValues == null) { throw new InvalidOperationException($"Can only use {nameof(UmbracoPageResult)} in the context of an Http POST when using a {nameof(SurfaceController)} form"); @@ -49,18 +49,21 @@ namespace Umbraco.Cms.Web.Website.ActionResults ActionDescriptor = umbracoRouteValues.ControllerActionDescriptor }; IActionInvokerFactory actionInvokerFactory = context.HttpContext.RequestServices.GetRequiredService(); - IActionInvoker actionInvoker = actionInvokerFactory.CreateInvoker(renderActionContext); + IActionInvoker? actionInvoker = actionInvokerFactory.CreateInvoker(renderActionContext); await ExecuteControllerAction(actionInvoker); } /// /// Executes the controller action /// - private async Task ExecuteControllerAction(IActionInvoker actionInvoker) + private async Task ExecuteControllerAction(IActionInvoker? actionInvoker) { using (_profilingLogger.TraceDuration("Executing Umbraco RouteDefinition controller", "Finished")) { - await actionInvoker.InvokeAsync(); + if (actionInvoker is not null) + { + await actionInvoker.InvokeAsync(); + } } } } diff --git a/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs b/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs index 04d2dd53f1..aa0c0afc3a 100644 --- a/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs +++ b/src/Umbraco.Web.Website/Controllers/RenderNoContentController.cs @@ -26,7 +26,7 @@ namespace Umbraco.Cms.Web.Website.Controllers { var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); var store = umbracoContext.Content; - if (store.HasContent()) + if (store?.HasContent() ?? false) { // If there is actually content, go to the root. return Redirect("~/"); diff --git a/src/Umbraco.Web.Website/Controllers/SurfaceController.cs b/src/Umbraco.Web.Website/Controllers/SurfaceController.cs index b86af23999..a8e875bcf7 100644 --- a/src/Umbraco.Web.Website/Controllers/SurfaceController.cs +++ b/src/Umbraco.Web.Website/Controllers/SurfaceController.cs @@ -32,11 +32,11 @@ namespace Umbraco.Cms.Web.Website.Controllers /// /// Gets the current page. /// - protected virtual IPublishedContent CurrentPage + protected virtual IPublishedContent? CurrentPage { get { - UmbracoRouteValues umbracoRouteValues = HttpContext.Features.Get(); + UmbracoRouteValues? umbracoRouteValues = HttpContext.Features.Get(); if (umbracoRouteValues is null) { throw new InvalidOperationException($"No {nameof(UmbracoRouteValues)} feature was found in the HttpContext"); diff --git a/src/Umbraco.Web.Website/Controllers/UmbExternalLoginController.cs b/src/Umbraco.Web.Website/Controllers/UmbExternalLoginController.cs index cb9188f5d0..526e647b10 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbExternalLoginController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbExternalLoginController.cs @@ -68,7 +68,7 @@ namespace Umbraco.Cms.Web.Website.Controllers [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] - public ActionResult ExternalLogin(string provider, string returnUrl = null) + public ActionResult ExternalLogin(string provider, string? returnUrl = null) { if (returnUrl.IsNullOrWhiteSpace()) { @@ -93,7 +93,7 @@ namespace Umbraco.Cms.Web.Website.Controllers { var errors = new List(); - ExternalLoginInfo loginInfo = await _memberSignInManager.GetExternalLoginInfoAsync(); + ExternalLoginInfo? loginInfo = await _memberSignInManager.GetExternalLoginInfoAsync(); if (loginInfo is null) { errors.Add("Invalid response from the login provider"); @@ -131,14 +131,14 @@ namespace Umbraco.Cms.Web.Website.Controllers if (result == SignInResult.LockedOut) { errors.Add( - $"The local member {loginInfo.Principal.Identity.Name} for the external provider {loginInfo.ProviderDisplayName} is locked out."); + $"The local member {loginInfo.Principal.Identity?.Name} for the external provider {loginInfo.ProviderDisplayName} is locked out."); } else if (result == SignInResult.NotAllowed) { // This occurs when SignInManager.CanSignInAsync fails which is when RequireConfirmedEmail , RequireConfirmedPhoneNumber or RequireConfirmedAccount fails // however since we don't enforce those rules (yet) this shouldn't happen. errors.Add( - $"The member {loginInfo.Principal.Identity.Name} for the external provider {loginInfo.ProviderDisplayName} has not confirmed their details and cannot sign in."); + $"The member {loginInfo.Principal.Identity?.Name} for the external provider {loginInfo.ProviderDisplayName} has not confirmed their details and cannot sign in."); } else if (result == SignInResult.Failed) { @@ -150,7 +150,7 @@ namespace Umbraco.Cms.Web.Website.Controllers { // This occurs when the external provider has approved the login but custom logic in OnExternalLogin has denined it. errors.Add( - $"The user {loginInfo.Principal.Identity.Name} for the external provider {loginInfo.ProviderDisplayName} has not been accepted and cannot sign in."); + $"The user {loginInfo.Principal.Identity?.Name} for the external provider {loginInfo.ProviderDisplayName} has not been accepted and cannot sign in."); } else if (result == MemberSignInManager.AutoLinkSignInResult.FailedNotLinked) { @@ -197,7 +197,7 @@ namespace Umbraco.Cms.Web.Website.Controllers [HttpPost] [ValidateAntiForgeryToken] - public IActionResult LinkLogin(string provider, string returnUrl = null) + public IActionResult LinkLogin(string provider, string? returnUrl = null) { if (returnUrl.IsNullOrWhiteSpace()) { @@ -219,7 +219,7 @@ namespace Umbraco.Cms.Web.Website.Controllers public async Task ExternalLinkLoginCallback(string returnUrl) { MemberIdentityUser user = await _memberManager.GetUserAsync(User); - string loginProvider = null; + string? loginProvider = null; var errors = new List(); if (user == null) { @@ -228,7 +228,7 @@ namespace Umbraco.Cms.Web.Website.Controllers } else { - ExternalLoginInfo info = + ExternalLoginInfo? info = await _memberSignInManager.GetExternalLoginInfoAsync(await _memberManager.GetUserIdAsync(user)); if (info == null) @@ -265,21 +265,21 @@ namespace Umbraco.Cms.Web.Website.Controllers [HttpPost] [ValidateAntiForgeryToken] - public async Task Disassociate(string provider, string providerKey, string returnUrl = null) + public async Task Disassociate(string provider, string providerKey, string? returnUrl = null) { if (returnUrl.IsNullOrWhiteSpace()) { returnUrl = Request.GetEncodedPathAndQuery(); } - MemberIdentityUser user = await _memberManager.FindByIdAsync(User.Identity.GetUserId()); + MemberIdentityUser user = await _memberManager.FindByIdAsync(User.Identity?.GetUserId()); IdentityResult result = await _memberManager.RemoveLoginAsync(user, provider, providerKey); if (result.Succeeded) { await _memberSignInManager.SignInAsync(user, false); - return RedirectToLocal(returnUrl); + return RedirectToLocal(returnUrl!); } AddModelErrors(result); diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs index 9dbcd292e4..7db6d3d702 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbLoginController.cs @@ -92,7 +92,7 @@ namespace Umbraco.Cms.Web.Website.Controllers // If it's not a local URL we'll redirect to the root of the current site. return Redirect(Url.IsLocalUrl(model.RedirectUrl) ? model.RedirectUrl - : CurrentPage.AncestorOrSelf(1).Url(PublishedUrlProvider)); + : CurrentPage!.AncestorOrSelf(1)!.Url(PublishedUrlProvider)); } // Redirect to current URL by default. diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs index ab22e6f143..f6e560366c 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs @@ -51,7 +51,7 @@ namespace Umbraco.Cms.Web.Website.Controllers // If there is a specified path to redirect to then use it. if (model.RedirectUrl.IsNullOrWhiteSpace() == false) { - return Redirect(model.RedirectUrl); + return Redirect(model.RedirectUrl!); } // Redirect to current page by default. diff --git a/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs b/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs index bd2980e2ad..153a2bd1dc 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbProfileController.cs @@ -76,7 +76,7 @@ namespace Umbraco.Cms.Web.Website.Controllers // If there is a specified path to redirect to then use it. if (model.RedirectUrl.IsNullOrWhiteSpace() == false) { - return Redirect(model.RedirectUrl); + return Redirect(model.RedirectUrl!); } // Redirect to current page by default. @@ -106,7 +106,7 @@ namespace Umbraco.Cms.Web.Website.Controllers private async Task UpdateMemberAsync(ProfileModel model, MemberIdentityUser currentMember) { using IScope scope = _scopeProvider.CreateScope(autoComplete: true); - + currentMember.Email = model.Email; currentMember.Name = model.Name; currentMember.UserName = model.UserName; @@ -121,25 +121,25 @@ namespace Umbraco.Cms.Web.Website.Controllers // now we can update the custom properties // TODO: Ideally we could do this all through our MemberIdentityUser - IMember member = _memberService.GetByKey(currentMember.Key); + IMember? member = _memberService.GetByKey(currentMember.Key); if (member == null) { // should never happen - throw new InvalidOperationException($"Could not find a member with key: {member.Key}."); + throw new InvalidOperationException($"Could not find a member with key: {member?.Key}."); } - - IMemberType memberType = _memberTypeService.Get(member.ContentTypeId); + + IMemberType? memberType = _memberTypeService.Get(member.ContentTypeId); if (model.MemberProperties != null) { foreach (MemberPropertyModel property in model.MemberProperties //ensure the property they are posting exists - .Where(p => memberType.PropertyTypeExists(p.Alias)) + .Where(p => memberType?.PropertyTypeExists(p.Alias) ?? false) .Where(property => member.Properties.Contains(property.Alias)) //needs to be editable - .Where(p => memberType.MemberCanEditProperty(p.Alias))) + .Where(p => memberType?.MemberCanEditProperty(p.Alias) ?? false)) { - member.Properties[property.Alias].SetValue(property.Value); + member.Properties[property.Alias]?.SetValue(property.Value); } } diff --git a/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs b/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs index 1e6c417ed3..5881ea18f7 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Web.Website.Controllers // If there is a specified path to redirect to then use it. if (model.RedirectUrl.IsNullOrWhiteSpace() == false) { - return Redirect(model.RedirectUrl); + return Redirect(model.RedirectUrl!); } // Redirect to current page by default. @@ -91,7 +91,7 @@ namespace Umbraco.Cms.Web.Website.Controllers if (RouteData.Values.TryGetValue(nameof(RegisterModel.MemberTypeAlias), out var memberTypeAlias) && memberTypeAlias != null) { - model.MemberTypeAlias = memberTypeAlias.ToString(); + model.MemberTypeAlias = memberTypeAlias.ToString()!; } if (RouteData.Values.TryGetValue(nameof(RegisterModel.UsernameIsEmail), out var usernameIsEmail) && usernameIsEmail != null) @@ -136,11 +136,11 @@ namespace Umbraco.Cms.Web.Website.Controllers { // Update the custom properties // TODO: See TODO in MembersIdentityUser, Should we support custom member properties for persistence/retrieval? - IMember member = _memberService.GetByKey(identityUser.Key); + IMember? member = _memberService.GetByKey(identityUser.Key); if (member == null) { // should never happen - throw new InvalidOperationException($"Could not find a member with key: {member.Key}."); + throw new InvalidOperationException($"Could not find a member with key: {member?.Key}."); } if (model.MemberProperties != null) @@ -148,7 +148,7 @@ namespace Umbraco.Cms.Web.Website.Controllers foreach (MemberPropertyModel property in model.MemberProperties.Where(p => p.Value != null) .Where(property => member.Properties.Contains(property.Alias))) { - member.Properties[property.Alias].SetValue(property.Value); + member.Properties[property.Alias]?.SetValue(property.Value); } } _memberService.Save(member); diff --git a/src/Umbraco.Web.Website/Controllers/UmbTwoFactorLoginController.cs b/src/Umbraco.Web.Website/Controllers/UmbTwoFactorLoginController.cs index ba86e63a36..c8c8536d62 100644 --- a/src/Umbraco.Web.Website/Controllers/UmbTwoFactorLoginController.cs +++ b/src/Umbraco.Web.Website/Controllers/UmbTwoFactorLoginController.cs @@ -75,7 +75,7 @@ namespace Umbraco.Cms.Web.Website.Controllers } [AllowAnonymous] - public async Task Verify2FACode(Verify2FACodeModel model, string returnUrl = null) + public async Task Verify2FACode(Verify2FACodeModel model, string? returnUrl = null) { var user = await _memberSignInManager.GetTwoFactorAuthenticationUserAsync(); if (user == null) @@ -87,7 +87,7 @@ namespace Umbraco.Cms.Web.Website.Controllers if (ModelState.IsValid) { var result = await _memberSignInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.IsPersistent, model.RememberClient); - if (result.Succeeded) + if (result.Succeeded && returnUrl is not null) { return RedirectToLocal(returnUrl); } @@ -113,13 +113,13 @@ namespace Umbraco.Cms.Web.Website.Controllers } [HttpPost] - public async Task ValidateAndSaveSetup(string providerName, string secret, string code, string returnUrl = null) + public async Task ValidateAndSaveSetup(string providerName, string secret, string code, string? returnUrl = null) { var member = await _memberManager.GetCurrentMemberAsync(); var isValid = _twoFactorLoginService.ValidateTwoFactorSetup(providerName, secret, code); - if (isValid == false) + if (member is null || isValid == false) { ModelState.AddModelError(nameof(code), "Invalid Code"); @@ -131,7 +131,7 @@ namespace Umbraco.Cms.Web.Website.Controllers Confirmed = true, Secret = secret, UserOrMemberKey = member.Key, - ProviderName = providerName + ProviderName = providerName, }; await _twoFactorLoginService.SaveAsync(twoFactorLogin); @@ -140,11 +140,11 @@ namespace Umbraco.Cms.Web.Website.Controllers } [HttpPost] - public async Task Disable(string providerName, string returnUrl = null) + public async Task Disable(string providerName, string? returnUrl = null) { var member = await _memberManager.GetCurrentMemberAsync(); - var success = await _twoFactorLoginService.DisableAsync(member.Key, providerName); + var success = member is not null && await _twoFactorLoginService.DisableAsync(member.Key, providerName); if (!success) { @@ -154,7 +154,7 @@ namespace Umbraco.Cms.Web.Website.Controllers return RedirectToLocal(returnUrl); } - private IActionResult RedirectToLocal(string returnUrl) => + private IActionResult RedirectToLocal(string? returnUrl) => Url.IsLocalUrl(returnUrl) ? Redirect(returnUrl) : RedirectToCurrentUmbracoPage(); } } diff --git a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs index 5f8f1d9b69..e5f30135fb 100644 --- a/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/DependencyInjection/UmbracoBuilderExtensions.cs @@ -25,7 +25,7 @@ namespace Umbraco.Extensions /// public static IUmbracoBuilder AddWebsite(this IUmbracoBuilder builder) { - builder.WithCollectionBuilder() + builder.WithCollectionBuilder()? .Add(builder.TypeLoader.GetSurfaceControllers()); // Configure MVC startup options for custom view locations diff --git a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs index 84fdafd823..5dee7c6273 100644 --- a/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/HtmlHelperRenderExtensions.cs @@ -36,9 +36,11 @@ namespace Umbraco.Extensions public static class HtmlHelperRenderExtensions { private static T GetRequiredService(IHtmlHelper htmlHelper) + where T : notnull => GetRequiredService(htmlHelper.ViewContext); private static T GetRequiredService(ViewContext viewContext) + where T : notnull => viewContext.HttpContext.RequestServices.GetRequiredService(); /// @@ -50,7 +52,7 @@ namespace Umbraco.Extensions /// /// Renders a partial view that is found in the specified area /// - public static IHtmlContent AreaPartial(this IHtmlHelper helper, string partial, string area, object model = null, ViewDataDictionary viewData = null) + public static IHtmlContent AreaPartial(this IHtmlHelper helper, string partial, string area, object? model = null, ViewDataDictionary? viewData = null) { var originalArea = helper.ViewContext.RouteData.DataTokens["area"]; helper.ViewContext.RouteData.DataTokens["area"] = area; @@ -77,7 +79,7 @@ namespace Umbraco.Extensions contentSettings.PreviewBadge, ioHelper.ResolveUrl(globalSettings.UmbracoPath), WebUtility.UrlEncode(httpContextAccessor.GetRequiredHttpContext().Request.Path), - umbracoContext.PublishedRequest.PublishedContent.Id); + umbracoContext.PublishedRequest?.PublishedContent?.Id); return new HtmlString(htmlBadge); } @@ -85,15 +87,15 @@ namespace Umbraco.Extensions } - public static async Task CachedPartialAsync( + public static async Task CachedPartialAsync( this IHtmlHelper htmlHelper, string partialViewName, object model, TimeSpan cacheTimeout, bool cacheByPage = false, bool cacheByMember = false, - ViewDataDictionary viewData = null, - Func contextualKeyBuilder = null) + ViewDataDictionary? viewData = null, + Func? contextualKeyBuilder = null) { var cacheKey = new StringBuilder(partialViewName); // let's always cache by the current culture to allow variants to have different cache results @@ -132,7 +134,7 @@ namespace Umbraco.Extensions var appCaches = GetRequiredService(htmlHelper); var hostingEnvironment = GetRequiredService(htmlHelper); - return appCaches.CachedPartialView(hostingEnvironment, umbracoContext, htmlHelper, partialViewName, model, cacheTimeout, cacheKey.ToString(), viewData); + return appCaches.CachedPartialView(hostingEnvironment, umbracoContext!, htmlHelper, partialViewName, model, cacheTimeout, cacheKey.ToString(), viewData); } // public static IHtmlContent EditorFor(this IHtmlHelper htmlHelper, string templateName = "", string htmlFieldName = "", object additionalViewData = null) @@ -161,7 +163,7 @@ namespace Umbraco.Extensions string prefix = "", bool excludePropertyErrors = false, string message = "", - object htmlAttributes = null) + object? htmlAttributes = null) { if (prefix.IsNullOrWhiteSpace()) { @@ -216,7 +218,7 @@ namespace Umbraco.Extensions } SurfaceControllerTypeCollection surfaceControllerTypeCollection = GetRequiredService(htmlHelper); - Type surfaceController = surfaceControllerTypeCollection.SingleOrDefault(x => x == surfaceType); + Type? surfaceController = surfaceControllerTypeCollection.SingleOrDefault(x => x == surfaceType); if (surfaceController == null) { throw new InvalidOperationException("Could not find the surface controller of type " + surfaceType.FullName); @@ -253,7 +255,7 @@ namespace Umbraco.Extensions this IHtmlHelper htmlHelper, string controllerAction, string area, - object additionalRouteVals = null) + object? additionalRouteVals = null) where TSurface : SurfaceController { var inputField = GetSurfaceControllerHiddenInput( @@ -271,7 +273,7 @@ namespace Umbraco.Extensions string controllerName, string controllerAction, string area, - object additionalRouteVals = null) + object? additionalRouteVals = null) { var encryptedString = EncryptionHelper.CreateEncryptedRouteString( dataProtectionProvider, @@ -300,7 +302,7 @@ namespace Umbraco.Extensions string controllerName, string controllerAction, string area, - object additionalRouteVals = null) + object? additionalRouteVals = null) : base(viewContext, htmlEncoder) { _viewContext = viewContext; @@ -335,25 +337,25 @@ namespace Umbraco.Extensions /// The method. /// the public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, string controllerName, FormMethod method) - => html.BeginUmbracoForm(action, controllerName, null, new Dictionary(), method); + => html.BeginUmbracoForm(action, controllerName, null, new Dictionary(), method); /// /// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, string controllerName) - => html.BeginUmbracoForm(action, controllerName, null, new Dictionary()); + => html.BeginUmbracoForm(action, controllerName, null, new Dictionary()); /// /// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, string controllerName, object additionalRouteVals, FormMethod method) - => html.BeginUmbracoForm(action, controllerName, additionalRouteVals, new Dictionary(), method); + => html.BeginUmbracoForm(action, controllerName, additionalRouteVals, new Dictionary(), method); /// /// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, string controllerName, object additionalRouteVals) - => html.BeginUmbracoForm(action, controllerName, additionalRouteVals, new Dictionary()); + => html.BeginUmbracoForm(action, controllerName, additionalRouteVals, new Dictionary()); /// /// Helper method to create a new form to execute in the Umbraco request pipeline against a locally declared controller @@ -383,8 +385,8 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, string controllerName, - object additionalRouteVals, - IDictionary htmlAttributes, + object? additionalRouteVals, + IDictionary htmlAttributes, FormMethod method) { if (action == null) @@ -417,8 +419,8 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, string controllerName, - object additionalRouteVals, - IDictionary htmlAttributes) + object? additionalRouteVals, + IDictionary htmlAttributes) { if (action == null) { @@ -447,13 +449,13 @@ namespace Umbraco.Extensions /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, Type surfaceType, FormMethod method) - => html.BeginUmbracoForm(action, surfaceType, null, new Dictionary(), method); + => html.BeginUmbracoForm(action, surfaceType, null, new Dictionary(), method); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, Type surfaceType) - => html.BeginUmbracoForm(action, surfaceType, null, new Dictionary()); + => html.BeginUmbracoForm(action, surfaceType, null, new Dictionary()); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin @@ -477,7 +479,7 @@ namespace Umbraco.Extensions string action, Type surfaceType, object additionalRouteVals, - FormMethod method) => html.BeginUmbracoForm(action, surfaceType, additionalRouteVals, new Dictionary(), method); + FormMethod method) => html.BeginUmbracoForm(action, surfaceType, additionalRouteVals, new Dictionary(), method); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin @@ -486,7 +488,7 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, Type surfaceType, - object additionalRouteVals) => html.BeginUmbracoForm(action, surfaceType, additionalRouteVals, new Dictionary()); + object additionalRouteVals) => html.BeginUmbracoForm(action, surfaceType, additionalRouteVals, new Dictionary()); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin @@ -552,8 +554,8 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, Type surfaceType, - object additionalRouteVals, - IDictionary htmlAttributes, + object? additionalRouteVals, + IDictionary htmlAttributes, FormMethod method) { @@ -588,7 +590,7 @@ namespace Umbraco.Extensions area = metaData.AreaName; } - return html.BeginUmbracoForm(action, metaData.ControllerName, area, additionalRouteVals, htmlAttributes, method); + return html.BeginUmbracoForm(action, metaData.ControllerName, area!, additionalRouteVals, htmlAttributes, method); } /// @@ -598,8 +600,8 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, Type surfaceType, - object additionalRouteVals, - IDictionary htmlAttributes) + object? additionalRouteVals, + IDictionary htmlAttributes) => html.BeginUmbracoForm(action, surfaceType, additionalRouteVals, htmlAttributes, FormMethod.Post); /// @@ -610,7 +612,7 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, object additionalRouteVals, - IDictionary htmlAttributes, + IDictionary htmlAttributes, FormMethod method) where T : SurfaceController => html.BeginUmbracoForm(action, typeof(T), additionalRouteVals, htmlAttributes, method); @@ -622,20 +624,20 @@ namespace Umbraco.Extensions this IHtmlHelper html, string action, object additionalRouteVals, - IDictionary htmlAttributes) + IDictionary htmlAttributes) where T : SurfaceController => html.BeginUmbracoForm(action, typeof(T), additionalRouteVals, htmlAttributes); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, string controllerName, string area, FormMethod method) - => html.BeginUmbracoForm(action, controllerName, area, null, new Dictionary(), method); + => html.BeginUmbracoForm(action, controllerName, area, null, new Dictionary(), method); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin /// public static MvcForm BeginUmbracoForm(this IHtmlHelper html, string action, string controllerName, string area) - => html.BeginUmbracoForm(action, controllerName, area, null, new Dictionary()); + => html.BeginUmbracoForm(action, controllerName, area, null, new Dictionary()); /// /// Helper method to create a new form to execute in the Umbraco request pipeline to a surface controller plugin @@ -643,10 +645,10 @@ namespace Umbraco.Extensions public static MvcForm BeginUmbracoForm( this IHtmlHelper html, string action, - string controllerName, + string? controllerName, string area, - object additionalRouteVals, - IDictionary htmlAttributes, + object? additionalRouteVals, + IDictionary htmlAttributes, FormMethod method) { if (action == null) @@ -683,8 +685,8 @@ namespace Umbraco.Extensions string action, string controllerName, string area, - object additionalRouteVals, - IDictionary htmlAttributes) => html.BeginUmbracoForm(action, controllerName, area, additionalRouteVals, htmlAttributes, FormMethod.Post); + object? additionalRouteVals, + IDictionary htmlAttributes) => html.BeginUmbracoForm(action, controllerName, area, additionalRouteVals, htmlAttributes, FormMethod.Post); /// /// This renders out the form for us @@ -696,11 +698,11 @@ namespace Umbraco.Extensions this IHtmlHelper htmlHelper, string formAction, FormMethod method, - IDictionary htmlAttributes, + IDictionary htmlAttributes, string surfaceController, string surfaceAction, string area, - object additionalRouteVals = null) + object? additionalRouteVals = null) { // ensure that the multipart/form-data is added to the HTML attributes if (htmlAttributes.ContainsKey("enctype") == false) diff --git a/src/Umbraco.Web.Website/Extensions/LinkGeneratorExtensions.cs b/src/Umbraco.Web.Website/Extensions/LinkGeneratorExtensions.cs index 217dbbf144..e7d32bb8ee 100644 --- a/src/Umbraco.Web.Website/Extensions/LinkGeneratorExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/LinkGeneratorExtensions.cs @@ -15,11 +15,11 @@ namespace Umbraco.Extensions /// Return the Url for a Surface Controller /// /// The - public static string GetUmbracoSurfaceUrl(this LinkGenerator linkGenerator, Expression> methodSelector) + public static string? GetUmbracoSurfaceUrl(this LinkGenerator linkGenerator, Expression> methodSelector) where T : SurfaceController { - MethodInfo method = ExpressionHelper.GetMethodInfo(methodSelector); - IDictionary methodParams = ExpressionHelper.GetMethodParams(methodSelector); + MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector); + IDictionary? methodParams = ExpressionHelper.GetMethodParams(methodSelector); if (method == null) { @@ -27,7 +27,7 @@ namespace Umbraco.Extensions $"Could not find the method {methodSelector} on type {typeof(T)} or the result "); } - if (methodParams.Any() == false) + if (methodParams is null || methodParams.Any() == false) { return linkGenerator.GetUmbracoSurfaceUrl(method.Name); } @@ -39,11 +39,11 @@ namespace Umbraco.Extensions /// Return the Url for a Surface Controller /// /// The - public static string GetUmbracoSurfaceUrl(this LinkGenerator linkGenerator, string actionName, object id = null) + public static string? GetUmbracoSurfaceUrl(this LinkGenerator linkGenerator, string actionName, object? id = null) where T : SurfaceController => linkGenerator.GetUmbracoControllerUrl( actionName, typeof(T), - new Dictionary() + new Dictionary() { ["id"] = id }); diff --git a/src/Umbraco.Web.Website/Middleware/BasicAuthenticationMiddleware.cs b/src/Umbraco.Web.Website/Middleware/BasicAuthenticationMiddleware.cs index 92836e2456..3833efb89f 100644 --- a/src/Umbraco.Web.Website/Middleware/BasicAuthenticationMiddleware.cs +++ b/src/Umbraco.Web.Website/Middleware/BasicAuthenticationMiddleware.cs @@ -36,8 +36,8 @@ namespace Umbraco.Cms.Web.Common.Middleware return; } - IPAddress clientIPAddress = context.Connection.RemoteIpAddress; - if (_basicAuthService.IsIpAllowListed(clientIPAddress)) + IPAddress? clientIPAddress = context.Connection.RemoteIpAddress; + if (clientIPAddress is not null && _basicAuthService.IsIpAllowListed(clientIPAddress)) { await next(context); return; @@ -52,10 +52,10 @@ namespace Umbraco.Cms.Web.Common.Middleware if (context.TryGetBasicAuthCredentials(out var username, out var password)) { - IBackOfficeSignInManager backOfficeSignInManager = + IBackOfficeSignInManager? backOfficeSignInManager = context.RequestServices.GetService(); - if (backOfficeSignInManager is not null) + if (backOfficeSignInManager is not null && username is not null && password is not null) { SignInResult signInResult = await backOfficeSignInManager.PasswordSignInAsync(username, password, false, true); diff --git a/src/Umbraco.Web.Website/Models/MemberModelBuilderBase.cs b/src/Umbraco.Web.Website/Models/MemberModelBuilderBase.cs index 6bfeeb8f73..ed91491b31 100644 --- a/src/Umbraco.Web.Website/Models/MemberModelBuilderBase.cs +++ b/src/Umbraco.Web.Website/Models/MemberModelBuilderBase.cs @@ -20,7 +20,7 @@ namespace Umbraco.Cms.Web.Website.Models public IMemberTypeService MemberTypeService { get; } - protected List GetMemberPropertiesViewModel(IMemberType memberType, IMember member = null) + protected List GetMemberPropertiesViewModel(IMemberType memberType, IMember? member = null) { var viewProperties = new List(); @@ -35,10 +35,10 @@ namespace Umbraco.Cms.Web.Website.Models var value = string.Empty; if (member != null) { - IProperty propValue = member.Properties[prop.Alias]; + IProperty? propValue = member.Properties[prop.Alias]; if (propValue != null && propValue.GetValue() != null) { - value = propValue.GetValue().ToString(); + value = propValue.GetValue()?.ToString(); } } diff --git a/src/Umbraco.Web.Website/Models/NoNodesViewModel.cs b/src/Umbraco.Web.Website/Models/NoNodesViewModel.cs index 30d3138d84..0c2cc270f9 100644 --- a/src/Umbraco.Web.Website/Models/NoNodesViewModel.cs +++ b/src/Umbraco.Web.Website/Models/NoNodesViewModel.cs @@ -2,6 +2,6 @@ { public class NoNodesViewModel { - public string UmbracoPath { get; set; } + public string? UmbracoPath { get; set; } } } diff --git a/src/Umbraco.Web.Website/Models/ProfileModel.cs b/src/Umbraco.Web.Website/Models/ProfileModel.cs index 5fc7ed2df8..85c2eaaebf 100644 --- a/src/Umbraco.Web.Website/Models/ProfileModel.cs +++ b/src/Umbraco.Web.Website/Models/ProfileModel.cs @@ -19,18 +19,18 @@ namespace Umbraco.Cms.Web.Website.Models [Required] [EmailAddress] [Display(Name = "Email")] - public string Email { get; set; } + public string Email { get; set; } = null!; /// /// The member's real name /// - public string Name { get; set; } + public string? Name { get; set; } [ReadOnly(true)] - public string UserName { get; set; } + public string UserName { get; set; } = null!; [ReadOnly(true)] - public string Comments { get; set; } + public string? Comments { get; set; } [ReadOnly(true)] public bool IsApproved { get; set; } diff --git a/src/Umbraco.Web.Website/Models/ProfileModelBuilder.cs b/src/Umbraco.Web.Website/Models/ProfileModelBuilder.cs index 4a94fb094c..e9d43e3295 100644 --- a/src/Umbraco.Web.Website/Models/ProfileModelBuilder.cs +++ b/src/Umbraco.Web.Website/Models/ProfileModelBuilder.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Web.Website.Models { private readonly IMemberService _memberService; private readonly IHttpContextAccessor _httpContextAccessor; - private string _redirectUrl; + private string? _redirectUrl; private bool _lookupProperties; public ProfileModelBuilder( @@ -40,16 +40,16 @@ namespace Umbraco.Cms.Web.Website.Models return this; } - public async Task BuildForCurrentMemberAsync() + public async Task BuildForCurrentMemberAsync() { - IMemberManager memberManager = _httpContextAccessor.HttpContext?.RequestServices.GetRequiredService(); + IMemberManager? memberManager = _httpContextAccessor.HttpContext?.RequestServices.GetRequiredService(); if (memberManager == null) { return null; } - MemberIdentityUser member = await memberManager.GetUserAsync(_httpContextAccessor.HttpContext.User); + MemberIdentityUser? member = _httpContextAccessor.HttpContext is null ? null : await memberManager.GetUserAsync(_httpContextAccessor.HttpContext.User); if (member == null) { @@ -72,14 +72,14 @@ namespace Umbraco.Cms.Web.Website.Models Key = member.Key }; - IMemberType memberType = MemberTypeService.Get(member.MemberTypeAlias); + IMemberType? memberType = member.MemberTypeAlias is null ? null : MemberTypeService.Get(member.MemberTypeAlias); if (memberType == null) { throw new InvalidOperationException($"Could not find a member type with alias: {member.MemberTypeAlias}."); } // TODO: This wouldn't be required if we support exposing custom member properties on the MemberIdentityUser at the ASP.NET Identity level. - IMember persistedMember = _memberService.GetByKey(member.Key); + IMember? persistedMember = _memberService.GetByKey(member.Key); if (persistedMember == null) { // should never happen diff --git a/src/Umbraco.Web.Website/Models/RegisterModel.cs b/src/Umbraco.Web.Website/Models/RegisterModel.cs index d949660539..d75f8ef4b8 100644 --- a/src/Umbraco.Web.Website/Models/RegisterModel.cs +++ b/src/Umbraco.Web.Website/Models/RegisterModel.cs @@ -19,7 +19,7 @@ namespace Umbraco.Cms.Web.Website.Models [Required] [EmailAddress] [Display(Name = "Email")] - public string Email { get; set; } + public string Email { get; set; } = null!; /// /// Returns the member properties @@ -35,7 +35,7 @@ namespace Umbraco.Cms.Web.Website.Models /// /// The members real name /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The members password @@ -44,17 +44,17 @@ namespace Umbraco.Cms.Web.Website.Models [StringLength(256)] [DataType(System.ComponentModel.DataAnnotations.DataType.Password)] [Display(Name = "Password")] - public string Password { get; set; } + public string Password { get; set; } = null!; [DataType(System.ComponentModel.DataAnnotations.DataType.Password)] [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public string ConfirmPassword { get; set; } = null!; /// /// The username of the model, if UsernameIsEmail is true then this is ignored. /// - public string Username { get; set; } + public string Username { get; set; } = null!; /// /// Flag to determine if the username should be the email address, if true then the Username property is ignored diff --git a/src/Umbraco.Web.Website/Models/RegisterModelBuilder.cs b/src/Umbraco.Web.Website/Models/RegisterModelBuilder.cs index d2dfda227d..d1170de163 100644 --- a/src/Umbraco.Web.Website/Models/RegisterModelBuilder.cs +++ b/src/Umbraco.Web.Website/Models/RegisterModelBuilder.cs @@ -12,10 +12,10 @@ namespace Umbraco.Cms.Web.Website.Models /// public class RegisterModelBuilder : MemberModelBuilderBase { - private string _memberTypeAlias; + private string? _memberTypeAlias; private bool _lookupProperties; private bool _usernameIsEmail; - private string _redirectUrl; + private string? _redirectUrl; public RegisterModelBuilder(IMemberTypeService memberTypeService, IShortStringHelper shortStringHelper) : base(memberTypeService, shortStringHelper) @@ -49,7 +49,7 @@ namespace Umbraco.Cms.Web.Website.Models public RegisterModel Build() { var providedOrDefaultMemberTypeAlias = _memberTypeAlias ?? Core.Constants.Conventions.MemberTypes.DefaultAlias; - IMemberType memberType = MemberTypeService.Get(providedOrDefaultMemberTypeAlias); + IMemberType? memberType = MemberTypeService.Get(providedOrDefaultMemberTypeAlias); if (memberType == null) { throw new InvalidOperationException($"Could not find a member type with alias: {providedOrDefaultMemberTypeAlias}."); diff --git a/src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs b/src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs index 5c758a948c..ecb36f8c9b 100644 --- a/src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs +++ b/src/Umbraco.Web.Website/Routing/ControllerActionSearcher.cs @@ -35,11 +35,11 @@ namespace Umbraco.Cms.Web.Website.Routing /// Determines if a custom controller can hijack the current route /// /// The controller type to find - public ControllerActionDescriptor Find(HttpContext httpContext, string controller, string action) + public ControllerActionDescriptor? Find(HttpContext httpContext, string? controller, string? action) { - IReadOnlyList candidates = FindControllerCandidates(httpContext, controller, action, DefaultActionName); + IReadOnlyList? candidates = FindControllerCandidates(httpContext, controller, action, DefaultActionName); - if (candidates.Count > 0) + if (candidates?.Count > 0) { return candidates[0]; } @@ -50,10 +50,10 @@ namespace Umbraco.Cms.Web.Website.Routing /// /// Return a list of controller candidates that match the custom controller and action names /// - private IReadOnlyList FindControllerCandidates( + private IReadOnlyList? FindControllerCandidates( HttpContext httpContext, - string customControllerName, - string customActionName, + string? customControllerName, + string? customActionName, string defaultActionName) { // Use aspnetcore's IActionSelector to do the finding since it uses an optimized cache lookup @@ -69,12 +69,12 @@ namespace Umbraco.Cms.Web.Website.Routing }; // try finding candidates for the custom action - var candidates = _actionSelector.SelectCandidates(routeContext) + var candidates = _actionSelector.SelectCandidates(routeContext)? .Cast() .Where(x => TypeHelper.IsTypeAssignableFrom(x.ControllerTypeInfo)) .ToList(); - if (candidates.Count > 0) + if (candidates?.Count > 0) { // return them if found return candidates; @@ -82,7 +82,7 @@ namespace Umbraco.Cms.Web.Website.Routing // now find for the default action since we couldn't find the custom one routeValues[ActionToken] = defaultActionName; - candidates = _actionSelector.SelectCandidates(routeContext) + candidates = _actionSelector.SelectCandidates(routeContext)? .Cast() .Where(x => TypeHelper.IsTypeAssignableFrom(x.ControllerTypeInfo)) .ToList(); diff --git a/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs b/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs index b272b4afd3..1d6504fbda 100644 --- a/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs +++ b/src/Umbraco.Web.Website/Routing/IControllerActionSearcher.cs @@ -5,6 +5,6 @@ namespace Umbraco.Cms.Web.Website.Routing { public interface IControllerActionSearcher { - ControllerActionDescriptor Find(HttpContext httpContext, string controller, string action); + ControllerActionDescriptor? Find(HttpContext httpContext, string? controller, string? action); } } diff --git a/src/Umbraco.Web.Website/Routing/IPublicAccessRequestHandler.cs b/src/Umbraco.Web.Website/Routing/IPublicAccessRequestHandler.cs index 0ce3ddad92..d55461f4a2 100644 --- a/src/Umbraco.Web.Website/Routing/IPublicAccessRequestHandler.cs +++ b/src/Umbraco.Web.Website/Routing/IPublicAccessRequestHandler.cs @@ -13,6 +13,6 @@ namespace Umbraco.Cms.Web.Website.Routing /// The current route values /// Updated route values if public access changes the rendered content, else the original route values. /// Redirecting to a different site root and/or culture will not pick the new site root nor the new culture. - Task RewriteForPublishedContentAccessAsync(HttpContext httpContext, UmbracoRouteValues routeValues); + Task RewriteForPublishedContentAccessAsync(HttpContext httpContext, UmbracoRouteValues routeValues); } } diff --git a/src/Umbraco.Web.Website/Routing/NotFoundSelectorPolicy.cs b/src/Umbraco.Web.Website/Routing/NotFoundSelectorPolicy.cs index 871ae75d33..f4bc0a84af 100644 --- a/src/Umbraco.Web.Website/Routing/NotFoundSelectorPolicy.cs +++ b/src/Umbraco.Web.Website/Routing/NotFoundSelectorPolicy.cs @@ -34,7 +34,7 @@ namespace Umbraco.Cms.Web.Website.Routing Endpoint e = _endpointDataSource.Endpoints.First(x => { // return the endpoint for the RenderController.Index action. - ControllerActionDescriptor descriptor = x.Metadata?.GetMetadata(); + ControllerActionDescriptor? descriptor = x.Metadata?.GetMetadata(); return descriptor?.ControllerTypeInfo == typeof(RenderController) && descriptor?.ActionName == nameof(RenderController.Index); }); @@ -49,7 +49,7 @@ namespace Umbraco.Cms.Web.Website.Routing // i.e. only dynamic routes. foreach (Endpoint endpoint in endpoints) { - ControllerAttribute controller = endpoint.Metadata?.GetMetadata(); + ControllerAttribute? controller = endpoint.Metadata?.GetMetadata(); if (controller != null) { return false; @@ -64,7 +64,7 @@ namespace Umbraco.Cms.Web.Website.Routing { if (AllInvalid(candidates)) { - UmbracoRouteValues umbracoRouteValues = httpContext.Features.Get(); + UmbracoRouteValues? umbracoRouteValues = httpContext.Features.Get(); if (umbracoRouteValues?.PublishedRequest != null && !umbracoRouteValues.PublishedRequest.HasPublishedContent() && umbracoRouteValues.PublishedRequest.ResponseStatusCode == StatusCodes.Status404NotFound) diff --git a/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs b/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs index 4c1f6acd99..3569f31ad3 100644 --- a/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs +++ b/src/Umbraco.Web.Website/Routing/PublicAccessRequestHandler.cs @@ -42,7 +42,7 @@ namespace Umbraco.Cms.Web.Website.Routing } /// - public async Task RewriteForPublishedContentAccessAsync(HttpContext httpContext, UmbracoRouteValues routeValues) + public async Task RewriteForPublishedContentAccessAsync(HttpContext httpContext, UmbracoRouteValues routeValues) { // because these might loop, we have to have some sort of infinite loop detection int i = 0; @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Web.Website.Routing _logger.LogDebug(nameof(RewriteForPublishedContentAccessAsync) + ": Loop {LoopCounter}", i); - IPublishedContent publishedContent = routeValues.PublishedRequest?.PublishedContent; + IPublishedContent? publishedContent = routeValues.PublishedRequest?.PublishedContent; if (publishedContent == null) { return routeValues; @@ -61,7 +61,7 @@ namespace Umbraco.Cms.Web.Website.Routing var path = publishedContent.Path; - Attempt publicAccessAttempt = _publicAccessService.IsProtected(path); + Attempt publicAccessAttempt = _publicAccessService.IsProtected(path); if (publicAccessAttempt.Success) { @@ -85,19 +85,19 @@ namespace Umbraco.Cms.Web.Website.Routing { case PublicAccessStatus.NotLoggedIn: _logger.LogDebug("EnsurePublishedContentAccess: Not logged in, redirect to login page"); - routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result.LoginNodeId); + routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result!.LoginNodeId); break; case PublicAccessStatus.AccessDenied: _logger.LogDebug("EnsurePublishedContentAccess: Current member has not access, redirect to error page"); - routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result.NoAccessNodeId); + routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result!.NoAccessNodeId); break; case PublicAccessStatus.LockedOut: _logger.LogDebug("Current member is locked out, redirect to error page"); - routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result.NoAccessNodeId); + routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result!.NoAccessNodeId); break; case PublicAccessStatus.NotApproved: _logger.LogDebug("Current member is unapproved, redirect to error page"); - routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result.NoAccessNodeId); + routeValues = await SetPublishedContentAsOtherPageAsync(httpContext, routeValues.PublishedRequest, publicAccessAttempt.Result!.NoAccessNodeId); break; case PublicAccessStatus.AccessAccepted: _logger.LogDebug("Current member has access"); @@ -124,13 +124,13 @@ namespace Umbraco.Cms.Web.Website.Routing - private async Task SetPublishedContentAsOtherPageAsync(HttpContext httpContext, IPublishedRequest publishedRequest, int pageId) + private async Task SetPublishedContentAsOtherPageAsync(HttpContext httpContext, IPublishedRequest? publishedRequest, int pageId) { - if (pageId != publishedRequest.PublishedContent.Id) + if (pageId != publishedRequest?.PublishedContent?.Id) { var umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); - IPublishedContent publishedContent = umbracoContext.PublishedSnapshot.Content.GetById(pageId); - if (publishedContent == null) + IPublishedContent? publishedContent = umbracoContext.PublishedSnapshot.Content?.GetById(pageId); + if (publishedContent is null || publishedRequest is null) { throw new InvalidOperationException("No content found by id " + pageId); } diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs index 60384de752..12ca67ce17 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValueTransformer.cs @@ -96,30 +96,30 @@ namespace Umbraco.Cms.Web.Website.Routing // If we aren't running, then we have nothing to route if (_runtime.Level != RuntimeLevel.Run) { - return null; + return null!; } // will be null for any client side requests like JS, etc... - if (!_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext umbracoContext)) + if (!_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? umbracoContext)) { - return null; + return null!; } if (!_routableDocumentFilter.IsDocumentRequest(httpContext.Request.Path)) { - return null; + return null!; } // Don't execute if there are already UmbracoRouteValues assigned. // This can occur if someone else is dynamically routing and in which case we don't want to overwrite // the routing work being done there. - UmbracoRouteValues umbracoRouteValues = httpContext.Features.Get(); + UmbracoRouteValues? umbracoRouteValues = httpContext.Features.Get(); if (umbracoRouteValues != null) { - return null; + return null!; } // Check if there is no existing content and return the no content controller - if (!umbracoContext.Content.HasContent()) + if (!umbracoContext.Content?.HasContent() ?? false) { return new RouteValueDictionary { @@ -139,7 +139,7 @@ namespace Umbraco.Cms.Web.Website.Routing httpContext.Features.Set(umbracoRouteValues); // Need to check if there is form data being posted back to an Umbraco URL - PostedDataProxyInfo postedInfo = GetFormInfo(httpContext, values); + PostedDataProxyInfo? postedInfo = GetFormInfo(httpContext, values); if (postedInfo != null) { return HandlePostedValues(postedInfo, httpContext); @@ -154,7 +154,7 @@ namespace Umbraco.Cms.Web.Website.Routing // our default 404 page but we cannot return route values now because // it's possible that a developer is handling dynamic routes too. // Our 404 page will be handled with the NotFoundSelectorPolicy - return null; + return null!; } // See https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.routing.dynamicroutevaluetransformer.transformasync?view=aspnetcore-5.0#Microsoft_AspNetCore_Mvc_Routing_DynamicRouteValueTransformer_TransformAsync_Microsoft_AspNetCore_Http_HttpContext_Microsoft_AspNetCore_Routing_RouteValueDictionary_ @@ -162,9 +162,9 @@ namespace Umbraco.Cms.Web.Website.Routing // So we create new ones. var newValues = new RouteValueDictionary { - [ControllerToken] = umbracoRouteValues.ControllerName + [ControllerToken] = umbracoRouteValues?.ControllerName }; - if (string.IsNullOrWhiteSpace(umbracoRouteValues.ActionName) == false) + if (string.IsNullOrWhiteSpace(umbracoRouteValues?.ActionName) == false) { newValues[ActionToken] = umbracoRouteValues.ActionName; } @@ -194,7 +194,7 @@ namespace Umbraco.Cms.Web.Website.Routing /// Checks the request and query strings to see if it matches the definition of having a Surface controller /// posted/get value, if so, then we return a PostedDataProxyInfo object with the correct information. /// - private PostedDataProxyInfo GetFormInfo(HttpContext httpContext, RouteValueDictionary values) + private PostedDataProxyInfo? GetFormInfo(HttpContext httpContext, RouteValueDictionary values) { if (httpContext is null) { @@ -211,13 +211,13 @@ namespace Umbraco.Cms.Web.Website.Routing if (!EncryptionHelper.DecryptAndValidateEncryptedRouteString( _dataProtectionProvider, ufprt, - out IDictionary decodedUfprt)) + out IDictionary? decodedUfprt)) { return null; } // Get all route values that are not the default ones and add them separately so they eventually get to action parameters - foreach (KeyValuePair item in decodedUfprt.Where(x => ReservedAdditionalKeys.AllKeys.Contains(x.Key) == false)) + foreach (KeyValuePair item in decodedUfprt.Where(x => ReservedAdditionalKeys.AllKeys.Contains(x.Key) == false)) { values[item.Key] = item.Value; } @@ -240,7 +240,7 @@ namespace Umbraco.Cms.Web.Website.Routing [ActionToken] = postedInfo.ActionName }; - ControllerActionDescriptor surfaceControllerDescriptor = _controllerActionSearcher.Find(httpContext, postedInfo.ControllerName, postedInfo.ActionName); + ControllerActionDescriptor? surfaceControllerDescriptor = _controllerActionSearcher.Find(httpContext, postedInfo.ControllerName, postedInfo.ActionName); if (surfaceControllerDescriptor == null) { @@ -258,11 +258,11 @@ namespace Umbraco.Cms.Web.Website.Routing private class PostedDataProxyInfo { - public string ControllerName { get; set; } + public string? ControllerName { get; set; } - public string ActionName { get; set; } + public string? ActionName { get; set; } - public string Area { get; set; } + public string? Area { get; set; } } // Define reserved dictionary keys for controller, action and area specified in route additional values data diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs index 5cba399fba..48348606f1 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Web.Website.Routing _defaultControllerName = new Lazy(() => ControllerExtensions.GetControllerName(renderingDefaults.Value.DefaultControllerType)); _defaultControllerDescriptor = new Lazy(() => { - ControllerActionDescriptor descriptor = _controllerActionSearcher.Find( + ControllerActionDescriptor? descriptor = _controllerActionSearcher.Find( new DefaultHttpContext(), // this actually makes no difference for this method DefaultControllerName, UmbracoRouteValues.DefaultActionName); @@ -75,7 +75,7 @@ namespace Umbraco.Cms.Web.Website.Routing throw new ArgumentNullException(nameof(request)); } - string customActionName = null; + string? customActionName = null; // check that a template is defined), if it doesn't and there is a hijacked route it will just route // to the index Action @@ -110,7 +110,7 @@ namespace Umbraco.Cms.Web.Website.Routing var customControllerName = request.PublishedContent?.ContentType?.Alias; if (customControllerName != null) { - ControllerActionDescriptor descriptor = _controllerActionSearcher.Find(httpContext, customControllerName, def.TemplateName); + ControllerActionDescriptor? descriptor = _controllerActionSearcher.Find(httpContext, customControllerName, def.TemplateName); if (descriptor != null) { hasHijackedRoute = true; @@ -142,7 +142,7 @@ namespace Umbraco.Cms.Web.Website.Routing && !_umbracoFeatures.Disabled.DisableTemplates && !hasHijackedRoute) { - IPublishedContent content = request.PublishedContent; + IPublishedContent? content = request.PublishedContent; // This is basically a 404 even if there is content found. // We then need to re-run this through the pipeline for the last diff --git a/src/Umbraco.Web.Website/Security/MemberAuthenticationBuilder.cs b/src/Umbraco.Web.Website/Security/MemberAuthenticationBuilder.cs index 8308abafff..a81cbfe73d 100644 --- a/src/Umbraco.Web.Website/Security/MemberAuthenticationBuilder.cs +++ b/src/Umbraco.Web.Website/Security/MemberAuthenticationBuilder.cs @@ -20,11 +20,11 @@ namespace Umbraco.Cms.Web.Website.Security public MemberAuthenticationBuilder( IServiceCollection services, - Action loginProviderOptions = null) + Action? loginProviderOptions = null) : base(services) => _loginProviderOptions = loginProviderOptions ?? (x => { }); - public string SchemeForMembers(string scheme) + public string? SchemeForMembers(string scheme) => scheme?.EnsureStartsWith(Constants.Security.MemberExternalAuthenticationTypePrefix); /// @@ -36,7 +36,7 @@ namespace Umbraco.Cms.Web.Website.Security /// /// /// - public override AuthenticationBuilder AddRemoteScheme(string authenticationScheme, string displayName, Action configureOptions) + public override AuthenticationBuilder AddRemoteScheme(string authenticationScheme, string? displayName, Action? configureOptions) { // Validate that the prefix is set if (!authenticationScheme.StartsWith(Constants.Security.MemberExternalAuthenticationTypePrefix)) diff --git a/src/Umbraco.Web.Website/Security/MemberExternalLoginsBuilder.cs b/src/Umbraco.Web.Website/Security/MemberExternalLoginsBuilder.cs index 4f8eb407be..22583e2cd8 100644 --- a/src/Umbraco.Web.Website/Security/MemberExternalLoginsBuilder.cs +++ b/src/Umbraco.Web.Website/Security/MemberExternalLoginsBuilder.cs @@ -24,7 +24,7 @@ namespace Umbraco.Cms.Web.Website.Security /// public MemberExternalLoginsBuilder AddMemberLogin( Action build, - Action loginProviderOptions = null) + Action? loginProviderOptions = null) { build(new MemberAuthenticationBuilder(_services, loginProviderOptions)); return this; diff --git a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs index abc46aacf1..7a2cf14c18 100644 --- a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs +++ b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs @@ -33,7 +33,7 @@ namespace Umbraco.Cms.Web.Website.ViewEngines return profiledResult; } - public ViewEngineResult GetView(string executingFilePath, string viewPath, bool isMainPage) + public ViewEngineResult GetView(string? executingFilePath, string viewPath, bool isMainPage) { using (_profiler.Step(string.Format("{0}.GetView, {1}, {2}, {3}", _name, executingFilePath, viewPath, isMainPage))) {