In your csproj file, add the following:
<Target Name="AddCustomLinkerDescriptor" AfterTargets="_CollectBlazorLinkerDescriptors">
<ItemGroup>
<BlazorLinkerDescriptor Include="CustomLinkerConfig.xml" />
</ItemGroup>
public class MyNetworkClient { | |
public event SomeDelegate OnException; | |
public async Task ConnectAsync(string address) { | |
await this.MakeTheActualConnection(address); | |
this.BeginReceiveLoop(); | |
} | |
// It's async void! But is that bad? | |
// I know that an unhandled exception here is going to bring down the process, but where else do you want |
@using StandaloneApp.Util | |
@(Layout<StandaloneApp.Shared.MainLayout>()) | |
<h1>Hello, world!</h1> | |
Welcome to your new app. | |
<button @onclick(DoRequest)>Do request</button> | |
<div><strong>Response: </strong>@responseText</div> | |
@functions { |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore; | |
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.Logging; |
class TaskResultUtil | |
{ | |
private static ConcurrentDictionary<Type, ITaskResultGetter> _cachedGetters = new ConcurrentDictionary<Type, ITaskResultGetter>(); | |
private interface ITaskResultGetter | |
{ | |
object GetResult(Task task); | |
} | |
private class TaskResultGetter<T> : ITaskResultGetter |
@* Unfortunately this has to be named BlazorForm, not Form, because we can't differentiate based on casing *@ | |
<form onsubmit=@HandleSubmit> | |
@ChildContent(_context) | |
</form> | |
@functions { | |
private FormContext _context = new FormContext(); | |
[Parameter] protected RenderFragment<FormContext> ChildContent { get; set; } | |
[Parameter] protected Action<FormContext> OnSubmit { get; set; } |
Blazor should make it easy to build all the classic high-level UI widgets, such as forms, grids, tabs, dialogs, and so on. One of the big technical pieces needed for this is templated components, and since 0.6.0 we have strong support for that. Another necessary bit of infrastructure is a mechanism for components to collaborate based on ancestor/descendant relationships. For example:
Form
component, you'd want nested Input
components to be able to affect the form's validation on submit.TabSet
component, you'd want the TabSet
to discover nested Tab
components so it knows what tab titles to display, and to render only the active one (either by TabSet
choosing which child to render, or by Tab
knowing whether it's currently the active one).NavBar
component, you'd want a HamburgerButton
component to be able to send a "toggle expansion" signal to the NavBar
.As of today, all these are possible but only through manual wiring. For exa
using Microsoft.AspNetCore.Blazor; | |
public interface ITab | |
{ | |
RenderFragment ChildContent { get; } | |
} |
This document describes options and proposals for #4048.
Principles:
Startup.cs
logic is completely different for the two runtime environments.The Razor Components auth feature set will be mostly the same as for MVC/Pages. We'll get the same long-tail features such as integration with 3rd-party social logins, 2FA, etc. The Razor Components template will support the same four auth options during project creation, and the "Scaffold Identity" feature will be usable on existing Razor Components projects.
Or in other words, why you should hard-code sequence numbers, and not generate them programmatically.
Unlike .jsx
files, .razor
/.cshtml
files are always compiled. This is potentially a great advantage for .razor
, because we can use the compile step to inject information that makes things better or faster at runtime.
A key example of this are sequence numbers. These indicate to the runtime which outputs came from which distinct and ordered lines of code. The runtime uses this information to generate efficient tree diffs in linear time, which is far faster than is normally possible for a general tree diff algorithm.