-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Blazor Hybrid Relative Path Handling #10898
Comments
Note that Oqtane (https://github.com/oqtane/oqtane.framework) is a modular app framework for Blazor and is already using the approach described above of including logic to render an absolute path when running on Blazor Hybrid, else render a relative path. In most cases it is working fine... however it does not seem to be the best solution... and there are some edge cases which are still not supported. For example, CSS files sometimes contain a url() function to include other CSS files. And usually the paths used in the url() function are specified in a relative manner. And because a CSS file is static there is no way to modify the behavior to use an absolute Url when running on Blazor Hybrid (without changing the CSS file itself - which is usually not recommended, especially if the CSS file is part of third part distribution such as an Icon library).
The use case of adding functionality to an application at run-time which is mentioned in the original post above is better explained in this blog: https://www.oqtane.org/blog/!/51/blazor-client-side-assembly-servicing . The modular architecture in Oqtane supports the dynamic servicing of micro-services and micro-frontends to create composable apps. |
Possibly related/similar to dotnet/aspnetcore#42924 ? |
Thanks for contacting us, @sbwalker. |
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
I realize that I did not provide a minimal repro - however the scenario is very easy to replicate. Basically create a shared razor component which contains an image tag. For the src attribute of the image tag, use a relative path to identify the resource (ie. image.png ). This component will work fine on Blazor Server and Blazor WebAssembly. Now assume that you do NOT want to package and deploy image.png with your Blazor Hybrid app - you want to reference the image on the server as your single source of truth. Run your Blazor Hybrid app and you will get a broken image (because the resource does not exist locally on the device). So what is the guidance to support this scenario ie. a shared component which works consistently in all Blazor hosting models? I would be very surprised if this scenario was an uncommon requirement. |
@sbwalker alright I think I understand now. An issue with something like a In my mind the only "reliable" way to do this would have to have a helper called |
@Eilon the GetAssetUrl() suggestion is exactly what I am doing in Oqtane already... but it feels like the wrong approach to treat this as a development concern (by forcing it to be implemented in the code itself) rather than a hosting model concern. And the suggestion does not handle the other scenario I documented above where static assets may also contain relative paths (ie. CSS url() method). To answer your question about the BlazorWebView property suggestion I was envisioning that if the new property was set and a reference was made to a relative path then it would add the property value to the path automatically. If the property was not set (the default) then no change in behavior. A developer would not be able to "mix modes" - if they want to bundle static resources locally with their app as part of deployment (the recommended model today) then they should not set the property. If they want to reference remote static resources then they can set the property. They would not be able to have some resources local and some remote as the property would have no way to determine how to handle them (unless this was enhanced to also include an asset manifest - but that would not be a requirement for the initial implementation) |
The ability to have razor components work seamlessly across ALL hosting models is definitely something that clients want. In addition, they do not always want to take on the burden of updating all client installations whenever a new version of their application is available. In many cases they would rather centralize the assets so that all client installations can share them. This is where a remote trusted server for assets can be very useful. Allowing components to leverage the same trusted remote server for CSS, JS, images, etc... allows the maximum code reusability across desktop, mobile, and web scenarios. |
@Eilon is there any update on this item? The shared razor component story would be greatly improved by this remote resource reference capability. The Android Asset Pack/Play Asset Delivery (PAD) with its Dynamic Delivery (ie. FastFollow or OnDemand) options provide a similar capability for native Android apps - referencing external assets so they do not need to be bundled with an app. |
@mkArtakMSFT I am not sure I understand how #11382 relates to this issue. Basically, all I need is way to reference remote assets in my shared components (without having to use absolute Urls) as this would allow me to create a shared component which works consistently in Blazor Web and Blazor Hybrid deployments. I am talking about remote static assets such as CSS, JS, or image files where there are no security/auth concerns. Do you suggest I add this clarification to #11382 so that it is considered in the final solution? |
Hi @sbwalker , this is from what we talked about at MVP Summit. In #11382 we would allow custom handling of requests coming from the WebView. So an app could say "I want to handle requests to |
Description
One of the major benefits of Blazor Hybrid is the ability to re-use a common set of components across web, mobile, and desktop. The razor component model works for the majority of use cases involving code, however there are currently some challenges when it comes to the management of static assets - specifically around relative paths. Note that static assets refer to any file which is delivered in an immutable form ie. CSS, JavaScript, images, icons, etc...The following diagram attempts to visualize the current behavior for static assets in various Blazor hosting models, as well as highlight the limitations in Blazor Hybrid.
On the left side you have a razor component which is intended to be used across all hosting models. It contains a reference to a static asset (x.png) using a relative path. The reference to the static asset will be rendered in a consistent manner across each of the hosting models. For Blazor Server and Blazor WebAssembly, the relative path refers to the static asset on the Server. However, for Blazor Hybrid, the relative path refers to the static asset on the client.
The means that there is no longer a single source of truth for your static assets. It means that anytime a new version of a static is created, it must be replicated or synchronized across all of the client installations. This may be acceptable in some environments, however in dynamic applications which allow for extensive run-time configuration this is highly problematic. For a simple example, consider an application which has a rich text editor where users can upload images to the server and then reference those images using standard relative paths. The image will be rendered correctly in Blazor Server and Blazor WebAssembly - however the image will not be rendered in Blazor Hybrid (because the image does not exist on the client). A more advanced example may be a modular system where an administrator can install new functionality at run-time... and this functionality will often have dependencies on static assets (which are expected to reside on the trusted server). Again, the functionality will work correctly in Blazor Server and Blazor WebAssembly - however not in Blazor Hybrid.
As explained above there are many scenarios where a Blazor Hybrid app may want a relative path static asset to refer to the object on a trusted server. Currently the only way to accomplish this is to use absolute paths in your components (ie. instead of src="x.png" the component would need to render src="https://mytrustedserver.com/x.png"). Hardcoding an absolute path is a bad practice for a variety of reasons, so this means that components would need to include some extra logic when creating references to static assets (ie. add the absolute path when running on Blazor Hybrid, else render a relative path). But polluting your components with this type of path logic does not feel like the correct solution. Unfortunately there currently does not seem to be any other solution to solve this problem currently.
I understand that there are some benefits of managing static assets on the client. Specifically, it would provide better performance as there would be less latency. Also it would allow the client to run off-line - ie. without a server connection. However the reality is that very few client applications in the real world need to run off-line - usually they need to interact with public APIs to retrieve data. Which means that off-line support is an edge case - not the primary use case for this technology. And if your app is going to access public APIs then why not allow it to also access public static assets? The counter-argument is that Blazor Hybrid already allows you to access public static assets - you just need to use an absolute Url reference - however this brings us full circle back to the discussion above.
On the topic of public APIs, they obviously need to access resources which do not exist on the client. This can be easily accomplished with HttpClient by configuring it as part of startup by providing a BaseAddress. Then the razor components can inject HttpClient and they will work fine regardless of the Blazor hosting model. Externalizing the behavior of relative paths to static assets would provide similar benefits.
One possible suggestion is to enhance the BlazorWebView with an optional property such as "StaticAssetBaseAddress". If a value was provided then all static assets could use it as a prefix - which would provide the ability to reference resources on a trusted server without resorting to custom logic within the components themselves.
Public API Changes
have not researched API changes needed
Intended Use-Case
explained above
The text was updated successfully, but these errors were encountered: