Page 25 - MSDN Magazine, March 2019
P. 25

Figure 7 Adding the RegistrationForm.cshtml File
Figure 8 Updating the Error Message
@page "/registrationform" @inject HttpClient Http @using SharedLibrary
<h1>Registration Form</h1>
@if (!registrationComplete) {
<form>
<div class="form-group">
<TextInput Model="model" FieldName="FirstName" DisplayName="First Name" /> </div>
<div class="form-group">
<TextInput Model="model" FieldName="LastName" DisplayName="Last Name" />
</div>
<div class="form-group">
<TextInput Model="model" FieldName="Email" DisplayName="Email" /> </div>
<div class="form-group">
<TextInput Model="model" FieldName="Phone" DisplayName="Phone" />
</div>
<button type="button" class="btn btn-primary" onclick="@Register" disabled="@model.HasErrors()">Register</button>
</form> }
else {
<h2>Registration Complete!</h2> }
@functions {
bool registrationComplete = false; RegistrationData model { get; set; }
protected override void OnInit() {
base.OnInit();
model = new RegistrationData() { FirstName =
"test", LastName = "test", Email = "test@test.com", Phone = "1234567890" }; model.ModelChanged += ModelChanged;
model.CheckRules();
}
private void ModelChanged(object sender, EventArgs e) {
base.StateHasChanged(); }
async Task Register() {
await Http.PostJsonAsync<RegistrationData>( "https://localhost:44332/api/Registration", model);
registrationComplete = true; }
}
@using SharedLibrary
<label>@DisplayName</label>
<input type="text" class="form-control" placeholder="@DisplayName"
oninput="@(e => OnFieldChanged(e.Value))"
value="@Model.GetValue(FieldName)" />
<small class="form-text" style="color:darkred;">@Model.Errors(FieldName)
</small> @functions {
[Parameter]
ModelBase Model { get; set; }
[Parameter]
String FieldName { get; set; }
[Parameter]
String DisplayName { get; set; }
public void OnFieldChanged(object value) {
Model.SetValue(FieldName, value); }
}
instead of Blazor in the New ASP.NET Core Web Application dialog box shown in Figure 1.
Once the new API project is created, I add a reference to the shared project, just as I did in the Blazor client application (see Figure 5). Next, I add a new controller to the API project. The new control- ler will accept the RegistrationData call from the Blazor client, as shown in Figure 9. The registration controller runs on the server and is typical of a back-end API server. The difference here is that it now runs the same validation rules that run on the client.
The registration controller has a single POST method that accepts the RegistrationData as its value. It calls the HasErrors method, which validates all the rules and returns a Boolean. If there are errors, the controller returns a BadRequest response; otherwise, it returns a success response. I’ve intentionally left out the code that would save the registration data to a database so I msdnmagazine.com
can focus on the validation scenario. The shared validation logic now runs on the client and server.
The Big Picture
This simple example of sharing validation logic in the browser and the back end barely scratches the surface of what’s possible in a full- stack C# environment. The magic of Blazor is that it allows the army of existing C# developers to build powerful, modern and responsive single-page applications with a minimal ramp-up period. It allows businesses to reuse and repackage existing code so it can run right in the browser. The ability to share C# code among browser, desktop, server, cloud and mobile platforms will greatly increase developer productivity. It will also allow developers to deliver more features and more business value to customers faster. n
Jonathan Miller is a senior architect. He’s been developing products on the Microsoft stack for a decade and programming on .NET since its inception. Miller is a full- stack product developer with expertise in front-end technologies (Windows Forms, Windows Presentation Foundation, Silverlight, ASP.NET, Angular/Bootstrap), middleware (Windows services, Web API), and back ends (SQL server, Azure).
Figure 9 The Registration Controller
[Route("api/Registration")]
[ApiController]
public class RegistrationController : ControllerBase {
[HttpPost]
public IActionResult Post([FromBody] RegistrationData value) {
if (value.HasErrors()) {
return BadRequest(); }
// TODO: Save data to database
return Created("api/registration", value); }
}
thanks to the following technical expert for reviewing this article: Dino Esposito
March 2019 19


































































































   23   24   25   26   27