Replies: 14 comments 67 replies
-
Update 1/31/2024: all of the functionality in _Host has now been refactored... and Antiforgery is fully working once again. Hosting Model was enhanced to allow for selection of Render Mode and Interactivity: Interactive Server and Interactive WebAssembly render modes are both functional. .NET MAUI is also functional. |
Beta Was this translation helpful? Give feedback.
-
One of the major benefits of using a framework as opposed to building an application from a template, is that a framework is responsible for all of the foundational run-time concerns. Basically for Oqtane this means that the migration from the traditional Blazor approach to the modern Blazor approach in .NET 8 is handled at the framework level... and custom modules get the benefit of the new approach without having to invest time or energy into complex code migrations or re-architecture. |
Beta Was this translation helpful? Give feedback.
-
Update: 2/2/2024 - a lot of progress was made on Phase 1 of the migration effort this week. When using Interactive Render Mode you can install the framework. You can login/logout (using the new AddCascadingAuthenticationState service in .NET 8). You can specify Server, WebAssembly, or Auto modes. You can add new Sites with their own Render Modes. I have moved on to Phase 2 - Static Rendering. I added the ability for Module razor components to specify a RenderMode (ie. Interactive/Static) which would then utilize the default Interactivity for the Site (ie. Server, WebAssembly, Auto). Currently I am blocked by an issue where the UI is not rendering in the browser - however no exception is being thrown and nothing is being logged which could provide a clue as to why this is happening. Note that the Oqtane POC project does not suffer from this issue, so it is something unique to the Oqtane framework code base. I have reached out to Microsoft for assistance. I do expect there will be many issues to overcome in order to benefit from Static Rendering. For example, any functionality which relies on OnClick or OnChange events would need to change. OnAfterRender is not supported. JS Interop is not supported. Alternative approaches would need to be considered for a lot of these scenarios - but only where it makes sense. From a high level the idea is that the core framework itself should support both static and interactive scenarios - however modules will have the ability to indicate that they require interactivity which will allow them to continue to function without any code changes (Interactive will be the default render mode for modules for backward compatibility reasons). |
Beta Was this translation helpful? Give feedback.
-
I have now spent 2 full days on the static rendering problem and I have still not been able to resolve it - however I was able to isolate the problem to the SiteRouter. Basically what is happening, is when running the framework in Static rendering mode, as soon as a backend service is called which uses HttpClient, it results in a short circuit of component rendering. To simplify things I created a simple component named Test.razor which displays the text [TEST]. I then modified the SiteRouter to display this component rather than ThemeBuillder (which is more complex as it loads a lot of nested child components). I modified the logic in the SiteRouter.razor Refresh() method to return at an earlier point in the processing:
Results in the [TEST] message being displayed in the browser. However, this code:
Results in a blank screen in the browser. Note that it does not matter which HttpClient service wrapper I reference (I have experimented with a number of them)… they all result in the component not being rendered. However, the service call does complete successfully... it calls the back-end server API method and returns the result successfully:
At this point I do not understand how component rendering could be affected by an HttpClient service call. Something strange is happening during static rendering – but there are no exceptions, errors in the browser console, etc… No clues as to why this is happening. Note that the reason why the POC project did not experience this problem is that it does not make any HttpClient service calls in its SiteRouter. |
Beta Was this translation helpful? Give feedback.
-
I was able to reproduce the problem in the Oqtane SSR POC application: If I remove the service call in OqtaneSSR.Client\Components\Router\SiteRouter.razor:
The OqtaneSSR.Client\Components\Modules\Home.razor component will display “Hello World!”: However if I include the service call in OqtaneSSR.Client\Components\Router\SiteRouter.razor:
The component does not display “Hello World!”: I am hoping that this code and repro will help identify the source of the problem. |
Beta Was this translation helpful? Give feedback.
-
@sbwalker Microsoft I believe says in documentation that for component library authors to set components to use stream rendering as it will work with all. If you think about it Oqtane Framework is like a massive library that gets extended. There is a slow feeling clicking between pages waiting for them each to render currently with static SSR and Oqtane. I expected more blink of the eye but it takes a moment to process a page. But I understand this should be expected behavior. Maybe production page loads will run quicker. The HTTPCLient issue was leading me here thinking maybe it was a cache issue or header issue, or maybe one of those would help. Then I read up some more on some static server-side rendering best practices. I would like to be sure to review all the security precautions while making adjustments as there are some things to investigate further still. There can be a switch to set which types of forms to be used, ie. if sSSR is enabled run different UI logic to make it interactive as needed. This would limit breaking changes, however it would be nice to try to ensure skins flow between the two with minimal additions. May need an ssr class or an id for a CSS selector for styles. Just thinking out loud here sorry getting excited to see this all pull together. Thank you 🚀 Edited note: I can most likely, definitely help here I believe I just would like to see one example first to be sure I follow patterns. For example if you do a larger one, I could work on the less difficult conversions and by the second or third PR start rolling them out the PR line. I have done a lot of them in the past in practice, but it has been a while. However, I have done it for a variety of services for both client and server using different structures from the courses I took. So once you start putting these out I guess I am warning you I may attempt doing a few myself. Not trying to take this topic off coarse, If you can please start another topic relating to this end note. Thanks again! |
Beta Was this translation helpful? Give feedback.
-
@thabaum in order to allow the Logout button to function in both Static and Interactive render modes, I had to get rid of the onclick event handler on the button and use a standard form post instead: Oqtane.Client\Themes\Controls\Theme\Login.razor Replace:
With:
This is working fine - however it causes a cosmetic styling issue: I am not sure why the button within a form is behaving completely different than a standalone button - perhaps its a Bootstrap issue. If you have time to explore this, it would be helpful as there will be many places where buttons will need to be replaced with forms. |
Beta Was this translation helpful? Give feedback.
-
I had that problem with https:/AIStoryBuilders/AIStoryBuilders. It is a MAUI program and the solution for me was to enable Android builds. |
Beta Was this translation helpful? Give feedback.
-
Update 2/9/2024: You can install Oqtane, login, and go into Site Settings and scroll to Hosting Model and change the Render Mode to Static Server Rendering and Interactivity to Server. In this configuration the theme, containers, and Html/Text module will all render statically. If you click on the "host" link to access the User Profile it will be displayed and it will indicate Render Mode: Interactive. However if you click the Save button nothing will happen because it is in fact in static render mode. I have spent the past day trying to determine why this is not working as expected - as it is working in the Oqtane SSR POC project which emulates the same nesting of components and uses the same technique for setting the render mode. |
Beta Was this translation helpful? Give feedback.
-
This was my first guess, and I tried to work on this and maybe the problem is within this issue described about serialization of a parameter earlier produced from that error. However from my last notes I show the Login page Login2 and Login3 buttons working, on homepage they are not. To summarize, I believe that there are two ways to set render modes, and one works for the pages which would be site level for Oqtane and the other for components. The previous post explains why I believe this to be the case. I am still learning here so not 100% sure how to come up with a solution other than separation of concerns using the current logic for site level, and introducing logic that replicates the POC for module level. I am on idle for working on it today, but I will continue to think about it and test a thing or two throughout the day/night. I will be more active on this tomorrow. Quick links to related areas of interest for render mode, parameters and prerendering settings:Page level or app level prerendering:
Component Render Modes:
Serializable parameters:I believe Microsoft documentation could clarify this better if it is the case. So much is scattered all over the place, a clue here, a clue there type of coding treasure hunt. |
Beta Was this translation helpful? Give feedback.
-
Update 2/12/2024: I was finally able to identify the interactive rendering issue. The obscure JavaScript error ("The list of component operations is not valid") from the browser console which @thabaum posted on the weekend provided a clue. This led me to Stack Overflow which suggested that it could be caused by parameter serialization. So I concluded that one difference between the POC and the full Oqtane framework is that the SiteState, PageState, and ModuleState classes have many more properties in the full framework than they do in the POC. So perhaps one of these classes contained a property which was not serializable. So I added some debugging logic to ModuleInstance.razor to attempt to serialize and then deserialize each parameter value which needed to be passed to the RenderModeBoundary.razor component (using the JsonSerializer): As you can see it identified an error deserializing the PageState value. This is due to the Route property which is based on a class that only has a single constructor which requires parameters. Obviously .NET does not know how to handle this constructor - so it throws a deserialization exception. Adding a parameterless constructor resolves this issue:
And with this tiny change (#3768), interactive rendering is now working as expected for modules. NOTE: although this resolves the fundamental issue for allowing module components to render interactively, there are MANY scenarios which are incomplete. Specifically, any UI scenario which is expected to support static rendering (ie. is not a module component) will need to be refactored to support the static methodology. |
Beta Was this translation helpful? Give feedback.
-
Update 2/13/2024: I have migrated a number of UI use cases to use the Static approach. In particular I have been focusing on the Control Panel as it is a central UI feature in Oqtane - and it needs to support both Static and Interactive render modes. One use case which was never explored in the POC was related to In Interactive rendering it is very easy to wire up an
However this event is not supported in Static rendering (neither is The only examples are for |
Beta Was this translation helpful? Give feedback.
-
@sbwalker does this help
Use different events for binding and handling. You can bind the value of your input element to a property using the @bind-value:event=“onchange” attribute, and then handle the input event separately using the @oninput attribute. For example: |
Beta Was this translation helpful? Give feedback.
-
@sbwalker I am seeing two uses of getting the page render mode: One was just shortened it looks like intentionally here: https:/oqtane/oqtane.framework/pull/3797/files 2 Are these two different render mode classes that Oqtane will support. If this is being moved would it be helpful for me to or will you update them all to the new namespace? |
Beta Was this translation helpful? Give feedback.
-
Oqtane 5.0 is already running on .NET 8... however it is still using the traditional Blazor approach in terms of hosting models ie. it supports Blazor Server and Blazor WebAssembly but it is not utilizing any of the new features introduced in .NET 8.
As discussed previously... the goal is to integrate the new Blazor features into Oqtane so that developers have the flexibility to leverage the full capabilities of Blazor. The plan is to tackle this work in few distinct phases:
Phase 1.
Make the foundational changes to the project structure to utilize the new Blazor Web App approach. Technically this means a change from using blazor.server.js/blazor.webassembly.js to using blazor.web.js (and a refactoring of a number of aspects of the Blazor application). In this initial phase the framework will only focus on Global Interactivity and ensuring all scenarios continue to function as they did previously.
Phase 2.
Implement Static Server-Side Rendering to enable modules to execute as either static or interactive components. The major challenge of this phase is expected to be dealing with state management (in a backward compatible manner).
It would be beneficial if both of these phases could be completed and included in the upcoming 5.1 release.
PLEASE NOTE... the Dev branch is expected to experience some instability while these changes are being introduced. So if you want to develop against a stable platform, you are encouraged to use the Master branch - or an official prior release.
PR #3697 is the initial commit for Phase 1 which starts moving the framework in this direction. The initial changes are largely based on the efforts which were invested over the past couple months on the Oqtane SSR POC project (https:/oqtane/OqtaneSSR) which provided a way to overcome some of the major obstacles and prove the viability of the new approach.
The current code in the Dev branch is functional - it allows you to create a new installation and navigate around the application. Currently it is hardcoded to InteractiveServer render mode. There are a number of specific features which were implemented in _Host that are commented out and will need to be refactored, including Visitor Management, Url Mapping Redirects, etc... In addition, Antiforgery is currently disabled at the application level as it is not working properly after the initial commit.
If you do any testing please log the issues under version 5.0.3 for now so that it is clear which codebase you are using.
Beta Was this translation helpful? Give feedback.
All reactions