Jesse Liberty: Recent Episodes

None

Espresso => Code

View Details

Maddy is the program manager/ owner of Microsoft’s Aspire. This is new, exciting and powerful.

More about Aspire



View Details

This from 2009:

Yudkowsky poses the following canonical problem:

1% of women at age forty who participate in routine screening have breast cancer. 80% of women with breast cancer will get positive mammographies. 9.6% of women without breast cancer will also get positive mammographies.

A woman in this age group had a positive mammography in a routine screening. What is the probability that she actually has breast cancer?

The frightening thing is that only 15% of doctors get this right. And they’re off by a lot. That is, the average answer is in the range of 80% while the correct answer is 7.8%. Apparently, there is something about the way we think about the problem that makes 7.8% hard to accept, and Yudkowsky does a great job of walking you through the logic in painfully small steps.

Let’s try something similar here…

What Do We Know & What Does It Imply?
We have three pieces of information:

1% of sample are TRUE (that is, they have cancer)

80% of sample who are TRUE will test TRUE

9.6% of sample who are FALSE will test TRUE.

On the face of it, we should guess that the percentage of women who test TRUE who actually are TRUE (test positive and actually have cancer) is pretty small based on two facts provided: the actual percentage of women from the sample who are TRUE (regardless of testing) is only 1%, and the test has a false positive for 9.6% of those tested.

So, to solve this:

1) Assume we have a sample of 1000 women (I use 1000 to reduce the amount I have to talk about fractional people, but I don’t use 10,000 as I get lost in the zeros).

2) We know that the reality is that of the 1,000 women, 10 will have cancer (1%).

990 = no cancer
10 = cancer

3) Of the 10 who have cancer, 8 will test positive
8 out 1000 women tested will test True and are True

4) Of the 990 with no cancer 9.6% will also test positive = 990 * .096 = 95.04.
95.04 women out of 1,000 will test True but are False.

5) The total number testing true is 8 + 95.04 = 103.04.
Of these, 8 actually have Cancer.

6) So the value for tests positive (103.04) versus is positive (8) is 8/103.4 or 0.773 or 7.8%

View Details

Microsoft has a wonderful tutorial on pattern matching, in which you model a lock (to raise or lower a ship when there would otherwise be a waterfall). They model the two doors and the water level.

While their example is excellent it is long, and in this blog post I’m going to take the essence of pattern matching using their example.

We start with a state machine:

The chart indicates whether the gate should be opened or closed based on the new setting and the current status of the gate as well as the water level. We read it as follows: if the new setting is closed, it doesn’t matter what the starting state of the gate is, nor the water level, we close the gate (first three lines).

On the other hand, if the gate is closed (line 4) and we give it a new state of open and the water level is high, then we open the gate. If, on line 5, we tell it to open from a closed state, but the water level is low then we have an error (don’t open when the water is low).

Finally, if we say open and it is open and the water level is high, then we do, in fact, open.

These states can be modeled in a switch expression using pattern matching where true = open and false = closed:

HighWaterGateOpen = (open, HighWaterGateOpen, CanalLockWaterLevel) switch{(false, false, WaterLevel.High) => false,(false, false, WaterLevel.Low) => false,(false, true, WaterLevel.High) => false,(true, false, WaterLevel.High) => true,(true, false, WaterLevel.Low) => throw new InvalidOperationException("Cannot open high gate when the water is low"),(true, true, WaterLevel.High) => true, As you can see, the first three arms of this expression start false and end false, as we saw above. Next, we have the case where the new state is true, the current state is false and the Water level is high. This causes the gate to open (true).

But it gets easier. First, we need the default case. In the latest C# an underscore matches anything. So we add

_ => throw new InvalidOperationException(“Invalid internal state”),

as the default, meaning if anything else comes up, it is invalid.

Note that, as we said, the first three arms all evaluate to false. We can replace them with
(false, _, _) => false,
You read this as, if the first value is false (the new condition) then no matter what the second and third conditions are, we will evaluate to false.

Next we need to know what to do if the new state is true. This is slightly tricker as it depends on the water level:

(true, _*, WaterLevel.High) => true,* *(true, false, WaterLevel.Low) => throw new InvalidOperationException("Cannot open high gate when the water is low"),* => throw new InvalidOperationException("Invalid internal state"), Thus, if the new state is true, and the water level is high (no matter the state of the gate), then we do open the gate. If the new state is open (from on original state o closed) and the water level is low then, uh oh.

Here is the final version of the method:

// Change the upper gate.public void SetHighGate(bool open){ HighWaterGateOpen = (open, HighWaterGateOpen, CanalLockWaterLevel) switch { (false, _, _) => false, (true, _, WaterLevel.High) => true, (true, false, WaterLevel.Low) => throw new InvalidOperationException("Cannot open high gate when the water is low"), _ => throw new InvalidOperationException("Invalid internal state"), };} All of this is simpler, cleaner and thus easier to understand and maintain than a series of if statements or even a set of switch statements.

View Details

I admit it, I’ve struggled with pattern matching. In the next few blog posts I’ll explore this magic, starting today with switch expressions (not to be confused with switch statements).

The type of switch we’re familiar with is the switch statement:

namespace switchStatement;internal class Program{ static void Main(string[] args) { string day = string.Empty; day = GetDay(2); Console.WriteLine(day); } public static string GetDay(int dayNum) { string dayName; switch (dayNum) { case 0: dayName = "Sunday"; break; case 1: dayName = "Monday"; break; case 2: dayName = "Tuesday"; break; case 3: dayName = "Wednesday"; break; case 4: dayName = "Thursday"; break; case 5: dayName = "Friday"; break; case 6: dayName = "Saturday"; break; default: dayName = "Invalid day number"; break; } return dayName; }} This will return Tuesday.

A switch expression has a slightly different syntax, but more important, it matches on a pattern. I’m going to use the example from Microsoft Learning (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression) and take it apart

public static class SwitchExample{ public enum Direction { Up, Down, Right, Left } public enum Orientation { North, South, East, West } public static Orientation ToOrientation(Direction direction) => direction switch { Direction.Up => Orientation.North, Direction.Right => Orientation.East, Direction.Down => Orientation.South, Direction.Left => Orientation.West, _ => throw new ArgumentOutOfRangeException(nameof(direction), $"Not expected direction value: {direction}"), }; public static void Main() { var direction = Direction.Right; Console.WriteLine($"Map view direction is {direction}"); Console.WriteLine($"Cardinal orientation is {ToOrientation(direction)}"); }} The output of this is

Map view direction is RightCardinal orientation is East The method ToOrientation takes a Direction and calls the switch expression (notice the placement of the keyword switch).

It then sets up the Direction to Orientation pattern matching. For example, it establishes that if the passed in parameter is Direction.Up (that is, the Up enumerated constant) then it is to be converted to Orientation.North, and so forth. (The underscore is a new way of indicating no value, or in this case, the default).

The various expressions are called “arms” and are separated by commas. Each arm contains a pattern and an expression. In the first arm, Direction.Up returns the expression Orientation.North.

It is this pattern matching that I’ll be exploring in the next few blog posts.

View Details

Until now, if you wanted to access the last item in a list you had to use a slightly cumbersome syntax. C# 13 introduces the “hat” operator (^) where ^1 is the last element in your collection, ^2 is the penultimate member, etc.

Like many things, this is best illustrated with an example. In the following code I create a simple Person class and initialize a list with three people (persons?)

internal class Program { static void Main(string[] args) { var tester = new Tester(); tester.Test(); } } public class Tester() { public void Test() { var john = new Person { Name = "John", Age = 25 }; var jane = new Person { Name = "Jane", Age = 30 }; var joe = new Person { Name = "Joe", Age = 35 }; var people = new List<Person> { john, jane, joe }; } } public class Person() { public string Name { get; set; } public int Age { get; set; } } Straight forward. Now, if I want to access the last person in this list I can write

var lastPerson = people[^1]; Console.WriteLine($"Last person is {lastPerson.Name} who is {lastPerson.Age} years old."); As you can see, this is concise and easy to understand. You read it as “lastPerson is equal to one back from the end of people.” Let’s run it:

Last person is Joe who is 35 years old. That is all there is to it. Easy to use and somewhat helpful in simplifying your code.

View Details

This short post will kick off a series covering some of the new features in C#.

One small but much requested feature is the ability to use any kind of collection for params. Previously you had to pass in an array:

public void MyMethod(int firstParam, params string[] otherParams) { foreach (var param in otherParams) { Console.WriteLine(param); } } But now you can pass in any kind of collection,

public void MyMethod(int firstParam, params List<string> otherParams) { foreach (var param in otherParams) { Console.WriteLine(param); } } This can save a great deal of fussing, converting your collection to an array and back.

Please note that this is a preview feature. Fortunately, Intellisense will convert your project for you. When you put this in you’ll get the dreaded red squiggly. Click on the light bulb and let it convert your project. Hey! Presto! it works.

We’ll look at a few bigger features in coming blog posts.

View Details

I sense that a lot of us have had trouble keeping up with the rapid growth of C# features. My guess is that most of us fell off the cliff somewhere around C# 7 (we’re up to 13/14). I have in mind to write a book that assumes you are already a C# programmer and brings you up to speed on the latest features and techniques.

Here are just a few topics I’d cover:
1. Switch Expressions
2. Pattern matching
3. Tuples
4. Records
5. Dynamic binding

I would not cover such topics as if statements, etc., nor even basic polymorphism.

The book would be as short as possible, providing hands-on examples but no fluff. Further, I wuld not show the evolution of a feature, but rather just teach the most modern version.

Would such a book be of interest to you? I’d like to get a sense of the audience before starting.

Please send me a note at jesseliberty@gmail.com

View Details

Two years ago, I made a list of my indispensable tools. Here is a quick updated version:

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

  1. Visual Studio 2022 – goes without saying that this is the world’s best IDE for .NET developers. I use it 8-12 hours a day, it just keeps getting better, especially with CoPilot.
  2. Copilot – AI done right. Integrated with Visual Studio, this add-on is the most powerful and useful tool I have. It can get in the way a little, but when it does its stuff, watch out. Point it at a class and ask for documentation and/or unit tests and watch it go! But kids, don’t try this at home — it needs adult supervision.
  3. ExamDiffPro – there are lots of comparison/merge utilities. Get a good one.
  4. Tweaks by Mads Kristensen — small but very valuable addition to VS
  5. Viasfora – I can not believe how useful this is. Matches braces by color and in any “real” application, this can save a lot of time.
  6. Evernote: I use it to log everything I do, including every fix for recurring issues. It is quick, powerful, and easy to use. Although it has limitations, overall, I’ve found it helpful and reliable.
  7. LastPass – my password manager. I’d be lost without it. (1Password may be better, our mileage may vary)
  8. Git Diff Margin – if you use Git you’ll want to Git this. See what changed in the margin
  9. DB Browser for SQLite – If you are using SQLite, this is a must-have.
  10. BlueSky – the single best social media site for .NET programmers

Note that nearly all of these are free. I do remember the days when a program like Lotus 123 cost something in the hundreds of dollars. It makes me laugh when I see people look at an app and say, “$4, naah, too expensive.”

I am not affiliated with any of these.

As I say, grab these, and if there are others that you use, please note them in the comments.

Thanks

View Details

My cache blew up my site. The good people at GoDaddy fixed me up, but I lost a good bit of the past 12 years of content (through my own stupidity). Never fear, however, all the new stuff is intact.

In addition, I took the opportunity to upgrade, so the site should be faster and backed up daily, and while I was at it, we upped the security. So, all in all, there was a silver lining.

View Details

An important part of creating APIs is interacting with data storage. While you can use any number of database programs, a common way to store simple data is in data tables. This is particularly useful when you are recording API calls as part of your telemetry.

Storage tables are not inherently relational. The goal is to keep storage tables simple. This makes them ideal for keeping lists, logging, creating progress entries, and so forth.In this demo, we’ll create a storage table that tracks exceptions thrown during execution of our program. Let’s create a console app that just throws exceptions every few seconds.

Create a new console app and name it TableStorageConsoleApp. Choose .NET 8 (or 9) and check Do not use top-level statements.

In main, create a forever loop and have it throw an exception. We want the exceptions to be thrown randomly.

I’m having trouble with WordPress layout, so please forgive the fonts in this post. I’ll sort it out ASAP.

try

{

Random rand = new Random();

var random = rand.Next(0, 10);

switch (random)

{

case 0:

throw new ArgumentException(“Argument Exception”);

case 1:

throw new ArgumentNullException(“Argument Null

Exception”);

case 2:

throw new ArgumentOutOfRangeException(“Argument Out Of

Range Exception”);

case 3:

throw new DivideByZeroException(“Divide By Zero

Exception”);

case 4:

throw new FileNotFoundException(“File Not Found

Exception”);

case 5:

throw new FormatException(“Format Exception”);

case 6:

throw new IndexOutOfRangeException(“Index Out Of Range

Exception”);

case 7:

throw new InvalidOperationException(“Invalid Operation

Exception”);

case 8:

throw new KeyNotFoundException(“Key Not Found Exception”);

case 9:

throw new NotImplementedException(“Not Implemented

Exception”);

case 10:

throw new NotSupportedException(“Not Supported

Exception”);

default:

throw new Exception(“Generic Exception – you should never

see this”);

}

}

Now we can catch each exception and put it into our table.

The key thing here is that the table has Partition keys and Row Keys. Partition keys aggregate rows, and makes retrieval much faster.

TableServiceClient is a NuGet package. We call Upsert and sleep for two seconds.

The table model itself looks like this:

public class TableModel : ITableEntity

{

required public string PartitionKey { get; set; }

required public string RowKey { get; set; }

public DateTimeOffset? Timestamp { get; set; }

public string? Message { get; set; }

public ETag ETag { get; set; } = ETag.All;

}

(Etag is used for optimist concurrency and must be in every table model.

Here is UpsertEntityAsync

public async Task UpsertEntityAsync(TableModel entity){var response = await _tableCreationTask;var table = _tableServiceClient.GetTableClient(response.Value.Name);return await table.UpsertEntityAsync(entity);}

To get started, we declare two member variables at the top of the class: private readonly TableServiceClient _tableServiceClient; private readonly Task> _tableCreationTask;Notice that the second member is of type Task. Both Response andTableItem are supplied by the Azure NuGet package. The constructor takes TableServiceClientpublic StorageTableService(TableServiceClient tableServiceClient){_tableServiceClient = tableServiceClient;_tableCreationTask = _tableServiceClient.CreateTableIfNotExistsAsync(“ExceptionsTable”);}It is here that we create the table if it doesn’t exist and name it ExceptionsTable.All the Upsert method needs to do is call tableCreationTask and wait to get back Response. With that in hand, it is ready to call GetTableClient onTableServiceClient, passing in the name of the table. Finally, we call UpsertEntityAsync on the table passing in TableModel.

Your output should be a simple table with one row for each exception thrown.The next step is to migrate this to Azure which we will do in the next blog post.

Note, this post is based on my forthcoming book Programming APIs with C# and .NET from Packt. Which will be available the end of November 2024.

View Details

jesseliberty.com just crossed 1MM views (lifetime). So pleased you’ve stuck with me. See find me in menu to continue the dialog.

View Details

End of November, 2024.

View Details

Mads Torgersen, lead designer of C# joins me to talk about what’s new in C# 13 and much more



View Details

Performance is king (well, after accuracy) in APIs. Sending a request to the Database only to discover that the request is invalid is a waste of resources. Thus, we want to validate the request as soon as it hits the endpoint.FluentValidation is a great tool for creating validators. It installs as a NuGet package. Also grab the version for ASP.Net.

To get going, add a using statement.

Using FluentValidation

Next, create a class that derives from AbstractValidator.

*public class CarNotDeletedValidator : AbstractValidator<Car>*

This example uses the Car class from my forthcoming book Creating .NET APIs with C#.

Put your validation rules in the constructor. Each rule is created by using the keyword RuleFor and a lambda expression that indicates which property you want to validate and the validation rule.

using Cars.Data.DTOs; using FluentValidation;namespace Cars.Validators{ public class CarNotDeletedValidator : AbstractValidator<CarDto> { **public CarNotDeletedValidator() { RuleFor(x => x.Is\_Deleted).Equal("0"); }** } }

The Equal operator is one of many that you can find at the FluentValidation documentation page: https://docs.fluentvalidation.net/en/latest/built-in-validators.html. We’ll test the data and then either compare it to what is valid and return an error if appropriate, or, more commonly, we’ll throw an exception if the data fails validation.

Assuming that it passes validation we can continue to the Database. If however it fails, we can return a meaningful error to the sender.

View Details

This site has been quiet for a few months while I finish up my book (.NET APIs with C#). I’m happy to reboot both the blog and Yet Another Podcast, starting soon with an interview of Mads Torgerson (lead designer of C#)!

To get things rolling, I’m going to pick up my series on creating APIs, based on my forthcoming book (scheduled to be in bookstores mid-November).

I will be speaking at Boston Code Camp this November as well. In fact, once the election is passed (I’m spending 10+ hours/week on campaigning) I expect to be putting in a lot of time on this blog.

I hope you will join me as I get back to work providing (hopefully useful) information to the community.

As always, you can reach me at jesseliberty@gmail.com

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. (This series begins here.) The code for this blog post is available here:git clone https://github.com/JesseLiberty/Cars.git Please note that WordPress seems to … Continue reading →

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

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 APIs for these operations. Dapper is a micro-ORM (Object Relational Mapper) … 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 present occasional posts 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. Finally, you can find my presentations on .NET MAUI and advanced .NET MAUI on YouTube, 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

In Stores Now!

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.

Use Cases
Videos
Download NDepend

View Details

My latest book: Learn .NET MAUI — An Essential Guide for C# Developers will be released March 31, 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.

What’s your opinion: XAML vs. Fluent C# for new MAUI programmers?

Please note that something went wrong with distributing this podcast and so I am reposting.

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.

What’s your opinion: XAML vs. Fluent C# for new MAUI programmers?

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. A gremlin got into the audio and I only just discovered it today. I was able to recover the original, and am reposting. I apologize for the inconvenience. Let’s see if I can get Apple to push this replacement out to all the podcast providers.

Both books are available in my tiny book store, listed under Favorite books for programmers.

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

Let’s take a quick look at simple navigation (in the next post we’ll look at some more you can do with navigation. As usual, we’ll start with the previous day’s code. To get started, we’ll add a button to the … Continue reading →

View Details

Once again, we’ll pick up where we left off. But today we’re in for some big changes. Let’s add an IsBusy property to use in the MainViewModel. We’ll use the same trick we did with _resultList: Let’s further assume you … Continue reading →

View Details

Busy week, so this one will be short. I’ve taken the code from Part 7 and copied it into Part 8. The source for 8 is here. So, what’s new? The most important improvement in 8 is the addition of … Continue reading →

View Details

Let’s pick up where we left off in the previous blog post, but it is time to clean up the app to use MVVM. First step: create a ViewModel folder and in that put two files: MainViewModel ViewModelBase MainViewModel is … Continue reading →

View Details

I’m going to start off where we were at the end of Part 5, but this time instead of creating two labels (for State and Zip) I’m going to create one label with MultiBinding:

View Details

When last we looked, we were returning a few countries. Let’s use ZipWise’s ability to look up a city name and give us all the info about all matching cities. We’ll then have fun with displaying that info. When I … Continue reading →

View Details

We’ve seen how to get a single zip code and display it in a series of labels. Let’s use a collection to take a look at how we might deal with that in MAUI. To get started, we’ll create a … Continue reading →

View Details

Our app will spring to life in AppShell.xaml. We’ll be putting a few additional things there, but key for now is the ShellContent element As you can see there are three attributes: the Title, the ContentTemplate and the Route. The … Continue reading →

View Details

As noted in part 0, I assume you are a Xamarin.Forms/C# programmer, familiar with Visual Studio. This series is not about converting your existing Xamarin.Forms apps; rather it is about converting your brain to MAUI. Since I’m learning as I’m going, your mileage … Continue reading →

View Details

As noted in part 0, I assume you are a Xamarin.Forms/C# programmer, familiar with Visual Studio. This series is not about converting your existing Xamarin.Forms apps; rather it is about converting your brain to MAUI. Since I’m learning as I’m … Continue reading →

View Details

Programming is not easy. It is made particularly difficult by legitimate statements such as these from a Xamarin.Forms project: This can be followed by If the first line doesn’t kill you then the last ones will.

View Details

I’m going to start a serious attempt to upgrade my skills from Xamarin.Forms to Maui. I’m not sure how difficult this will be, but I’m starting with James Montemagno’s excellent video/code course for beginners. Unfortunate for me, and perhaps for … Continue reading →

View Details

Incredibly pleased to have one of the pioneers in Agile programming: Robert “Uncle Bob” Martin. Uncle Bob is known for, among other things, his SOLID principles of development. He is the author of the seminal book Clean Code along with … Continue reading →

View Details

I expect most people my age have had great ideas they never patented. I’ll list a few here just to make myself feel better and to encourage you to post yours (these are ideas that are already patented or can’t … Continue reading →

View Details

I’m joined by James Montemagno, Principal Lead Program Manager for .NET Community at Microsoft, and the most enthusiastic person I know. James is the author of the .NET Presentations – .Net Maui In A Box, among many other things. You … Continue reading →

View Details

.visx files are magic as far as I’m concerned. Mads takes us through their history and how they have become much easier to create.  vsixcookbook.com Yet Another Podcast is available wherever you get your podcasts.

View Details

Part 1 of Being a Visual Studio Champ – is now on video! This is a 3 part conference streaming from Denmark and world-wide. vschamp.com Do not miss the next one on Add-ons with (among others) Mads Kristensen. April 27, … Continue reading →

View Details

I love Visual Studio 2022. I spend all my work day in it. It is by far the best IDE I’ve ever worked with. Each iteration gets better, with amazing features. But I’m greedy, so here are some features I … Continue reading →

View Details

Jon Galloway comes on Yet Another Podcast to talk about… well, a lot of stuff. ASP.NET Core Minimal APIs .NET Upgrade Assistant Upgrading from ASP.NET MVC 5 to .NET 6 Upgrading Windows Forms to .NET 6 Upgrading WPF to .NET … Continue reading →

View Details

In this post we will examine one of the aspects of advanced databinding that many people find confusing. Binding . (that is, Binding dot). However, it is surprisingly easy to explain. Binding . allows you to access the entire binding … Continue reading →

View Details

Bill Wagner joins us once again, this time to talk about C# 10 and the evolving Microsoft. documentation. Check back here for links but I just couldn’t wait to publish this.

View Details

You want to bind to a collection of values and display each in turn, but it is possible that some of the objects in the list have null properties, or some properties are missing altogether. You can handle this with … 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 changed, your code had to update the display. If you had a list of data, you had a bit of code to write to get each item in the list displayed in turn.

Xamarin.Forms provides Databinding to do all that work for you. Essentially you say “here’s my data and I want it in this UI element over here. If the data changes, update the display for me.” Even better you can say “here is a collection of objects, and here is how I want you to display properties from each one in turn and if something is added to or taken from the collection, adjust the list accordingly.

“Databinding” is well named: you bind your data to a control, and as the data changes, that change is reflected in the control.

Note: In all our examples we explain only the parts that are relevant to Databinding. For more on XAML, search through this site, or check out the Microsoft documentation.

Binding to a property In the simplest case you want to bind to a single property in your code-behind. In that case, create the property

``` private string _welcomeText = "Welcome to Basic DataBindings!"; public string WelcomeText { get { return _welcomeText; } set { _welcomeText=value; } }

```

Now we’re going to add a label to the xaml page, but we’re going to tell that label to get its text from the property we just created

```

```

That really is all there is to databinding. You mark your Xaml that you want its Text to be from the property WelcomeText in the object you’ve set as the binding context.

Binding Context The binding context is nothing more than telling the UI where to get its data (typically a class — either the code-behind as we’ve done here, or in a View Model as you should.).

There are a couple ways to set the binding context. One is to set it directly in the constructor of the code behind, another and recently preferred approach is what we do in our example: set it in the Xaml.

```

```

I’ve set the binding context to the Bookstore class in the model folder. We’ll set all that up below.

Binding Mode Normally, your binding is from your source (the property) to the target control. But sometimes you want your data to go the other way (for example when the user is filling in a form).

```

```

With two way binding the user’s entry will be put in the Property. Here I used a placeholder, but you are free to initialize the Entry with a value and then replace that value with whatever the user enters.

There actually are a number of modes, but these are the two you’ll use 90% of the time.

Collections To show this, we need a bit of setup. I’ll create a folder named Model and in it create a class Book.

``` public class Book { public string Name { get; set; } public string Author { get; set; }

}

```

In the same file (because I’m lazy) I’ll create a class Bookstore, and stock it with a collection of three books.

``` public class BookStore { public string StoreName { get; set; } public List Books { get; set;} public BookStore() { StoreName="Jesse's Books"; var booksInStock = new List { new Book { Name="The Sound And The Fury", Author="Faulkner", }, new Book { Name = "The Time Of Our Singing", Author = "Powers", },

        new Book
        {
            Name= "In Search of Lost Time",
            Author="Proust",

        }

    };

  Books = booksInStock;
}

}

```

With that data source, we’re ready to tell Xaml how to display each one.

Template In manufacturing you set up a template of what you want and then stamp them out one after the other. The same is true with databinding the contents of lists. We’ll set up how we want to display each book, and then feed the list to the list control and it will stamp out each item.

(Normally, I’d put the list data (the bookstore) in a ViewModel, but our focus here is on binding, not MVVM)

```

```

The first thing we see is the BindingContext being set.

Next we have our content, starting with a label that displays static text, the word Hello

Following that, we have our simple databinding as shown above, this time setting the text to whatever is in the property StoreName.

Now the fun begins. We declare a ListView element and set its ItemsSource to a list of objects; in this case the Books collection. Each member of that collection is a Book, and each Book has the properties Name and Author. These are the properties we want to display.

I think of it this way: the ListView takes one object off the collection at a time. In this case it is a Book. The template tells us which properties of that object to display.

The result is a list displaying the name and author (and because we are using a TextCell, the author is being treated as a detail.

Excelsior! With what you’ve seen here, you are ready for the rest of our series on Advanced Data Binding. The first in that series is here.

More about databinding from Microsoft here

Source Code here

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen Pluralsight & LinkedIn Learning courses. He was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP and a Microsoft MVP.View all posts by Jesse Liberty →

Rodrigo Juarez is a full-stack and Xamarin Certified Mobile Professional developer. His mission is to solve complex problems for his clients focusing on the results, applying the most adequate technology available and best practices to ensure a cost-effective and high-quality solution. He has 20+ years of experience in a wide variety of projects in the development of applications for web, desktop and mobile using Microsoft technologies in areas such as management, services, insurance, pharmacy and banks. He can be reached at Rodrigo Juarez

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 entry and a button, but you only want the button enabled as long as there are one or more characters in the text entry, and of course if there is no text entered you want to disable button.

You could bind the button to a boolean property in your View Model and bind the text to another property and then on text changed you could test to see if there is text in the entry control and update the button. Yuck.

Value Converters For example, since “IsEnabled takes a boolean and the number of characters is an int, you need a way to convert that int into a bool. That is where value converters enter the picture.

The standard format for a value converter is

  • Implement IValueConverter
  • Implement a method Convert according to the interface
  • Implement a method ConvertBack according to the interface

Note that frequently you won’t need ConvertBack. In that case, implement it to return null or to throw a NotImplemented exception.

Our converter is pretty common. Since we want to convert an int to a bool, we’ll use the clever name IntToBoolConverter.

Next, we implement the first method, Convert

``` public class IntToBoolConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (int)value!=0; }

```

And for ConvertBack we’re going to say if the value is true, return 1 otherwise return 0

``` public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value ? 1 : 0; }

```

Using the Converter Our test code is as simple as can be. We have an entry which has no text in it, and a button whose IsEnabled value depends on binding to that control, but converting the int (how many characters) to a bool (enable or not).

We start by creating a ResourceDictionary, in this case at the top of the XAML page (which is very common for resources you are only going to use on one page)

```

```

Note: For resources you are going to use on many pages, you will want to put the resource in a ResourceDictionary in app.xaml. You will access it in exactly the same way as all the ResourceDictionaries in a project are merged at compile time.

Notice that we’ve assigned a key to the converter, this allows us to use the key in the XAML.

```

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 these every week or two.

Getting Started We will be posting Part 0 shortly.

Samples For each topic we discuss, we will provide a simple sample (as simple as possible but no simpler) which we’ll put up on Github and we’ll provide the URL in the blog post. We will walk through that sample to eliminate any confusion and to drive home what we’ve said about the topic.

Some of the samples we’ll make up for this series, others we’ll steal from the Microsoft documents. Which reminds me, why would you read this instead of the official documents? The answer, for me, is that the Microsoft documents are very thorough, but sometimes that can be overwhelming. Most important, however is that triangulating from multiple sources can help zero in on a full understanding.

Topic #1: Paths The use of the path keyword is a good, intermediate place to start. It can be used in a number of ways. The most frequent is either to point to a property of an object held in a resource, or to point to a property of a property.

Example Here is an example we can take apart. To create this example, I opened VS22 and created a new cross platform (Xamarin.Forms) application. This gave me MainPage.xaml and MainPage.xaml.cs which for this simple example is all we need.

I will leave MainPage.xaml.cs alone, and do all the work in MainPage.xaml. All of the use of path in this example will be declarative.

Here is the complete example:

```

<StackLayout Margin="10,50">

    <TimePicker x:Name="timePicker" Time="17:05" />

    <Label Text="{Binding Source={x:Reference timePicker}, Path=Time.TotalSeconds, StringFormat='{0} total seconds'}" />

    <Slider
        x:Name="slider"
        BackgroundColor="DarkSlateGray"
        Maximum="10"
        Minimum="0"
        ThumbColor="Red"
        Value="4" />

    <!--  Path and BindingContext set in the binding  -->
    <Label Text="{Binding Source={x:Reference slider}, Path=Value, StringFormat='The value of slider is {0}'}" />

    <!--  Path as content property  -->
    <Label Text="{Binding Value, Source={x:Reference slider}, StringFormat='The value of slider is {0}'}" />

    <!--  Path as content property & setting the binding context  -->
    <Label BindingContext="{x:Reference slider}" Text="{Binding Value, StringFormat='The value of slider is {0}'}" />

    <Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture}, Path=DateTimeFormat.DayNames[3], StringFormat='The middle day of the week is {0}'}" />

</StackLayout>

```

The first step is to declare a TimePicker control named timePicker (the name will be important). We initialize its time to 17:05 (5:05pm).

We are now ready to access a property the TimePicker control, Time. But we don’t want that property, we want the subproperty TotalSeconds. No problem, we set the source to the TimePicker as a Reference using the name (timePicker) and then set the path to the subproperty we are interested in. We can then make use of the StringFormat clause to display the total seconds

Using path to capture a sub-property In the second part of this example,we declare a slider, and set a few attributes, including initializing its value to 4. We are now ready to access the slider and its value. If you have setup INotifyPropertyChanged, as you move the slider the value in the Label will be updated.

Tying the label to the value of the slider Notice that in the next part (Path as Content Property) we bind to the Value and then provide the source, and do not have to make the implied path explicit. That is, we could write

```

```

But in this case, the path is redundant.

We then see the option to set the BindingContext explicitly to the slider, and then we can continue to bind to the value .

The short story here is that there are a number of ways to set the (implicit or explicit) binding context (see Post 0)

In the final part of this example, we bind to the CurrentCulture which allows u to use an indexed path. Study this one a bit, it is not intuitive that you can do this.

The complete example Future posts will be a bit more complex and/or advanced, but we wanted to start out easy.

Additional documentation about binding path can be found here.

The source code for this example (and all examples in this series) can be found here.

This blog post and sample was written (as all will be) by Rodrigo Juarez and Jesse Liberty. Spanish translation for this post can be found here.

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen Pluralsight & LinkedIn Learning courses. He was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP and a Microsoft MVP.

Rodrigo Juarez is a full-stack and Xamarin Certified Mobile Professional developer. His mission is to solve complex problems for his clients focusing on the results, applying the most adequate technology available and best practices to ensure a cost-effective and high-quality solution. He has 20+ years of experience in a wide variety of projects in the development of applications for web, desktop and mobile using Microsoft technologies in areas such as management, services, insurance, pharmacy and banks. He can be reached at Rodrigo Juarez

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)

I have created a simple example. We’re going to start with an out of the box Xamarin.Forms project. As part of that we’ll get an AboutPage. At the bottom of the about page I’m going to add a button:

```

View Details

Lance McCarthy talking about Maui, VS2022, community contributions and much more.

http://jesseliberty.com/wp-content/media/Show203.mp3 Referenced sites and source:

  • Twitter – https://twitter.com/lancewmccarthy
  • Blog – https://dvlup.com/
  • Resources (see descriptions below)
    • 1 https://github.com/LanceMcCarthy/CommonHelpers
    • 2 https://github.com/LanceMcCarthy/DevOpsExamples
    • 3 https://github.com/LanceMcCarthy/MediaFileManager
    • 4 Bonus https://github.com/LanceMcCarthy/Flusher
  • Tools
    • GitKracken | Legendary Git

Resource 1 – CommonHelpers

That is the CommonHelpers NuGet package I was referring to. It not only is a good helper in a .NET project, but you can also look at it’s GitHub Actions to see how to automatically built, test and publish to NuGet.

  • Take a look at the readme for just a small taste of what it provides help for in a project https://github.com/LanceMcCarthy/CommonHelpers/blob/main/README.md
  • Take a look at its GitHub Actions workflows to learn how you can automatically build, test and publish to NuGet.org https://github.com/LanceMcCarthy/CommonHelpers/tree/main/.github/workflows
  • I also have the Azure DevOps pipelines publicly visible here https://dev.azure.com/lance/DevOps%20Examples/_build

Resource 2 – DevOpsExamples

That repo shows you how to build WPF, ASP.NET Core, WinForms, Console, Xamarin.Forms, .NET MAUI, Angular, React and Vue projects in GitHub Actions, Azure DevOps, GitLab CI and AppCenter (see the build status badges here).

The workflows can be found here https://github.com/LanceMcCarthy/DevOpsExamples/tree/main/.github/workflows

Resource 3 – MediaFileManager a real-world CI-CD example for WPF

This repo is for MediaFileManager, one of my real-world WPF apps that is published to the Microsoft Store. It shows you how to use GitHub Actions to automatically build MSIX packages and publish to the Microsoft Store.

Not only does it build and upload to the Store, but I also show how to build an msixbundle with an appinstaller file that gets uploaded to Azure Blob Storage so you can host your own mini-Microsoft Store for your non-Store users. Check out the mini-store page here Media File Manager (windows.net)

Resource 4 (bonus) – AI Powered Toilet Flusher for my Cat

I built a full system that uses AI, SignalR, Windows IoT, and Xamarin.Forms to automatically flush the human toilet when my cat uses it. You can see the companion blog post here Using Windows IoT, SignalR, Azure Custom Vision and Xamarin Forms to Flush a Toilet – DVLUP

View Details

Mads Kristensen talks about all the goodness in Visual Studio 2022

http://jesseliberty.com/wp-content/media/Show202.mp3

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 one hand it has some fantastic features for a serious programmer. On the other hand, it is a beast and can significantly slow both loading VS and building your app. I’ve loaded it and removed it a number of times. On balance, it is a killer utility.

1 – CodeMaid – another extension for Visual Studio. This does all the ugly work of organizing your files and making them rational and good looking. Unfortunate name, but wonderful extension. Beware, however, that VS occasionally complains that CodeMaid is slowing down the build.

2 – OzCode. I’m fascinated by this utility. It claims it will help you walk through a complex LINQ statement, and do a host of other things (check out their website). I have the sense that their strong suit is on the Mac. Still, worth checking out.

3 – Powershell. It’s simple, if you are using Git you need this. It’s good for a million things, but I use it dozens of time a day to interact with git, and I make it pretty with Hanselman’s guide.

4 – CopyClip2 – Okay this is a cheat since CopyClip2 only runs on the Mac. For Windows I use Alt-V. They do the same thing: they let you review your clipboard. CopyClip2 costs a few bucks, and don’t get me started on how weird it is that we won’t spend a few dollars on software. “$.99? Oh no, that’s too expensive for this $3,000 computer.”

5 Notepad++ – This gem of a program is, essentially Notepad on steroids. “Notepad++ is a text editor and source code editor for use under Microsoft Windows. It supports around 80 programming languages with syntax highlighting and code folding.” – oh and so much more.

6 Feedly – Suffice to say that I like all my RSS feeds in one place, rather than distracting me when I’m trying to get work done. This is, in my opinion, the best RSS manager out there.

7 – LinqPad – This incredibly powerful program should be on every programmer’s list. Need to experiment with code snippets? with Linq, with Regular expressions, it does all of that and a hell of a lot more.

8 – Clean My Mac/ Clean My PC – A wonderful way to keep your computer clean, empty of cruft, and generally optimized. The Mac version is more powerful, but the PC version is still quite great.

9 – Teams. Microsoft wins this one for intra-team communication and collaboration, though I still have a soft spot in my heart for Slack.

10 – OneNote. I’ve tried a number of similar products. They all turn out to be “write once , read never.” OneNote has a great search, and that is really what I need.

11 – Microsoft ToDo – I’ve tried a zillion to do lists, many set up to work well with “Getting Things Done.” Some are expensive, most are complex. I love Microsoft ToDo. It could not be simpler to use, it has alarms and due dates and notes but not much more, and it syncs seamlessly across my PC, Mac and phone. Oh, and it’s free.

NB: I’ve received free copies of some of these as a Microsoft MVP. But only because I asked, which I did only because I thought they were great.

View Details

Presentation to the St. Pete’s user group

View Details

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

http://jesseliberty.com/wp-content/media/Show200.mp3