dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.2k stars 9.95k forks source link

Razor Pages UserControl replacement #41127

Open HybridSolutions opened 2 years ago

HybridSolutions commented 2 years ago

Is there an existing issue for this?

Is your feature request related to a problem? Please describe the problem.

Razor pages do indeed support components, but they are for rendering views only. Developing modular applications and promoting reuse of interactive UI blocks is very hard with Razor Pages.

Describe the solution you'd like

Please consider improving the support in View Components for dealing with events and postbacks. User controls in Webforms, allowed us to have blocks with full functionality and to deal with things so simple like a postback from a button click and on top of that, they could also be compiled, dynamically injected into a page and reused over and over.

Razor Pages need some kind of Components like UserControls or like Components in Blazor that can present data, deal with common interactivity and allow them to be reused by compiling them into a class library.

Without this, it's very hard to migrate from dynamic applications built on webforms.

Blazor has these features, but unfortunately, any minor changes to HTML code in already deployed .razor files always requires to recompile a project so it's not a viable solution for now in my point of view.

What is you opinion on this? Didn't you experience at some point this major gap? Here's a simple example:

How do you build a compiled, reusable component for newsletter subscription that receives an e-mail from the user and stores it into a DB with Razor Pages?

Thank you!

Additional context

No response

javiercn commented 2 years ago

@HybridSolutions thanks for contacting us.

We believe that Blazor Server is the natural replacement for the event-based web forms model and that's what we recommend people to switch to. We don't have plans to add features to MVC or Razor Pages to support this paradigm.

Blazor has these features, but unfortunately, any minor changes to HTML code in already deployed .razor files always requires to recompile a project so it's not a viable solution for now in my point of view.

I imagine this comes from the lack of Runtime Compilation for razor components. In that regard, I would point out that we've always considered Runtime Compilation a development feature before hot reload existed, and while we know of people using it in other contexts, it's not something that we've recommended nor encouraged.

HybridSolutions commented 2 years ago

@HybridSolutions thanks for contacting us.

We believe that Blazor Server is the natural replacement for the event-based web forms model and that's what we recommend people to switch to. We don't have plans to add features to MVC or Razor Pages to support this paradigm.

Blazor has these features, but unfortunately, any minor changes to HTML code in already deployed .razor files always requires to recompile a project so it's not a viable solution for now in my point of view.

I imagine this comes from the lack of Runtime Compilation for razor components. In that regard, I would point out that we've always considered Runtime Compilation a development feature before hot reload existed, and while we know of people using it in other contexts, it's not something that we've recommended nor encouraged.

I think Blazor is great but as I said, not being able to have a designer make even subtle changes to html code, and I mean not even touching any c# code, without having to be forced to manually recompile an entire project is just insane. Try that with a team and it just doesn't work. Really hope someday. NET team realizes this and finds a way of solving this problem. Thank you.

davidfowl commented 2 years ago

@HybridSolutions Is it to make quick fixes to HTML or something more permanent?

HybridSolutions commented 2 years ago

Don't quite understand your question. Are you asking about changes in a Razor Component? If yes, then it's any kind of changes. Change the class btn-primary to btn-danger on a button inside a component and there you go, call the development guy because we need to recompile the whole website and deploy it again to the web server.

davidfowl commented 2 years ago

Those fixes are made to the deployed assets. I'm assuming its about making quick fixes to the site that a developer will eventually also make in the main source (which will be redeployed eventually).

call the development guy because we need to recompile the whole website and deploy it again to the web server.

So the idea here is that there are non developers making changes to the HTML only in production right? Not the original source (or maybe they do that as well).

I'm trying to get an understanding of the workflow (I understand this is possible with runtime compilation but for your scenario, what is the typical workflow?)

HybridSolutions commented 2 years ago

First of all thank you for your interest. I'm going do describe exactly the workflow we have. We have our own CMS built on webforms and we are starting to prepare the transition to .NET 6 by using Razor Pages + Blazor.

Currently, our solution is deployed to each client host, and our designers create custom HTML templates (usercontrols - *.ascx) that have a couple server controls in it that define editable zones, where modules (News, login, galleries, etc) can be manually inserted by the clients using drag & drop whenever they want. Modules (usually, menus, footers, etc) can also be directly inserted by our designer in the template by using simple tags so that the client doesn't have to do it later for each page.

These templates do not need to be compiled. The designer or even the client with HTML knowledge can create and change each template very easily just by using a text editor.

If a client needs a template with a column on the left to place modules, it's a 5 minute task and it will only require an upload to the Templates folder after changes are made to the template.ascx file. No recompile, no developers envolved, just a notepad and a simple upload.

The same applies when changes are required for existing templates. Our designer changes the template using any html editor, places additional zones by placing the required zone server controls, saves and uploads it to the website. Runs the website, and changes show up immediately. Once again, no recompile, or calling the development team to develop a new template in Visual Studio, compile the solution or deploy dlls to the host.

Changes can be made by a junior designer that even doesn't know what c# is. Do you see the huge difference here? Usercontrols made possible to abstract c# code from designers!

With Blazor, we need to have a project for templates in Visual Studio, have a designer and a developer working on them at the same time, compile the templates or even the hole project for testing, deploy them to the website, and hope no more changes are required so that 2 people are not allocated to a simple task like changing the CSS class of a button. It's just not practical.

We need to be able to edit the HTML (I don't mean c# code!) of Razor components without the need of them to be recompiled using Visual Studio in a local development machine. We need our designer that works in a MAC or any other platform, in the office, at home or any other palce elese, to be able to open our DefaultTemplate.razor file and can change that CSS class of the button, and upload that file to the templates folder in the server.

That template has nothing to do with our Software solution. The designer doesn't even need to know how to open our solution in VS to be able to tweak a template.

Here's a concrete example:

This is our simplified template created by the designer. It only has HTML using some Bootstrap CSS and 3 other Razor Components that are used to define editable areas. Very similar to what we currently have with webforms and UserControls:

DefaultTemplate.razor

@inherits TemplateBase

@*Template HTML*@

<div class="container">
  <div class="row py-10">
    <div class="col-sm-4">
      <Zone Name="Left"></Zone>
    </div>
    <div class="col-sm-4">
      <Zone Name="Main"></Zone>
    </div>
    <div class="col-sm-4">
      <Zone Name="Right"></Zone>
    </div>
  </div>
</div>

@*End Template HTML*@

@code {
    public override string Zones => "Left;Main;Right";
}

Now let's imagine the client requires that the Left column is larger. Our designer opens the template file in a text editor, and changes the template to:

@inherits TemplateBase

@*Template HTML*@

<div class="container">
  <div class="row py-10">
    <div class="col-sm-6">
      <Zone Name="Left"></Zone>
    </div>
    <div class="col-sm-3">
      <Zone Name="Main"></Zone>
    </div>
    <div class="col-sm-3">
      <Zone Name="Right"></Zone>
    </div>
  </div>
</div>

@*End Template HTML*@

@code {
    public override string Zones => "Left;Main;Right";
}

The only change was in div CSS classes. Designer uploads the DefaultTemplate.razor to the client website, presses F5 and nothing changes. Oops! Recompile in Visual Studio is necessary!

davidfowl commented 2 years ago

Ah hah! CMS! That's what I was looking for! Thanks for the details.

cc @sebastienros for this thoughts.

HybridSolutions commented 2 years ago

Ah hah! CMS! That's what I was looking for! Thanks for the details.

cc @sebastienros for this thoughts.

Is that a good thing? I'm not crazy? 😃 Status.Resolved should be removed...

davidfowl commented 2 years ago

No but it’s not a typical server side application. Dynamic runtime compilation has been relegated to advanced scenarios where you may opt in and a CMS is one of them. We generally don’t feel the need to provide first class features optimized for CMS scenarios but are open to extensibility points to make building these sorts of scenarios easier.

Also there are some CMS platforms that were migrated to ASP.NET Core already so things like this are already possible, but we’re not planning to make dynamic compilation a first class feature for mainline runtime scenarios, the CMS needs to implement that in their own.

davidfowl commented 2 years ago

Also blazor components can have code behind instead of code inside of them. The compilation model (making changes to files outside of source) and the separation of code and html are different concerns.

HybridSolutions commented 2 years ago

No but it’s not a typical server side application. Dynamic runtime compilation has been relegated to advanced scenarios where you may opt in and a CMS is one of them. We generally don’t feel the need to provide first class features optimized for CMS scenarios but are open to extensibility points to make building these sorts of scenarios easier.

Also there are some CMS platforms that were migrated to ASP.NET Core already so things like this are already possible, but we’re not planning to make dynamic compilation a first class feature for mainline runtime scenarios, the CMS needs to implement that in their own.

I'm sure you know Oqtane. Well, it suffers exactly from what I described. You can't update template html without recompiling. I must say that I first found this issue while playing a bit with that platform and I started to become nervous. When you say CMS platforms already tackled this, I'm not so sure about that. At least Oqtane, one of the best Blazor examples out there did not and suffers from the issue.

HybridSolutions commented 2 years ago

Hi,

after researching a bit and thinking this over, we've found a way to overcome this issue but since we're just getting started with this approach I'm not sure of which problemas may arise when introducing some other required features. Fingers crossed!

So, here's a video of how using Razor Pages for the page (Runtime Compilation Package installed), View Components for the Zone component, Partial Views for the templates that use Zone View Components to define editable areas and Blazor for the modules that go into the zones, we accomplished template editing with NO COMPILATION required. Just open the template in any HTML editor, changes things, save and that's it!

The list of modules that each zone loads is passed as a model from the page itself so it can come from a database. For the sake of simplicity we just created the following model named PageData that will be passed from the Razor Page to the Partial View Template and then to each Zone View Component:

public class Module
    {
        public string Name { get; set; }
        public string Zone { get; set; }
        public int Value { get; set; }
        public int Order { get; set; }

        public Module (string name, string zone, int value, int order)
        {
            Name = name;
            Zone = zone;
            Value = value; // just a start value to use in Counter modules types
            Order = order;
        }
    }

    public class PageData
    {
        public string PageName { get; set; }
        public List<Module> Modules { get; set; } = new List<Module>();
    }

Now, look at the workflow and tell me that it's not practical and productive in a team environment were not everyone has Visual Studio or knows how to compile projects. Forgive me to say this, the approach for killing this kind of productivity and assume everyone inside a company must know c# and use Visual Studio is just not acceptable. It's ok, for projects that don't need UI changes, but not for web projects. It's not the real world. I agree that this should be an optional feature though, but not only for Razor Pages, but also for Blazor Server projects.

The video was recorded on a regular windows machine running Windows 11 and changes to the template was made using Visual Code (it's the tool our designer uses for HTML). Demo running on Edge browser.

Notice that since we haven't developed a module picker yet, we still have to do it by hand in code instead of getting the data from a database so ignore that in the video.

https://user-images.githubusercontent.com/8672899/162727127-f722cbe5-9750-48e9-9332-e767c50b99ca.mp4

davidfowl commented 2 years ago

No need to apologize, but there's no quick fix for this that will happen on our side and we haven't even decided to tackle the problem for Blazor. Supporting the runtime compilation model is ALOT of work and isn't even planned so I'd expect anything you want to work from a Blazor POV will be incompatible with that runtime compilations model, so I would avoid it for now if that's a hard requirement.

As for Razor Pages, at least there is currently runtime compilation and view components, practically speaking, it should be possible to accomplish what you want with what's there.

We'll need to have a bigger discussion with the team if we want to go down the runtime compilation path for Blazor, which is something we have no plans of doing right now.

ghost commented 2 years ago

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.