Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created INavigationManager to replace Globals.NavigateURL #3160

Merged

Conversation

SkyeHoefling
Copy link
Contributor

@SkyeHoefling SkyeHoefling commented Oct 17, 2019

Closes: #3159

Summary

Refactored Globals.NavigateURL() to a new interface INavigationManager and updated ALL references to use dependency injection.

Note

This is a first attempt, and we may need to make several revisions to this or target 10.0 instead of 9.x.

Tasks

Below is a list of tasks that I need to complete prior to us accepting the PR. I will continue to edit them as we review the code changes:

  • Fix failing unit tests
  • Verify installer works
  • Verify DNN Happy Path - General workflow, login, logout, page management, etc.
  • Create DotNetNuke.Abstractions library to contain new common registrations such as INavigationManager
  • Create nuspec file for DotNetNuke.Abstractions so it can be registered as a NuGet library
  • Update all .ascx.cs injections to be private readonly instead of protected
  • Remove extra xml records added by Visual Studio (.csproj, .config files)
  • Add new unit tests for DotNetNuke.Common.NavigationManager

All Tasks Completed

bdukes
bdukes previously approved these changes Oct 17, 2019
DNN Platform/Library/Common/Globals.cs Outdated Show resolved Hide resolved
DNN Platform/Library/Common/Utilities/UrlUtils.cs Outdated Show resolved Hide resolved
DNN Platform/Library/DotNetNuke.Library.csproj Outdated Show resolved Hide resolved
DNN Platform/Library/Properties/AssemblyInfo.cs Outdated Show resolved Hide resolved
[assembly: InternalsVisibleTo("DotNetNuke.Modules.Journal")] // Once Globals is refeactored to Dependency Injection we should be able to remove this
[assembly: InternalsVisibleTo("DotNetNuke.Modules.RazorHost")] // Once Globals is refeactored to Dependency Injection we should be able to remove this
[assembly: InternalsVisibleTo("DotNetNuke.Website")] // Once Globals is refeactored to Dependency Injection we should be able to remove this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? The only internal type I'm seeing is NavigationManager, which none of these are directly referencing…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Globals.DependencyProvider (our DependencyInjection Container) is internal by design. However the entire platform doesn't fully support Dependency Injection and there are many areas where we need to manually resolve dependencies using the Service Locator Pattern

IMyCutomType myInstance = Globals.DependencyProvider.GetService<IMyCustomType>();

I am not sure the best way to approach this problem as to make this change I need all of those InternalsVisibleTo declarations otherwise we won't have access to the DependencyProvider.

@mitchelsellers and I have discussed in the past that we do not want to make the DependencyProvider public and it is internal to the platform.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, that works for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is creating Technical Debt for the platform. I don't like that I had to create all of these statements to allow classes to access Globals.DependencyProvider but it is a necessary evil. There is no way possible that we could migrate the entire platform to Dependency Injection in 1 Pull Request. That type of change is just way too massive and to consider it would require several weeks to review, at best.

As we proceed forward with more Dependency Injection changes we can re-evaluate these and remove them as needed. For example when the entry point of a certain workflow is being resolved by the container, that will allow us to use constructor injection further down the call stack. At that point we will be able to remove this, but not until then.

Ideally, there will never be any usage of Globals.DependencyProvider anywhere, but we are no where near that stage with our Dependency Injection usage

@SkyeHoefling
Copy link
Contributor Author

SkyeHoefling commented Oct 18, 2019

@bdukes I updated the code with a notable change of migrating INavigationManager to a new .NET Standard 2.0 project called DotNetNuke.Abstractions. A small problem with this migration is the dependency on PortalSettings. This demonstrates the tight-coupling that top-level code has with bottom-tier code and vice-versa which makes these changes very difficult.

My proposed solution is to create a new IPortalSettings in the DotNetNuke.Abstractions project. Then I updated the actual PortalSettings in DotNetNuke.Library to implement the class and updated code throughout. The reach of this change is pretty significant, be sure to take a close look at the following items:

  • IPortalController - I updated the GetCurrentPortalSettings() to be deprecated in lieu of changing the signature. If we were to change the signature to return IPortalSettings it will create a ripple effect and that is a much larger change. There is now a new method on the interface called GetCurrentSettings() which returns the IPortalSettings
  • Updated several usages of PortalSettings to IPortalSettings - I believe these changes are not breaking changes, even for public APIs, this is because PortalSettings now inherits from IPortalSettings
  • Removed [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] from the interface and implementation as recommended
  • I added IPortalController as a Dependency Injection registration so we can easily resolve it in the NavigationManager. This is the first instance Dependency Injection in the platform code where we have a dependency resolving another dependency. It is finally paying off 🎉

@SkyeHoefling SkyeHoefling requested a review from bdukes October 18, 2019 00:51
@SkyeHoefling
Copy link
Contributor Author

I fixed the failing unit tests. I needed to create a mock of IServiceProvider and INavigationManager and manually assign it to the Globals.DependencyProvider. The difficult part to this is handling the state of Singletons. DNN uses the Singleton pattern throughout the codebase, the usage of this pattern was caching state between test classes which demonstrates poor unit test isolation.

As we move forward, hopefully we can migrate these tests to use interfaces instead of the singleton pattern

@SkyeHoefling
Copy link
Contributor Author

Running ./build.ps1 -Target CreateInstall isn't working and I am waiting for build changes to be finalized from #3137. I have custom built an installer for this Pull Request but our installer files are too large to upload to GitHub. I have ran through the installer I have and this change does install correctly and basic DNN functionality appears to work.

If anyone wants to help verify this change I can email you the installer file or share it in one of the many slack channels we have in the DNN Community.

mitchelsellers
mitchelsellers previously approved these changes Oct 18, 2019
@SkyeHoefling SkyeHoefling force-pushed the globals_navigation_manager branch from c7452b4 to f02b63f Compare October 19, 2019 13:39
@SkyeHoefling
Copy link
Contributor Author

Since this is a large Pull Request, I saw it best to rebase on the latest changes. This is a common practice I have done on large PRs for other .NET open source projects (CoreFX).

The build updates appear to be working and I can now build this solution locally and get an installer that works for testing. Once the build completes check out the installer and see if it works for you as well.

I would love to find problems with the changes now so we can address them during the code review

@SkyeHoefling SkyeHoefling force-pushed the globals_navigation_manager branch from bd16e78 to f8b9050 Compare October 20, 2019 04:04
@SkyeHoefling SkyeHoefling force-pushed the globals_navigation_manager branch from f8b9050 to 326c80e Compare October 20, 2019 04:10
…ivate readonly since there should never be a child class
@SkyeHoefling
Copy link
Contributor Author

@mitchelsellers @bdukes
I have pushed some more changes to address some of our requested changes. Right now this PR is just about ready to merge. If you guys can review again and provide any additional feedback.

My next steps at this point:

  • Test the installer again (earlier tests proved to be successful)
  • Clean up PR to exclude extra content in .config and .csproj

@valadas valadas added this to the 9.4.2 milestone Oct 20, 2019
@SkyeHoefling
Copy link
Contributor Author

@bdukes @mitchelsellers
I have tested the installer and marked all tasks completed. I believe this PR is ready to be merged.

Unless you have additional feedback

Copy link
Contributor

@mitchelsellers mitchelsellers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - Need to be sure to test this during RC

Copy link
Contributor

@valadas valadas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@valadas valadas merged commit 484f17b into dnnsoftware:release/9.4.x Oct 22, 2019
mitchelsellers pushed a commit that referenced this pull request Oct 22, 2019
* Remove disposal of MemoryStream for email attachments sent using SendtokenizedBuilkEmail

* Corrected references to older site URL (#3056)

* Corrected references to older site URL

* corrected typo from replacement of registered character

* Made the BuildAll task default + docs

* Fixed a typo

* Update .github/BUILD.md

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Update .github/BUILD.md

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Remove reference to empty fs npm package (#3094)

fs is a core package, and the version on the npm registry is just an
empty package; this was almost certainly added accidentally

Fixes #3091

* Added defensive coding to prevent memory leaks

* Updates .Net 4.7.2 warning for NL and DE languages (#3032)

* Updated de-DE text

As per Sebastian Leupold translation

* Updated nl-NL warning about .Net 4.7.2

As per Timo Breumelhof translation

* DNN-29557 - Infinite while loop fix (#3123)

* Update Pages.resx

SEO tip for creating a title

(cherry picked from commit 04d1ee6)

* DNN-31121 - Fix the non alphanumeric character regex (#3059)

* DNN-7818: add send verification mail link in unverified message.

* Add 'fileName' to condition when checking request for logo file.

* Permissions for default folders (#3024)

(cherry picked from commit e77a281)

* DNN-32978 Copying pro html module don't modify the permission

* Fixes errors with previous build scripts following PB merge

* Updates issue templates and build docs (#3165)

* Updates documentation as per recent changes

* Added version information

* Removed unneeded BuildAll parameter

* Added back how to clean

* Was already clearer

* Documentation action cleanup (#3171)

* Add validation method with IsNullOrWhiteSpace check.  Use method to validate RoleGroup Name. closes #2927 (#3170)

* OAuthClientBase now returns the correct RequestingCode instead of aborting the thread (#3152)

* Created INavigationManager to replace Globals.NavigateURL (#3160)

* Added INavigationManager and updated Globals to reference new INavigationManager

* Updated CreateModule to use new INavigationManager

* Deprecated NavigateURL for v11.0

* Updated viewsource to use INavigationManager

* Migrated Globals.NavigateUrl to use INavigationManager

* Updated persona bar controllers to use NavigateUrl

* Refactored NavigateURL to use new INavigationManager

* Refactored Globals.NavigateURL -> INavigationManager

* Refactored more NavigationManager usages

* Updated more references to Globals.NavigateURL to use INavigationManager

* Cleaned up mistakes that happened in config files in csproj files. These changes were auto-generated by visual studio and shouldn't have been made

* removed generated nodes from csproj

* Fixed spacing in web.config

* Updated old Globals.NavigateURL methods to use registered INavigationManager so everything will execute the same code path

* Updated INavigationManager reference to be static readonly instead of an instance property

* Aliased Constants to 'Dnn.PersonaBar.Libary.Constants' to handle ambiguity

* Added DependencyInjection to website project and updated RazorHost and Export

* Updated DotNetNuke.Website Globals.NavigateURL references to use the new INavigationManager

* Added missing using statement

* Fixing typo

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Removing whitespace

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Fix typo

* Use GetRequiredService for INavigationManager

Rather than waiting for a null reference later when it's used, there's
never a scenario where this dependency is expected to be missing, so we
want to indicate that it's expected and recieve an error right away if
there's an issue

* Added new DotNetNuke.Abstractions project for storing different common abstractions for the platform

* Updated all (non website project) classes to use INavigationManager from the new DotNetNuke.Abstractions project

* Updated Website Project to use the INavigationManager from the new DotNetNuke.Abstractions project

* Removed unnecessary attributes from NavigationManager

* Updated redirection controller tests to mock out the DependencyProvider and the INavigationManager to fix failing unit tests

* Fixed failing unit tests with mocking out INavigationManager

* Removed private fields for DependencyProvider

* Added singleton clear statements to prevent the INavigationManager from remaining in memory and conflicts between unit tests

* Reset singleton state for PortalController to reduce side-effects from other tests and stale object state from Dependency Injection

* Moved state cleanup code to teardown routine

* Fixed failing unit tests in tests.web project. Added mocks for INavigationManager so the DepenencyProvider can resolve

* Added new DotNetNuke.Abstractions.nuspec to create NuGets during build

* Added missing nuspec files to the solution file

* Updated copyright on all nuget files

* Added .NET Foundation file headers to new Abstraction files

* Resolved duplicate addition of DotNetNuke.Abstractions to sln file

* Added SetTestableInstance and Clear methods to make it easier to test Components. The new methods are internal

* Added happy path test for Navigation Manager

* Added NavigationManager tests

* Updated all INavigationManager references in .ascx.cs files to use private readonly since there should never be a child class

* Removed extra's added by visual studio to .csproj files
@SkyeHoefling SkyeHoefling deleted the globals_navigation_manager branch October 24, 2019 13:25
DnnSoftwarePersian pushed a commit to DnnSoftwarePersian/Dnn.Platform that referenced this pull request May 17, 2020
* Remove disposal of MemoryStream for email attachments sent using SendtokenizedBuilkEmail

* Corrected references to older site URL (dnnsoftware#3056)

* Corrected references to older site URL

* corrected typo from replacement of registered character

* Made the BuildAll task default + docs

* Fixed a typo

* Update .github/BUILD.md

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Update .github/BUILD.md

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Remove reference to empty fs npm package (dnnsoftware#3094)

fs is a core package, and the version on the npm registry is just an
empty package; this was almost certainly added accidentally

Fixes dnnsoftware#3091

* Added defensive coding to prevent memory leaks

* Updates .Net 4.7.2 warning for NL and DE languages (dnnsoftware#3032)

* Updated de-DE text

As per Sebastian Leupold translation

* Updated nl-NL warning about .Net 4.7.2

As per Timo Breumelhof translation

* DNN-29557 - Infinite while loop fix (dnnsoftware#3123)

* Update Pages.resx

SEO tip for creating a title

(cherry picked from commit 04d1ee6)

* DNN-31121 - Fix the non alphanumeric character regex (dnnsoftware#3059)

* DNN-7818: add send verification mail link in unverified message.

* Add 'fileName' to condition when checking request for logo file.

* Permissions for default folders (dnnsoftware#3024)

(cherry picked from commit e77a281)

* DNN-32978 Copying pro html module don't modify the permission

* Fixes errors with previous build scripts following PB merge

* Updates issue templates and build docs (dnnsoftware#3165)

* Updates documentation as per recent changes

* Added version information

* Removed unneeded BuildAll parameter

* Added back how to clean

* Was already clearer

* Documentation action cleanup (dnnsoftware#3171)

* Add validation method with IsNullOrWhiteSpace check.  Use method to validate RoleGroup Name. closes dnnsoftware#2927 (dnnsoftware#3170)

* OAuthClientBase now returns the correct RequestingCode instead of aborting the thread (dnnsoftware#3152)

* Created INavigationManager to replace Globals.NavigateURL (dnnsoftware#3160)

* Added INavigationManager and updated Globals to reference new INavigationManager

* Updated CreateModule to use new INavigationManager

* Deprecated NavigateURL for v11.0

* Updated viewsource to use INavigationManager

* Migrated Globals.NavigateUrl to use INavigationManager

* Updated persona bar controllers to use NavigateUrl

* Refactored NavigateURL to use new INavigationManager

* Refactored Globals.NavigateURL -> INavigationManager

* Refactored more NavigationManager usages

* Updated more references to Globals.NavigateURL to use INavigationManager

* Cleaned up mistakes that happened in config files in csproj files. These changes were auto-generated by visual studio and shouldn't have been made

* removed generated nodes from csproj

* Fixed spacing in web.config

* Updated old Globals.NavigateURL methods to use registered INavigationManager so everything will execute the same code path

* Updated INavigationManager reference to be static readonly instead of an instance property

* Aliased Constants to 'Dnn.PersonaBar.Libary.Constants' to handle ambiguity

* Added DependencyInjection to website project and updated RazorHost and Export

* Updated DotNetNuke.Website Globals.NavigateURL references to use the new INavigationManager

* Added missing using statement

* Fixing typo

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Removing whitespace

Co-Authored-By: Brian Dukes <bdukes@engagesoftware.com>

* Fix typo

* Use GetRequiredService for INavigationManager

Rather than waiting for a null reference later when it's used, there's
never a scenario where this dependency is expected to be missing, so we
want to indicate that it's expected and recieve an error right away if
there's an issue

* Added new DotNetNuke.Abstractions project for storing different common abstractions for the platform

* Updated all (non website project) classes to use INavigationManager from the new DotNetNuke.Abstractions project

* Updated Website Project to use the INavigationManager from the new DotNetNuke.Abstractions project

* Removed unnecessary attributes from NavigationManager

* Updated redirection controller tests to mock out the DependencyProvider and the INavigationManager to fix failing unit tests

* Fixed failing unit tests with mocking out INavigationManager

* Removed private fields for DependencyProvider

* Added singleton clear statements to prevent the INavigationManager from remaining in memory and conflicts between unit tests

* Reset singleton state for PortalController to reduce side-effects from other tests and stale object state from Dependency Injection

* Moved state cleanup code to teardown routine

* Fixed failing unit tests in tests.web project. Added mocks for INavigationManager so the DepenencyProvider can resolve

* Added new DotNetNuke.Abstractions.nuspec to create NuGets during build

* Added missing nuspec files to the solution file

* Updated copyright on all nuget files

* Added .NET Foundation file headers to new Abstraction files

* Resolved duplicate addition of DotNetNuke.Abstractions to sln file

* Added SetTestableInstance and Clear methods to make it easier to test Components. The new methods are internal

* Added happy path test for Navigation Manager

* Added NavigationManager tests

* Updated all INavigationManager references in .ascx.cs files to use private readonly since there should never be a child class

* Removed extra's added by visual studio to .csproj files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants