(MVC) MVC (2020)

Blazor syntax and opportunity

In this page I want to create my view to Blazor syntax, opportunity and main programming techniques. Similar review I was written in 2002-year, when Microsoft was created NET Framework 1.1, Visual Basic 7 and Classic ASP.NET - Как я осваивал .NET-framework., Как я осваивал .NET-студию., Язык программирования VB.NET and when I made important step in my life - step from VB6 to VB7. Then in 2010 I made next important step in my life - moving from Classic ASP.NET to ASP.NET MVC - Мой первый сайт на MVC 3 Razor.

And now, in 2020, I'm reading current Microsoft documentation to this technology - MS ASP.NET.pdf trying to moving to this techniques and I want to write my small notice review of Blazor syntax and opportunity.


1. How Blazor work (Layout, SignaR, Static/dynamic page).

Because MS always doing one step forward and two step backward, Blazor is some kind of reincarnation of Classic ASP.NET. This is a good news for me, because MS agreed with my deep feeling, than ASP.NET MVC with complex and sophisticated frontend like Angular was bee greatest mistake. 2020 year is good time of return to Classic ASP.NET.

This is documentation of Blazor for Classic ASP.NET programmer. It contains only couple page, because we have always understanding this technology.



This is scheme to configuring common NET Core environment and Blazor start page.



You can see (and parse!) only static page in browser. In the screen below you can understand what in Layout (Master Page in term of Classic ASP.NET) or for russian speaking its named "плашка сайта".



If page rendering dynamically, you can not see HTML at all. And Browser developer tools nothing to show. But If you connect browser through proxy (How to debug SignalR application in Net Core 3.1), you can see full SignalR traffic.



2. C# expression.

In Blazor HTML-page we can use directly any C# C# statements, operators, variables as Blazor expression (after "@" without generic or after "@()"), this is MS description of Blazor Expression.





Preprocessor directives
NameSpace
Control flow
Events/delegates
Variables
Adding string, numeric, float, delegate
Compare
Null (Nothing)
in C# is absent:
Access modifier
Instantiate
OOP keywords
Type check and conversion
In C# is absent built-in conversion
Other keywords
MultiThreading
Generic
Pointer operators
Logical and bitwise
Array access
Math operation
Other modifiers
In C# is absent


3. Rules to link own C# code with HTML.

We can inserting own C# code into Blazor lifeCycle in some place.


   1:          public virtual Task SetParametersAsync(ParameterView parameters);
   2:          protected virtual void BuildRenderTree(RenderTreeBuilder builder);
   3:          protected Task InvokeAsync(Action workItem);
   4:          protected Task InvokeAsync(Func<Task> workItem);
   5:          protected virtual void OnAfterRender(bool firstRender);
   6:          protected virtual Task OnAfterRenderAsync(bool firstRender);
   7:          protected virtual void OnInitialized();
   8:          protected virtual Task OnInitializedAsync();
   9:          protected virtual void OnParametersSet();
  10:          protected virtual Task OnParametersSetAsync();
  11:          protected virtual bool ShouldRender();
  12:          protected void StateHasChanged();


In Blazor we have some directives in HTML, for example in screen below you can see directive @OnClick. We can link own C# code by this way - assign string to directive.



Alternative way to link own C# function to HTML is Lambda expression @onclick=@(async ()=>await XXX(YYY))



This events calling in the green circle in diagram above, before OnAfterRendering events and this is MS description of ComponentBase context, available in C# code.



4. List of available HTML-event to link own handlers by C# code.

We have a lot of events to link own code, not only @OnClick.




Progress events
@onloadstartProgressEventArgs
@ontimeoutProgressEventArgs
@onabortProgressEventArgs
@onloadProgressEventArgs
@onloadendProgressEventArgs
@onprogressProgressEventArgs
@onerrorErrorEventArgs
General events
@onactivateEventArgs
@onbeforeactivateEventArgs
@onbeforedeactivateEventArgs
@ondeactivateEventArgs
@onendedEventArgs
@onfullscreenchangeEventArgs
@onfullscreenerrorEventArgs
@onloadeddataEventArgs
@onloadedmetadataEventArgs
@onpointerlockchangeEventArgs
@onpointerlockerrorEventArgs
@onreadystatechangeEventArgs
@onscrollEventArgs
Focus events
@onfocusFocusEventArgs
@onblurFocusEventArgs
@onfocusinFocusEventArgs
@onfocusoutFocusEventArgs
Mouse events
@onmouseoverMouseEventArgs
@onmouseoutMouseEventArgs
@onmousemoveMouseEventArgs
@onmousedownMouseEventArgs
@onmouseupMouseEventArgs
@onclickMouseEventArgs
@ondblclickMouseEventArgs
@oncontextmenuMouseEventArgs
@onwheelWheelEventArgs
@onmousewheelWheelEventArgs
Drag events
@ondragDragEventArgs
@ondragendDragEventArgs
@ondragenterDragEventArgs
@ondragleaveDragEventArgs
@ondragoverDragEventArgs
@ondragstartDragEventArgs
@ondropDragEventArgs
Clipboard events
@onbeforecopyEventArgs
@onbeforecutEventArgs
@onbeforepasteEventArgs
@oncopyClipboardEventArgs
@oncutClipboardEventArgs
@onpasteClipboardEventArgs
Keyboard events
@onkeydownKeyboardEventArgs
@onkeyupKeyboardEventArgs
@onkeypressKeyboardEventArgs
Input events
@onchangeChangeEventArgs
@oninputChangeEventArgs
@oninvalidEventArgs
@onresetEventArgs
@onselectEventArgs
@onselectstartEventArgs
@onselectionchangeEventArgs
@onsubmitEventArgs
Touch events
@ontouchcancelTouchEventArgs
@ontouchendTouchEventArgs
@ontouchmoveTouchEventArgs
@ontouchstartTouchEventArgs
@ontouchenterTouchEventArgs
@ontouchleaveTouchEventArgs
Pointer events
@ongotpointercapturePointerEventArgs
@onlostpointercapturePointerEventArgs
@onpointercancelPointerEventArgs
@onpointerdownPointerEventArgs
@onpointerenterPointerEventArgs
@onpointerleavePointerEventArgs
@onpointermovePointerEventArgs
@onpointeroutPointerEventArgs
@onpointeroverPointerEventArgs
@onpointerupPointerEventArgs
Media events
@oncanplayEventArgs
@oncanplaythroughEventArgs
@oncuechangeEventArgs
@ondurationchangeEventArgs
@onemptiedEventArgs
@onpauseEventArgs
@onplayEventArgs
@onplayingEventArgs
@onratechangeEventArgs
@onseekedEventArgs
@onseekingEventArgs
@onstalledEventArgs
@onstopEventArgs
@onsuspendEventArgs
@ontimeupdateEventArgs
@onvolumechange EventArgs
@onwaitingEventArgs

More detail about Event see please in MS Documentation ASP.NET Core Blazor event handling.

5. List of available Blazor directives.

This is list of Page-Directives - MS Description.

  • @attribute
  • @code
  • @implements
  • @inherits
  • @inject
  • @layout
  • @namespace
  • @page
  • @typeparam
  • @using

And example of use it.



Also there are 5 Html-Directives. @bind and @on is metadirectives, @on mention in section above, @attributes in section below.

  • @attributes
  • @bind
  • @on{event}
  • @key
  • @ref

6. List of available Blazor attributes.

Property and method in C# code can be marked by some attributes Microsoft.AspNetCore.Components Namespace.

  • [BindElement]
  • [BindInputElement]
  • [CascadingParameter]
  • [EventHandler]
  • [Inject]
  • [Layout]
  • [Parameter]
  • [Route]

7. Call Javascript from Blazor and call Blazor from Javascript.

In Blazor we can execute JS by the pattern below.



This is right way to calling JS.



But not standard library as jQuery and many other JS library has conflict with _framework/blazor.server.js, for example Pace.JS (because PACE.JS is part of blazor.server.js and all js-constants will be doubled). This message show PACE.JS, included in blazor.server.js



In opposite direction you can call Blasor component from JS.



8. Capturing HTML-Attributes.

In screen below component receive two parameters (width, heigh) and set in to image.



9. Set style of HTML-elements.

Raw method of changing CSS looks as this



But if we create CSS helper.



CSS will be changed more simple.



And even more simple with static definition of this helper.



Usually I always create my own HTML-helper in this case How to create Razor html-helper in VB.NET, but at the moment I write this notice I don't understand how to do this in Blazor.

10. Forms and Validation.

There are some tags rendering to HTML-input elements.



DataAnnotation in Model is processing as usually automatically by DataAnnotationsValidator. And this is common patter to use it.



Instead MS DataAnnotationsValidator it's possible to create custom validation component in the pattern below, validator component nested from Abstract validator.



More details about validation see please in MS documentation - ASP.NET Core Blazor forms and validation and Forms and validation.

11. Two-way data binding.

Any HTML property or component parameters can be binding to data structure, Data must be parameters to binding XXX and EventCallback XXXChanged.



Binding tag also has two modifier - format and culture.



12. NET Core tags and attributes.

We can imports all NET Core tags to blazor CHTML-file (not in Blazor !) - Tag Helpers in forms in ASP.NET Core, Built-in ASP.NET Core Tag Helpers.



After that will be accessible a lot of ancient (but useful HTML-helpers).



For example this helper generate input=text with additional attributes two-way binded to data.


@Html.EditorFor(model => model.YourProperty, new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })
@Html.ValidationSummary

Also there are more modern way to receive access to ASP.NET server functionality of this tags.


asp-action
<a asp-controller="Speaker" asp-action="Evaluations">Speaker Evaluations</a>
asp-controller
<a asp-controller="Speaker" asp-action="Index">All Speakers</a>
asp-area
<a asp-area="Sessions" asp-page="/Index">View Sessions</a>
asp-fragment
<a asp-controller="Speaker" asp-action="Evaluations" asp-fragment="SpeakerEvaluations">Speaker Evaluations</a>
asp-host
<a asp-protocol="https" asp-host="microsoft.com" asp-controller="Home" asp-action="About">About</a>
asp-protocol
<a asp-protocol="https" asp-controller="Home" asp-action="About">About</a>
asp-route
<a asp-route="speakerevals">Speaker Evaluations</a>
[Route("/Home/Test", Name = "Custom")]
asp-all-route-data
<a asp-route="speakerevalscurrent" asp-all-route-data="parms">Speaker Evaluations</a>
asp-route-*
<a href="/Speaker/Detail?speakerid=12">SpeakerId: 12</a>
asp-page
<a asp-page="/Attendee">All Attendees</a>
asp-page-handler
<a asp-page="/Attendee" asp-page-handler="Profile" asp-route-attendeeid="12">Attendee Profile</a>
  
asp-action
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home" asp-action="Index">
<input type="submit" asp-controller="Home" asp-action="Index">Send</button>
<form asp-controller="Home" asp-action="Index">
asp-controller ...
asp-area ...
asp-page ...
asp-page-handler ...
asp-route ...
asp-route-{value} ...
asp-all-route-data ...
asp-fragment ...
cache-enabled
<cache enabled="true">
<distributed-cache name="MyCache" enabled="true">
cache-expires-on
<cache expires-on="@new DateTime(2025,1,29,17,02,0)">
<distributed-cache name="MyCache" expires-on="@new DateTime(2025,1,29,17,02,0)">
cache-expires-after
<cache expires-after="@TimeSpan.FromSeconds(120)">
<distributed-cache name="MyCache" expires-after="@TimeSpan.FromSeconds(120)">
cache-expires-sliding
<cache expires-sliding="@TimeSpan.FromSeconds(60)">
<distributed-cache name="MyCache" expires-sliding="@TimeSpan.FromSeconds(60)">
cache-vary-by-header
<cache vary-by-header="User-Agent">
<distributed-cache name="MyCache" vary-by-header="User-Agent">
cache-vary-by-query
<cache vary-by-query="Make,Model">
<distributed-cache name="MyCache" vary-by-query="Make,Model">
cache-vary-by-route
<cache vary-by-route="Make,Model">
<distributed-cache name="MyCache" vary-by-route="Make,Model">
cache-vary-by-cookie
<cache vary-by-cookie=".AspNetCore.Identity.Application">
<distributed-cache name="MyCache" vary-by-cookie=".AspNetCore.Identity.Application">
cache-vary-by-user
<cache vary-by-user="true">
<distributed-cache name="MyCache" vary-by-user="true">
cache-vary-by
<cache vary-by="@Model">
cache-priority
<cache priority="High">
<distributed-cache name="MyCache" priority="High">
environment-names
<environment names="Staging,Production">
environment-include
<environment include="Staging,Production">
environment-exclude
<environment exclude="Development">
component
<component type="typeof(ColorfulCheckbox)" render-mode="ServerPrerendered" param-Size="14" param-Color="@("blue")" />
asp-append-version
<img src="~/images/asplogo.png" asp-append-version="true">
asp-antiforgery
<form asp-controller="Home" asp-action="Index" asp-antiforgery="true" asp-route-returnurl="@ViewData["ReturnUrl"]" >
asp-for, asp-items
<select asp-for="Country" asp-items="Model.Countries"></select>
asp-for
<input asp-for="<Expression Name>">
asp-validation-for
<span asp-validation-for="Email"></span>
asp-antiforgery
<form asp-controller="Home" asp-action="Index" asp-antiforgery="true" >
Html.ValidationMessageFor
<span asp-validation-for="Email"></span>
ValidationSummary.All/ModelOnly/None
<div asp-validation-summary="ModelOnly"></div>


Some this tags we can directly use in our Blazor program, for example validation tags:



13. Additional NET Core attributes for standard HTML5-tags.

At the moment we have a lot of HTML-tags, but NET Core provide huge number of additional attributes. For example, HTML5 standard describe 25 attributes of HTML5-Button element: accesskey, autofocus, class, contenteditable, data-*, dir, disabled, draggable, form, formaction, formenctype, formmethod, formnovalidate, formtarget, hidden, id, lang, name, spellcheck, style, tabindex, title, translate, type, value. But Blazor support 14 tags for the same HTML-Button element:

  • contextmenu
  • dropzone
  • inert
  • itemid
  • itemprop
  • itemref
  • itemscope
  • itemtype
  • prefix
  • property
  • resource
  • role
  • typeof
  • uiactions
  • vocab

14. Blazor HTML-tags (component).

We have four group of Blazor tags in the standard blazor namespaces (selected in _Imports.razor):

  • @using Microsoft.AspNetCore.Authorization
  • @using Microsoft.AspNetCore.Components.Authorization
  • @using Microsoft.AspNetCore.Components.Forms
  • @using Microsoft.AspNetCore.Components.Routing
  • @using Microsoft.AspNetCore.Components.Web

That is:

  • <AuthorizeRouteView Authorizing= Context= DefaultLayout= NotAuthorized= RouteData= />
  • <AuthorizeView Authorized= Authorizing= ChildContent= Context= NotAuthorized= Policy= Resource= Roles= />

  • <CascadingAuthenticationState ChildContent= />
  • <CascadingValue ChildContent= IsFixed= Name= TValue= Value= />

  • <EditForm AdditionalAttributes= ChildContent= Context= EditContext= Model= />
  • <InputCheckbox AdditionalAttributes= Value= ValueChanged= ValueExpression= />
  • <InputDate AdditionalAttributes= ParsingErrorMessage= TValue= Value= ValueChanged= ValueExpression= />
  • <InputNumber AdditionalAttributes= ParsingErrorMessage= TValue= Value= ValueChanged= ValueExpression= />
  • <InputSelect AdditionalAttributes= ChildContent= TValue= Value= ValueChanged= ValueExpression= />
  • <InputText AdditionalAttributes= Value= ValueChanged= ValueExpression= />
  • <InputTextArea AdditionalAttributes= Value= ValueChanged= ValueExpression= />

  • <DataAnnotationsValidator />
  • <ValidationMessage AdditionalAttributes= For= TValue= />
  • <ValidationSummary AdditionalAttributes= Model= />

We can see example of using this tags in my public project templates:

15. Additional MS library for Blazor.

There are some MS components, usually mandatory to each project:

  • Microsoft.AspNetCore.Components.NavigationManager
  • System.Net.WebClient
  • Microsoft.EntityFrameworkCore

16. Third-party components and extension for Blazor.

Microsoft provide only couple of poor component for Blazor.

  • <LayoutView ChildContent= Layout= />
  • <RouteData DefaultLayout= RouteData= />
  • <RouteView DefaultLayout= RouteData= />
  • <NavLink ActiveClass= AdditionalAttributes= ChildContent= Match= />

Its not seriously at all. Need to provide at least the same components that was in ASP.NET in 2002 year GridView, DataList and 50+ was present in MS AJAX package for Classic ASP.NET in 2005 year.

Therefore other company can be create various useful to programmer components Blazor Open Source Projects, for example Radzen Blazor Components containes 40+ free components, Blazorise is a good package too.

Also there are Blazor extension Extensions, it can be additional script like this Logging Extensions



But this Logging Extensions is stupid and inexplicable for me, it can be replaced only one line of Javascript code. If you download my own Blazor project template, you will see only one line Javascript I replace this extension.

17. jQuery support.

At the moment Blazor has 8 tags related to jQuery, but officially I don't see any documentation about its. Maybe this is only empty stubs for future.

  • <jq />
  • <jqScript />
  • <jqScriptCdnGoogle />
  • <jqScriptCdnMs />
  • <jqScriptMin />
  • <jqScriptUiCdnGoogle />
  • <jqScriptValidateCdnMs />
  • <jqScriptValidateUnobtrusiveCdnMs />

However I constantly use jQuery functionality in my Blazor projects and doing it in the same way:

18. User Identity in Blazor.

For accounting user Blazor perform ordinary NET Core classes Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext and classes derived from this class ApplicationDbContext:



But a lot of ordinary Net Core classes working with User Identity (like HttpContextAccessor, SignInManager<ApplicationUser>) is not working correctly in Blazor. Only classes with database (like UserManager<ApplicationUser>) still working in Blazor as in Net Core MVC.

Because Blazor use SignalR connection instead simple WebRequest/WebResponse, User Authentication is not similar to previous WebTechnology. There are two different methods of AU - with break existing socket connection and reestablishing it again with cookies with login after login will be processing by simple webRequest.



First method I have published in this project template:

And second method is use IdentityServer and JWT OWIN Token. Project template for method I will be publish soon.

19. What missing in Blazor?

In Blazor is missing five main components:

  • VB.NET support - Why Microsoft vilified Visual Basic ?. C# syntax was born in 1978 year and VB was been develop as improvement stupid C syntax, for delete most stupid C ideas, for example named full different conception like Inheritance and Implementation by the same character ":".
  • Designer like designer in Classic ASP.NET. Designer is not browser to show Html-markup, Designer give programmer main tools for RAPID creating sites, by click on HTML-elements EventHandler was been created automatically with all closures, Designer tools and so on.
  • Blazor contains only four simplest builting components, there are nothing convenient to ASP.NET Classic components like GridView, DataList and so on.
  • jQuery support and integration. jQuery was be supported perfectly in Classic ASP.NET and then MS leave to support most of main tools for programmers, of course including jQuery.
  • In each previously ASP.NET technology we can simple changing source code (including with Debugger) then simple press refresh in Browser and code was been recompiled and changing in background. After few seconds we was have new code in Browser and library. But in Blazor this development is not work now. If we want to change something, we must stop debugger, stop IIS, stop Browser. Make change and then restart application. This permanently restarting set of application slow down development process at millions times.


As a result, this restriction of ASP.NET Core Blazor technology give programmers only tiny percents of performance ASP.NET Classic programmers, in ASP.NET Core Blazor you will create for months the same site as Classic ASP.NET programmer could created during one day, but this obscure is full fit to Microsoft point of view - price of any software in the world must be increase, so that can be induce increase cost of Microsoft stock as software leader company.





<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <MAIL ME>  <ABOUT ME>  < THANKS ME>