Jesse Liberty - Silverlight Geek: Recent Episodes

None

More Signal - Less Noise

View Details

A dive into an amazing program for developers: NDepend

View Details

Scott Hunter (VP Microsoft) joins Yet Another Podcast’s reboot to talk about Aspire, Azure and much more. Do not miss this episode… Aspire will blow you away!

Links to follow.



View Details

In the previous post, I introduced Swagger and showed how to set up your project for Swagger. In this post I will show how to add Swagger comments to annotate your program.

In earlier posts we looked at the database of cars and the Get method that retrieves the entire list. That can be quite a lot of data going over the wire. What we want instead is to send pages. I’ll show that briefly and then we’ll annotate that code.

In the CarController we’ll have a Get method that takes three parameters: showDeleted, pageNumber and pageSize. The first we’ve seen before, it determines whether the list returned to the caller will include our deleted records. The second, pageNumber, will designate which page of data we want to return (zero based). The third parameter, pageSize, will designate how many records to return per page.

Thus, if we were to write

Get(false,3,4) we would expect to get back records 17, 18, 19 and 20, because page 0 would have records 1-4, page 1 would have 5-8, etc.

Here is the compete endpoint that will directly call our repository (we won’t bother with a service for this example).

public async Task<IEnumerable<Car>> Get([FromRoute] bool showDeleted, int pageNumber, int pageSize ){ return await _carRepository.Get(showDeleted, pageNumber, pageSize);} When the repository is called, the parameters are passed in, and it does its magic. For now, however, we are only concerned with documenting this method. We do that with XML comments, designated by three forward slash marks (///).

First, we will document the purpose of the endpoint; that is, what it does. We do that in the summary

/// <summary>/// Get all the cars in the Database /// </summary> Next, we want to document the parameters

/// <param name="returnDeletedRecords">If true, the method will return all the records,/// including the ones that have been deleted</param>/// <param name="pageOffset">which page to display</param>/// <param name="pageSize">how many records to display per page</param> Finally, I’m going to document the possible response codes. Note, these are, by no means, all that you can document, but they’ll give us a good idea of how it is done

/// <response code="200">Cars returned</response>/// <response code="404">Specified Car not found</response>/// <response code="500">An Internal Server Error prevented the request from being executed.</response> When an error is encountered and we return one of these codes, the text we’ve specified goes along for the ride, which is enormously helpful to the calling client.

At the top of the swagger page is our summary

At each parameter is our designated text

Finally, each of the error codes is documented

It is a best practice to document all of the endpoints. Many developers go further, and document all of the methods in both the service and the repository; that is a decision to be made by the team. Since the endpoint is the only thing visible to the client, it has the greatest claim on your time and effort. Remember, “comments rust,” and that is as true for Swagger comments as any other.

View Details

This is part 6 in a series about building APIs in .NET using C#. The previous (part 5) entry is here, and the series starts here.

As you know, an API sits between a client and the back end. It is imperative for the client programmer to know not only what an API does, but what the URL is, what verbs it supports and what parameters are available.

Fortunately, there is an open standard and free server: Open API and Swashbuckle. You install these once for each project and then you can just use them, as we’ll see.

This post will show you how to install them, using Visual Studio. You’ll obtain the bits you need using NuGet. Start by installing Swashbuckle.AspNetCore.

Go to your project’s properties and choose Application and Console Application. Then choose Output under Build and scroll down to where you can check “Generate a file containing API documentation”

Open Program.cs and add the Swagger generator to the services collection:

builder.Services.AddSwaggerGen( x => { x.SwaggerDoc( "v1", new OpenApiInfo { Title = $"{Assembly.GetExecutingAssembly().GetName().Name}", Version = "Version 1", Description = "Create documentation for myApp", Contact = new OpenApiContact { Name = "Jesse Liberty", Email = "yourName@gmail.com", Url = new Uri("https://jesseliberty.com") } }); var xmlFilename = System.IO.Path.Combine(System.AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"); c.IncludeXmlComments(xmlFilename);});That's it, you are now ready to create Swagger documentation. We'll review how to do so in the next installment.

View Details

An experiment in supplementing the API material with video. This will be rough at first…

View Details

In the previous posting we saw how to create an API to get all the cars in our database. In this posting we’ll look at the remaining CRUD (Create Review Update Delete) operations.

As you may remember, we created a controller named CarController. ASP.NET will strip off the word Controller, leaving us with Car, which we will use to access the endpoints of our API.

An endpoint is just a URL that takes us to the operation we want.

We looked at GetAll, let’s take a look at Get. In this case, we have an id for the car we want, but we want all the details of that car. Simple!

First we need a method in our controller:

[HttpGet**("{id}")]**public async Task<ActionResult<Car>> Get(int id){ var car = await \_carRepository.Get(id); if (car == null) { return NotFound(); } return car;} Notice that next to the HttpGet attribute we indicate that the endpoint will take the id of the car we want

[HttpGet("{id}")] This means we need to modify the URL to access the endpoint by adding the actual id of the desired record.

The first thing we do is call the repository, passing in the id.

public async Task<Car?> Get(int id){ var query = "select * from car where id=@id"; using var db = databaseConnectionFactory.GetConnection(); return await db.QuerySingleOrDefaultAsync<Car>(query, new {id});} In the Get method of the repo we create our query, get our connection and execute the query returning the value we retrieved (if any). This is very close to what we did previously.

Back in the controller, we check to ensure that we received a Car. If not, we return NotFound which is a shorthand way of returning a 404 message. Otherwise we return the Car as a Json object. You can see this in Postman:

We’ll issue a Get command passing in the URL, ending with the id of the car we want (in this case 4)

Notice that we get back a 200, indicating success. In the body of the returned Json we get back all the details of the Car. (If you decide to use DTOs you can get whatever subset of the information makes sense):

{ “id”: 4, “name”: “subaru impreza”, “mpg”: “16”, “cylinders”: “8”, “displacement”: “304”, “horsepower”: “150”, “weight”: “3433”, “acceleration”: “12”, “model_year”: “22”, “origin”: “usa”, “is_deleted”: “0”}PostAdding a Car to the database is quite similar. We need a method in the controller and one in the repo. Here is the controller method:

[HttpPost]public async Task<ActionResult<Car>> Post([FromBody] Car car){ try { car = await **\_carService.Insert(car)**; } catch (Exception e) { return BadRequest(e); } return CreatedAtAction(nameof(Get), new { id = car.Id }, car);} Look at the attribute in the parameter ([FromBody]. This indicates to the API that the data needed to insert this Car will be in the body of the call. The alternative is FromQuery. You can, in fact, use both in one call.

Note: CreatedAction causes a return code of 201, which is what we want. Here’s the body we’ll insert:

{ “name”: “chevrolet chevelle malibu”, “mpg”: “18”, “cylinders”: “8”, “displacement”: “307”, “horsepower”: “130”, “weight”: “3504”, “acceleration”: “12”, “model_year”: “70”, “origin”: “usa”, “is_deleted”: “0” }When we click Send this data is sent to the API which returns 201 (created) and in the body of the returned data we see the new id assigned to this car

{ “id”: 409, “name”: “chevrolet chevelle malibu”, “mpg”: “18”, “cylinders”: “8”, “displacement”: “307”, “horsepower”: “130”, “weight”: “3504”, “acceleration”: “12”, “model_year”: “70”, “origin”: “usa”, “is_deleted”: “0”}Service ClassNotice that this time, instead of calling the Repo directly, the method in the controller calls into a service class. A service class is a great way to get the logic out of the controller, where it does not belong, without putting it into the repo, where it also does not belong.

Here’s the top of the CarService

public class CarService : ICarService{ private readonly ICarRepository \_carRepository; public CarService(ICarRepository carRepository) { \_carRepository = carRepository; } public async Task<Car> Insert(Car car) { var newId = await \_carRepository.UpsertAsync(car); if (newId > 0) { car.Id = newId; } else { throw new Exception("Failed to insert car"); } return car; } All the logic associated with this insert (e.g., making sure we get back a legitimate id from the repository, etc.) is encapsulated in the service.

This leaves the repository free to just talk to the database,

public async Task<int> UpsertAsync(Car car){using var db = databaseConnectionFactory.GetConnection();var sql = @"DECLARE @InsertedRows AS TABLE (Id int);MERGE INTO Car AS targetUSING (SELECT @Id AS Id, @Name AS Name, @Model\_Year AS Model\_Year, @Is\_Deleted AS Is\_Deleted, @Origin AS origin ) AS source ON target.Id = source.IdWHEN MATCHED THEN UPDATE SET Name = source.Name, Model\_Year = source.Model\_Year, Is\_Deleted = source.Is\_Deleted,Origin = source.OriginWHEN NOT MATCHED THENINSERT (Name, Model\_Year, Is\_Deleted, Origin)VALUES (source.Name, source.Model\_Year, source.Is\_Deleted, source.Origin)OUTPUT inserted.Id INTO @InsertedRows;SELECT Id FROM @InsertedRows;";var newId = await db.QuerySingleOrDefaultAsync<int>(sql, car);return newId == 0 ? car.Id : newId;} Rather than having an insert and an update method, we combine that logic into this upsert method. This is a common idiom for database manipulation.

Note: to make this work, be sure to fill in all the fields for a car (or at least as many as you want to have in the Database.

DeleteAs noted earlier, we will implement a soft delete; that is, rather than actually removing the data from the database, we’ll just set the is_deleted column to true. This allows us to reverse the action, and make the row not-deleted by simply changing that value to false.

[HttpDelete(“{id}”)]
public async Task Delete(int id)
{
try
{
await _carService.Delete(id);
}
catch (Exception e)
{
return BadRequest(e);
}
return NoContent();
}

As you would expect, the endpoint takes an id (the id of the car we want to delete). The controller then hands that off to the service, which calls the repository which, in turn, marks that id as deleted:

public async Task<int> DeleteAsync(int id){ using var db = databaseConnectionFactory.GetConnection(); var query = "UPDATE car SET Is\_Deleted = 1 WHERE Id = @Id"; return await db.ExecuteAsync(query, new { Id = id });} If you are comfortable with SQL none of this will be very surprising. The key walkaway is:

SummaryIn this post we saw that endpoints are just URLs with (potentially) data in the body of the request. The controller handles the URL and in our case passes the id or other data to the service. The service handles the (business) logic and then delegates talking to the database to the repository.

BookThis posting is excerpted from my forthcoming book Building APIs with .NET and C# to be released next year by Packt.

View Details

Super excited and proud to have Mads (lead designer of C#) back to talk about C# 12

View Details

We are, finally, ready to create our ASP.NET Core application that will host our traditional and our minimal APIs.

Please note that WordPress seems to be broken and so the layout will be imperfect.

To get started, open Visual Studio 2022 and make sure you are fully up to date. Click on Create A New Project and select ASP.NET Core Web App, making sure that C# is the selected language

Give your project a name and a location

Choose .NET 7 as your Framework with no authentication and click Create.

If you’ve been following along with this tutorial already, you can steal from your earlier project. Otherwise, just type in the code.

Let’s start in appsettings.json where we will add the connection string to connect us to the database we created last time

ControllersKey to creating your API is to create controllers. A controller is the class that holds the start of the logic that your API will use. This is much easier to demonstrate than to explain. Start by creating a folder named Controllers

Right click on your Controllers folder and create a class named CarController. For now, all our APIs will originate here. Let’s set up the top of the file by declaring a logger (supplied by Microsoft in the Microsoft.AppNetCore.MVC namespace) and an instance of our CarRepository

RESTWe’ll be using REST for our APIs. There is much that you can know about REST, but for our purposes all we need to know is that we’ll be using the standard HTTP keywords to Post (Create), Get (Read), Put (Update) and Delete (Delete).

Starting DataTo have data to work with, I downloaded the Car Information Dataset from Kagel (Please read their licensing agreement before using this data elsewhere). I modified the CSV file to add an id column and an is_deleted column.

I then imported this data into a table, following the directions in this excellent tutorial. Finally, I dropped the id column and added it back as the identity column.

alter table caradd car_id_new int identity(1,1)goalter table car drop column idgoexec sp_rename 'car_id_new', 'id'go At this point, I have a table with all the columns from the imported data, as well as an identity column.

Go to your car class (that we created in part 3) and modify it as follows (to match the incoming data):

public class Car{ public int id { get; set; } public string name { get; set; } = null!; public string mpg { get; set; } = null!; public string cylinders { get; set; } = null!; public string displacement { get; set; } = null!; public string horsepower { get; set; } = null!; public string weight { get; set; } = null!; public string acceleration { get; set; } = null!; public string model_year { get; set; } = null!; public string origin { get; set; } = null!; public string? is_deleted { get; set;}} Note that for now we are keeping things very simple. We will not declare DTOs, and so we will not deal with mapping. We’ll save that for a later blog post.

Creating Our First APIWe are ready to create our first API. Its job will be to get all the cars in the database. We’ll do this by creating the API in a controller class and then invoking a method in our Car repository.

Create a Controllers folder, if you have not already, and in that folder create a CarController class. Add the following code to the top of the class:

public class CarController : ControllerBase { private readonly ILogger<CarController> _logger; readonly CarRepository carRepository; public CarController(ILogger<CarController> logger, CarRepository carRepository) { _logger = logger; this.carRepository = carRepository; }

ControllerBase and ILogger are provided by Microsoft (thanks Satya!). Now, let’s create our API, which is a method decorated with the [HttpGet] attribute

Deceptively simple. This method returns a list of Car objects by calling GetAll on the carRepository. Let’s go look at that method:

(If you don’t already have a folder Repositories, please create one and add the class CarRepository). Here’s the top of the class:

You will need a using statement for Dapper.

We are now ready to implement the GetAll method:

This method will return the list of Car objects that we need, and defaults to not returning deleted records. We begin by creating a SqlBuilder – an object provided by Dapper. We then create our template, ending it with the syntax /where/ — this too is for Dapper and allows us to dynamically create our where clause.

You see this in the if statement; we’ll only add the where statement that restricts the results to non-deleted records if the parameter (returnDeletedRecords) is false.

Next we obtain a connection to the DataBase from our databaseConnectionFactory and finally we use that connection to call QueryAsync, identifying the type (Car) and passing in the SQL statement and the parameters to that statement, if any. In this simplified case we do not have any parameters, but we’ll see how to use them in a later blog post.

Testing with PostmanWhen you run your application Swagger will come up. Minimize that and open Postman, which is much more powerful and easier to work with (especially once we add authorization). Create a folder named Cars (of course, you can actually name it anything you like) and next to that folder click on the three dots that appear when you click on the name of the folder.

Choose Add Request, and rename your new request GetCars. Go to the right hand pane, and make sure the drop down is set to Get. Next to the drop down enter

https://localhost:7025/car

Be sure to substitute the port number (bold) to the one used by Swagger.

That’s all you have to do. Click Send in the upper right hand corner and your API will be called (don’t be afraid to set break points to prove this to yourself) which will call the method in the repository, which will in turn fetch your data from the database and it will all be returned to Postman…

Congratulations! You have your first working API to your back-end data stored in SQL Server!

In this coming blog posts we’ll add the remaining CRUD APIs, examine using services and DTOs and take a look at minimal APIs.


Rodrigo Juarez is a full-stack developer who has specialized in Xamarin in recent years and is now focusing on MAUI. He is also a book author. With over 25 years of experience, Rodrigo has contributed to a diverse array of projects, developing applications for web, desktop, and mobile platforms. Specialized in Microsoft technologies, he has expertise across various sectors, including management, services, insurance, pharmacy, and banking. Rodrigo Juarez can be reached at info@rodrigojuarez.com

View Details

In a previous post I said I was still looking for the right file comparison tool. I may have found it! I returned to ExamDiff Pro and voilà! the perfect combination of power and ease of use. I integrated it … Continue reading →

View Details

The code for this blog post is available here:git clone https://github.com/JesseLiberty/Cars.git In part 2 of this series we created a simple database. In this part we’ll look at how to perform CRUD operations against that DataBase in anticipation of creating … Continue reading →

View Details

I’m interviewed by my old friend J. Tower (of Trailhead Technology Partners) on his Blue Blazes YouTube program, talking about Unit Testing. Lots of fun discussing an important topic. Tune in here.

View Details

As noted in part 1 of this series, I will be building an application specifically to explore building APIs. To get started, I’ll want to build a back-end database. The application we’ll be simulating is a car dealership. Customers can … Continue reading →

View Details

While I’m still happily ensconced at CNH Industrial, I have changed my job. I’m no longer writing mobile applications (for the first time in about 7 years!) but rather am writing APIs using ASP.NET Core and C#. -The plan is … Continue reading →

View Details

Pleased and proud to have been awarded my 11th MVP award from Microsoft.

View Details

I had the pleasure of turning the tables and being interviewed on WebRush with Jon Papa et al https://www.webrush.io/episodes/episode-240-theres-something-net-maui-with-jesse-liberty

View Details

https://www.packtpub.com/article-hub/writing-a-customized-cover-letter-for-a-specific-job-in-minutes-using-chatgpt

View Details

Today I spoke with Valerio De Sanctis, author of Building Web APIs with ASP.NET Core.

View Details

Just posted on Packt: Writing Unit Tests with ChatGPT

View Details

I wrote this blog post in September of last year, and looking at it today I realized that I don’t use a couple of these anymore: 1) Resharper: the overhead was borderline too much and most of the refactoring power … Continue reading →

View Details

I have changed jobs within my current company (CNH Industrial). I will no longer be doing mobile programming (for the first time in six years) and will be building APIs and back-end code!

I think you can expect fewer articles on mobile/ .NET MAUI programming, and more on ASP.NET Core, Azure Functions, APIs, Architecture, Microservices, etc.

I’m also scoping out writing a book which may include the following topics:

  • Creating the back end (SQL Server & SQL)
  • Azure (Docker, Azure Functions) & Localhost
  • Designing and creating the Minimal API (architecture, end points, etc)
  • Creating the front end ( .NET MAUI )

The book would assume only that you have some C# experience. We’d also cover tools, setup, and best practices. All of this would be in the context of a non-trivial application.

I’d be very interested in hearing your thoughts on such a book. Please feel free to send me email at jesseliberty@gmail.com.

View Details

I’ve posted my .NET MAUI For Xamarin.Forms Programmers and Advanced .NET MAUI videos on YouTube.

View Details

I’ll be presenting at Boston Code Camp on

  • .NET MAUI For Xamarin.Forms Developers
  • Advanced .NET MAUI

This is a free, one-day event on Saturday, April 29, in Burlington, MA.

View Details

With the release of my newest book, .NET MAUI For C# Developers, I’m pleased to start a new .NET MAUI series on advanced topics. If you are just starting out, however, you may want to take a look at my previous 15 part series in which I learn .NET MAUI or my second series that uses the app (Forget Me Not) that we’ll be using here.

Managing Visual State

Every VisualElement has a Visual State. For example, does the VisualElement have focus? Is it selected? Xaml allows you to change the presentation of that VisualElement (e.g., a button) based on that state.

The object that sets visual properties on a VisualElement based on its state is the Visual State Manager. The Visual State Manager selects from among a set of VisualStates and displays the view according to styles that you create.

Defining the common visual states

.NET MAUI defines a set of common visual states:

  • Normal
  • Disabled
  • Has focus
  • Is selected
  • Mouse over (for Windows and MacOs)

.NET MAUI also allows you to define your own visual states.

Button VisualState example

When you first come to the Login page in Forget Me Not, the Submit button is disabled. Once you fill in the two fields of Your Email and Password, the button should turn light green. If you tab to the button it should signify that it has the focus by turning fully green. You can do all this declarative with Visual States.

Visual State and Styles

You can set the visual state on an individual button, or, as we will do here, you can put the visual state XAML into a style and apply it to all the buttons. Here is the complete Style for buttons:

```

``` We start by declaring a normal Style, in this case implicit for every button. You may have one or more groups of visual states (we have one). The first group (and in this case the only one) is the CommonStates

We declare each VisualState in turn (here we’re starting with Normal). For each state, we can declare a set of Setters. Our first (and in this case only) Setter sets the BackgroundColor property

We then go on to set the Setters for all the other states. Notice that we did not set the Setter for PointerOver, which means that, on Windows and macOS, if you hover the mouse over the button there will be no change.

.NET MAUI defines specialized visual states for controls. For example, Button adds the Pressed state while CheckBox adds the IsChecked state and CollectionViews adds Selected.

The .NET MAUI community toolkit provides further help for managing the appearance and behavior of your app with a large collection of Behaviors.

View Details

I presented on .NET MAUI For Xamarin.Forms Programmers and Advanced .NET MAUI in Prague last week, and it was great (Prague, not the presentations).

All went well, but touring Prague was terrific. The city was founded in the 10th century and the architecture reflects a millennium of development. The city is immaculate and while only about ⅓ of the people I tried to talk to spoke English, many of those who did spoke it perfectly. The mass transit system is fantastic and the sites are literally awesome.

I’m very grateful to have had this opportunity.

Speaking at .NET MAUI Update

View Details

Due March 31, from Packt

Very excited about this book. Feedback is very welcome at jesseliberty@gmail.com.

Thanks!

View Details

Excited to have Patrick Smacchia of NDepend on to discuss this amazing tool for creating world-class .NET applications.

https://www.ndepend.com/docs/ndepend-use-cases
https://www.ndepend.com/docs/videos
https://www.ndepend.com/download
https://www.ndepend.com/purchase

View Details

My latest book: Learn .NET MAUI — An Essential Guide for C# Developers will be released mid-April 2023.

Given the existence and likely enhancements to the .NET MAUI Community Markup Toolkit for C#, and that many people will come to MAUI with little or no XAML (or will know XAML and hate it), I was tempted to show all of the code in C#.

But the truth is that most extant User Interface code is in XAML and anything you can do in C# you can do in XAML. So, at least for the first edition, the majority of the code is in XAML with one full view recreation in C#

Here is the Table of Contents:

  1. Assembling your tools and creating your first app
  2. What we will build: Forget Me Not
  3. XAML and C#
  4. MVVM And Controls
  5. Advanced Controls
  6. Layout
  7. Understanding Navigation
  8. Storing and retrieving data
  9. Unit Tests
  10. Consuming a REST API
  11. Advanced Topics

I’m eager to hear your ideas about this decision.

Thanks.

View Details

Triggers in .NET MAUI are not that different from triggers in Xamarin.Forms, but since this is not a frequently used feature, I thought I’d provide a quick deep-dive into their usage.

Triggers allow you to declare, in your XAML, how a control should appear based on data changes. You can combine state triggers with Visual State, a topic I’ll cover in a subsequent blog post.

This is the first of a series of short pieces based on material in my forthcoming book .NET MAUI For C# Developers (Packt* Publishing) which we are targeting for publication in early April.

For example, suppose we have a create account page, and we want the create button to be disabled if the user has not filled in a password. You can certainly do this in code (and .NET MAUI Community Toolkit will make this very easy with behaviors), but you can also do it declaratively in XAML using a DataTrigger.

<Button Command="{Binding DoCreateAccountCommand}" Grid.Column="1" Grid.Row="2" Style="{StaticResource LoginButton}" Text="Create Account"> <Button.Triggers> <DataTrigger Binding="{Binding Source={x:Reference passwordEntry}, Path=Text.Length}" TargetType="Button" Value="0"> <Setter Property="IsEnabled" Value="False" /> </DataTrigger> </Button.Triggers></Button> Notice that the Button has a collection of Triggers. The type we want is a DataTrigger (as opposed, for example, to an event trigger). The trigger binds to the passwordEntry field’s Text.Length and looks for the value 0. If that is true, then the property IsEnabled is set to false. Once the Text.Length is not zero, the property is set to true.

That’s all it takes. You can see that triggers are often quite simple, but for some reason considered “advanced” and thus not used often; which is a shame because they can greatly simplify your code and make the logic easier to understand.

Note that the field you are checking (in this case password) must have its Text initialized to “” (in the ViewModel or code-behind, but of course the ViewModel is the right place). Otherwise it will be null, and the trigger may not act as expected.

In my next tutorial, I’ll tackle the more interesting and complex subject of Visual States.

———–

*This being my second book from Packt, I decided to ask how it is pronounced. Turns out it is one syllable, sounding more like packed than like packet. If you want to get it really right, say the word pack and sneak in a t sound at the end. (Just thought you’d want to know.)

View Details

I’m speaking about .NET MAUI in Prague on March 23 and 24. If you’re in the neighborhood…

https://maui.updatedays.cz/speakers/en?langChange=en

https://maui.updatedays.cz/#about/en

View Details

This video, from evolve 2016 covers Test Driven Development in Xamarin.Forms.

View Details

Picking the best blog posts is pretty painless as I’m the only one posting, so there is no one to insult, but picking the best podcasts risks slighting some of the amazing people who came on Yet Another Podcast.

5 Best Blog PostsThe best blog posts are those that either alone or in a series teach something valuable and current. For 2022, these stand out:

  • Forget Me Not – a non-trivial application built in .NET MAUI (series, part 1)
  • A Dozen Utilities for programmers
  • Learning .NET MAUI – part 1 of 15
  • Advanced Data Binding part 1 of 4
  • The Miracle of IQueryAttributable – honorable mention from 12/21

5 Best PodcastsWe had 11 fantastic podcasts in 2022, how do I pick the top five? The only reasonable approach is by their popularity. In date order, they are:

  • James Montemagno on .NET MAUI
  • Uncle Bob Martin on Agile Programming
  • C# 11 with Mads Torgerson and Dustin Campbell (parts 1 and 2)
  • Bill Wagner on C# 11 Documentation
  • David Ortinau on .NET MAUI

It was quite a year for me as well. I started my newest book .NET MAUI for C# Developers (Packt) to be released at the end of the summer (or, I hope, earlier!)

I also moved from Twitter to Mastodon, which was a big and terrific change. I opened my tiny book store, mostly to keep track of my favorite books, and I opened a new web site for my novel in search of an agent.

Along the way I shed 100 pounds, trained my dog not to pull and, oh yeah, worked full time writing mobile applications for CNH Industrial.

Welcome to what someone on Mastodon called 2020 v3. Let’s hope it is a good and safe year.

Simon (2 year old pointer-mix rescue)

View Details

David Ortinau, Program Manager .NET and voice of .NET MAUI discusses MAUI as a platform, Blazor Hybrid, Community Toolkits, as well as what’s on the road map for .NET MAUI.

View Details

Bill Wagner creates C# learning and reference materials for https://learn.microsoft.com. He works with colleagues on the C# team, related content teams, and customers to provide resources for everyone that wants to learn more about C#. He’s also a member of the ECMA C# Standardization committee, working to update the C# standard.

I asked Bill, to come talk about C# 11 and to do so from the perspective of a programmer who stopped following the newest additions to C# as of C# 7 or 8 or so. That is, how do we catch up if we’ve fallen behind on the latest features?

This is part one, in which we discuss, among other things, Pattern Matching.

Here is a link to the tutorial Bill describes.

And here is a link to the top of the C# documentation.

View Details

Mark Price joined me to discuss C# 11 and his books, C# 11 and .NET 7 and Apps and Services with .NET 7. Both books are available in my tiny book store, listed under Favorite books for programmers.

Note: A gremlin got into the original audio; fixed now. I apologize for the inconvenience.

View Details

Mark Price, author of C# 11 and .NET 7 and Apps and Services with .NET 7 joins me to talk about C# 11

View Details

Picking up where we left off, I want to add unit tests to my program. Now, I know, I should have been using unit tests all along. I have no excuse and hang my head in shame. To get started, … Continue reading →

View Details

I have posted the (incomplete) code at https://github.com/jesseliberty/GraniteStateForgetMeNot and a video of much of the material captured in this series is now on YouTube

View Details

I’ve started a newsletter where I am publishing the first chapter of my novel, one sentence per day. This is not a techie novel, but check it out anyway. More at my fiction web site.

View Details

Part 2 of my discussion with Mads and Dustin on what’s new in C# 11 with a focus on when application developers will use the new features.

View Details

I’ve started a tiny bookstore of my favorite books.

View Details

Joined today by Mads and Dustin to discuss what’s new in C# 11 with a focus on when application developers will use the new features.

View Details

Building on the previous postings, today I want to discuss the magic of Dependency Injection (DI) Dependency Injection makes for cleaner and more testable code. We’ll get into testing and Mocks in a later blog post, but using DI allows … Continue reading →

View Details

Building on the previous blog posts, here I’d like to illustrate how you can pass complex data from one page’s view model to another’s. Let’s assume we’ve tapped on the Buddies Icon on the tab bar and were taken to … Continue reading →

View Details

This is part 4 in an ongoing series in which I will build and dissect a non-trivial app. For details, please see the first in this series. Part 3 ended with a teaser about the Preferences Page. As you’ll remember, … Continue reading →

View Details

In the previous postings we looked at creating the basic app and adding a single, simple page. This post will really begin to get into it. We’re going to have a number of pages A page for you to enter … Continue reading →

View Details

In Part 1 we created the skeleton of Forget Me Not (and explained what it is). Here in Part 2 we’ll add an about page. This is so easy that this will be a short post. Create the page Creating … Continue reading →

View Details

My buddy in Argentina, Roberto Juarez, and I have set out to create a real-world, non-trivial program using .NET MAUI. This is a learning exercise and I’d like to invite you to join us. We anticipate that (eventually) this will … Continue reading →

View Details

Lists are always subjective, but it is helpful, I think, to exchange favorites now and again. Feel free to add yours to the comments. Here’s my list in no particular order Visual Studio 2022 – goes without saying that this … Continue reading →

View Details

So let’s talk about something we don’t talk about. Many of us (programmers) are significantly overweight. You see it at every conference. I’ve heard 3xl referred to as a programmer’s medium. This year I decided to do something about it … Continue reading →

View Details

As an experienced XF programmer, you know that there are times you need a relational database, and SQLite has been the mobile db of choice for a very long time. In this post we’ll create a table in SQLite and … Continue reading →

View Details

Very excited to have Maddy back on Yet Another Podcast. Today we go beyond the basics to intermediate and advanced topics in .NET MAUI. Or wherever you get your podcasts.

View Details

Have I thanked James Montemagno yet? His 4 hour training video is the foundation of this series of posts (with his permission). Part 0 which kicks off this series is here. Platform Specific Services Now that we’ve covered platform services … Continue reading →

View Details

In this post we’ll do three things: Add a clear button to clear out the list of zip codes Add the Connected service to make sure we have internet connection before trying to get the zip codes Add the IMap … Continue reading →

View Details

We left off displaying the zip codes and going to the details, but not displaying the selected zip code. Let’s fix that and clean some things up. Choosing from the list and displaying the details In the previous version we … Continue reading →

View Details

This one should be short. We’re going to take a look at passing values when navigating. Passing in values requires that you pass a Dictionary, where the key is an arbitrary string and the object is the value you are … Continue reading →

View Details

In the ugly old days, if you had data that you wanted to display you would put the data into a variable and then write some code to copy that data to a control on your page. If the data … Continue reading →

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

En Español There are times when you need to bind to a source but the source is not in the right format or otherwise needs to be manipulated. For example, suppose, as we’ll show below, that you have a text … Continue reading →

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

This is the first in a series on advanced data binding. In this series we will look at: using value converters with binding, relative binding, the {Binding .} and {Binding self} constructs, and more. We hope to release one of … Continue reading →

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

This knocked me out. Let’s say you have a value in one view model, and when you navigate to another page you want that value in the new page’s view model. Enter IQueryAttributable. (tough to say, even tougher to spell) … Continue reading →

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

Lance McCarthy talking about Maui, VS2022, community contributions and much more. Referenced sites and source: Twitter – https://twitter.com/lancewmccarthy Blog – https://dvlup.com/ Resources (see descriptions below) 1 https://github.com/LanceMcCarthy/CommonHelpers...

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

Mads Kristensen talks about all the goodness in Visual Studio 2022

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

Here are 12 utilities I use every day. They are in no particular order. I spend most of my day programming in Visual Studio 2019. #0 – Resharper. I’m so ambivalent about this add on for Visual Studio. On the … Continue reading →

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

Presentation to the St. Pete’s user group

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com

View Details

Mads comes back on show 200 (!) to talk about all things C# 10, which will be released November 2021.

For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com