<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shawn Wildermuth</title>
    <description>The latest articles on Forem by Shawn Wildermuth (@shawnwildermuth).</description>
    <link>https://forem.com/shawnwildermuth</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F63451%2Fad7c3309-58e9-4a89-b82c-ab552d68a0ad.jpg</url>
      <title>Forem: Shawn Wildermuth</title>
      <link>https://forem.com/shawnwildermuth</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shawnwildermuth"/>
    <language>en</language>
    <item>
      <title>Is it Time to Panic? Suddenly, Everyone Seems to Need a Job</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Tue, 15 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/is-it-time-to-panic-suddenly-everyone-seems-to-need-a-job-3aon</link>
      <guid>https://forem.com/shawnwildermuth/is-it-time-to-panic-suddenly-everyone-seems-to-need-a-job-3aon</guid>
      <description>&lt;p&gt;In my last &lt;a href="https://wildermuth.com/2023/07/31/where-have-i-been"&gt;blog post&lt;/a&gt;, I mentioned that I was pivoting to what I’m doing next. It feels a lot of people are going through an upheaval. Is it systemic?&lt;/p&gt;

&lt;p&gt;To be clear, I have no idea what’s happening but it looks like a lot of organizations have taken the current landscape to trim their rolls. Of course, some of you might think AI is the culprit but I talked about that in one of my rants if you want to go flame me there ;)&lt;/p&gt;

&lt;p&gt;Over the past month or so, I’ve watched as Pluralsight, LinkedIn, Plex, Microsoft and I am sure more that I haven’t noticed. Earlier in the year, the announcement from Facebook, Alphabet, Twitter and Microsoft already left some people worried.&lt;/p&gt;

&lt;p&gt;A lot of these jobs seem to be more about developer relations. This seems like a pattern. Sure, startups like SourceGraph are hiring, but can they absorb the other layoffs? I don’t know.&lt;/p&gt;

&lt;p&gt;Am I concerned? For my own future, sure. I’m 54 and ageism exists, but I have faith in my abilities. The real concern for me, is that Developer Advocates are being cut. There is a real movement towards Discord as documentation and developer relationships. I think this trend is newer than the pandemic.&lt;/p&gt;

&lt;p&gt;The other side of the coin is that overall the unemployment rate is actually pretty low. For me, that meant I wasn’t looking at jobs outside of the tech companies. Sometimes I forget that most tech jobs aren’t in tech companies like Ford, Geico, and Wells Fargo. So, if you’re looking, don’t forget that tons of other companies have openings (in fact, reach out if you are a Vue developer that can work remote, I know of a job or two).&lt;/p&gt;

&lt;p&gt;Lastly, I wanted to highlight a few people that I know are looking and that I think are genuinely great. Here are their LinkedIn links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;David Neal: &lt;a href="https://www.linkedin.com/in/davidneal/"&gt;https://www.linkedin.com/in/davidneal/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Joe Guadagno: &lt;a href="https://www.linkedin.com/in/josephguadagno/"&gt;https://www.linkedin.com/in/josephguadagno/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ted Neward: &lt;a href="https://www.linkedin.com/in/tedneward/"&gt;https://www.linkedin.com/in/tedneward/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lars Klint: &lt;a href="https://www.linkedin.com/in/lklint/"&gt;https://www.linkedin.com/in/lklint/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am not sure I’m looking for a job yet, but I’m still writing courses and working with clients for the time being. This fall may tell a different tale.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1s4ZNDVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>Where Have I Been?</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Mon, 31 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/where-have-i-been-415m</link>
      <guid>https://forem.com/shawnwildermuth/where-have-i-been-415m</guid>
      <description>&lt;p&gt;I went to my blog the other day and noticed my last story here was in February. I guess I got a little distracted. So, what have I been up to? Let’s talk about it.&lt;/p&gt;

&lt;p&gt;Over the last couple of years, like many blogs, I’ve seen the readership dwindle. This doesn’t mean I think it’s time to abandon the blog. But with so many other things taking my time, I suspect I won’t be blogging quite as regularly as I have in the past. After 1730 blog posts, this blog has been really important to me. I’d never abandon it.&lt;/p&gt;

&lt;p&gt;So, if I’m not blogging, what am I doing?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Film
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://manenoughfilm.com/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cHL1x5Ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://twainfilms.com/img/manenough/poster-horizontal.jpg" alt="Man Enough to Heal" width="800" height="450"&gt;&lt;/a&gt;The most obvious answer to this is the film I’ve been working on since the beginning of Covid: &lt;a href="https://manenoughfilm.com/"&gt;Man Enough to Heal&lt;/a&gt;. The film post-production wrapped in May. Since then, I’ve submitted it to film festivals and engaged a sales agent to find distribution. I’m quite happy with the results and can’t wait to share here when it’s available to watch!&lt;/p&gt;

&lt;h2&gt;
  
  
  Pluralsight Courses
&lt;/h2&gt;

&lt;p&gt;Since the beginning of the year, I’ve working full-time updating and creating new courses for &lt;a href="https://shawl.ink/psauthor"&gt;Pluralsight&lt;/a&gt;. Right now, I’m in the middle of updating my long &lt;a href="https://www.pluralsight.com/courses/aspnetcore-mvc-efcore-bootstrap-angular-web"&gt;ASP.NET Core, End-to-End course&lt;/a&gt; for .NET 6 (and .NET 8 when it ships). The other courses I’ve released or updated this year include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pluralsight.com/courses/javascript-modules"&gt;Modules in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pluralsight.com/courses/javascript-proxy-objects-reflect"&gt;Proxy Objects in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pluralsight.com/courses/vue-3-forms"&gt;Vue 3 Forms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Coding Shorts
&lt;/h2&gt;

&lt;p&gt;While blogging has waned, I’ve been focused on doing short videos I’m calling “Coding Shorts”. These videos are ten or so minutes long so I can teach one, discrete skill or technology. I’ve made 67 of these so far. Here’s one of my recent ones if you’re interested in getting a taste of them:&lt;/p&gt;

&lt;p&gt;I’ve also authored a handful of “Rants” where I talk about the industry and my opinions about what is important. You can find all the videos at my channel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://shawnl.ink/yt"&gt;https://shawnl.ink/yt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Pivot
&lt;/h2&gt;

&lt;p&gt;Lastly, I’ve been spending time thinking about what is next. Every once in a while (~10 years), I find the need to change the direction of my career. Teaching and training have been great, but I think I’m ready for another challenge. In the past, these pivots have been about what things I’ve focused on. Some of these include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;xBase development that pivoted to C++&lt;/li&gt;
&lt;li&gt;C++ pivoted to COM and ActiveX&lt;/li&gt;
&lt;li&gt;COM and ActiveX that pivoted to ASP.NET and C#&lt;/li&gt;
&lt;li&gt;ASP.NET/C# pivoted to desktop development with WPF/XAML&lt;/li&gt;
&lt;li&gt;WPF/XAML pivoted to Silverlight training&lt;/li&gt;
&lt;li&gt;And lastly, Silverlight pivoted back to ASP.NET and .NET Core&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But where do I go next? I have no idea. But I realize that this is likely my last pivot. This means I’m looking to do something that excites me and that I think is important to do. But who knows what that is. I’m scaling back my training and doing more client work, but I’d love to find some clients that are doing important things. If you think you’re one of those companies, feel free to reach out on my work site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://shawn.wildermuth.com/"&gt;https://shawn.wildermuth.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Last Thing…
&lt;/h3&gt;

&lt;p&gt;In case you don’t know, I release a newsletter every week with the articles that I find useful — both software related and other tech (e.g. Space, Science). If you want to subscribe, feel free to visit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://shawnl.ink/newsletter"&gt;https://shawnl.ink/newsletter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1s4ZNDVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>personal</category>
      <category>videos</category>
    </item>
    <item>
      <title>Minimal API Discovery Tool</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Wed, 22 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/minimal-api-discovery-tool-4874</link>
      <guid>https://forem.com/shawnwildermuth/minimal-api-discovery-tool-4874</guid>
      <description>&lt;p&gt;I’ve been posting and making videos about ideas I’ve had for discovering Minimal APIs instead of mapping them all in &lt;code&gt;Program.cs&lt;/code&gt; for a while. I’ve finally codified it into an experimental nuget package. Let’s talk about how it works.&lt;/p&gt;

&lt;p&gt;I also made a Coding Short video that covers this same topic, if you’d rather watch than read:&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The package can be installed via the dotnet tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package WilderMinds.MinimalApiDiscovery

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once it is installed, you can use an interface called &lt;code&gt;IApi&lt;/code&gt; to implement classes that can register Minimal APIs. The &lt;code&gt;IApi&lt;/code&gt; interface looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// An interface for Identifying and registering APIs
/// &amp;lt;/summary&amp;gt;
public interface IApi
{
  /// &amp;lt;summary&amp;gt;
  /// This is automatically called by the library to add your APIs
  /// &amp;lt;/summary&amp;gt;
  /// &amp;lt;param name="app"&amp;gt;The WebApplication object to register the API &amp;lt;/param&amp;gt;
  void Register(WebApplication app);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essentially, you can implement classes that get passed the &lt;code&gt;WebApplication&lt;/code&gt; object to map your API calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class StateApi : IApi
{
  public void Register(WebApplication app)
  {
    app.MapGet("/api/states", (StateCollection states) =&amp;gt;
    {
      return states;
    });
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would allow you to register a number of related API calls. I think one class per API is too restrictive. When used in .NET 7 and later, you could make a class per &lt;code&gt;group&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public void Register(WebApplication app)
  {
    var group = app.MapGroup("/api/films");

    group.MapGet("", async (BechdelRepository repo) =&amp;gt;
    {
      return Results.Ok(await repo.GetAll());
    })
      .Produces(200);

    group.MapGet("{id:regex(tt[0-9]*)}", 
      async (BechdelRepository repo, string id) =&amp;gt;
    {
      Console.WriteLine(id);
      var film = await repo.GetOne(id);
      if (film is null) return Results.NotFound("Couldn't find Film");
      return Results.Ok(film);
    })
      .Produces(200);

    group.MapGet("{year:int}", (BechdelRepository repo, 
        int year, 
        bool? passed = false) =&amp;gt;
        {
          var results = await repo.GetByYear(year, passed);
          if (results.Count() == 0)
          {
            return Results.NoContent();
          }

          return Results.Ok(results);
        })
      .Produces(200);

    group.MapPost("", (Film model) =&amp;gt;
    {
      return Results.Created($"/api/films/{model.IMDBId}", model);
    })
      .Produces(201);

  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of lambdas missing some features (e.g. default values), you can always move the lambdas to just static methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Register(WebApplication app)
{
  var grp = app.MapGroup("/api/customers");
  grp.MapGet("", GetCustomers);
  grp.MapGet("", GetCustomer);
  grp.MapPost("{id:int}", SaveCustomer);
  grp.MapPut("{id:int}", UpdateCustomer);
  grp.MapDelete("{id:int}", DeleteCustomer);
}

static async Task&amp;lt;IResult&amp;gt; GetCustomers(CustomerRepository repo)
{
  return Results.Ok(await repo.GetCustomers());
}

//...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason for the suggestion of using static methods (instance methods would work too) is that you do not want these methods to rely on state. You might think that constructor service injection would be a good idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomerApi : IApi
{
  private CustomerRepository _repo;

  // MinimalApiDiscovery will log a warning because
  // the repo will become a singleton and lifetime 
  // will be tied to the implementation methods.
  // Better to use method injection in this case.
  public CustomerApi(CustomerRepository repo)
  {
    _repo = repo;
  }

// ...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This doesn’t work well as the call to &lt;code&gt;Register&lt;/code&gt; happens once at startup and since this class is sharing that state, the injected service becomes a singleton for the lifetime of the server. The library will log a &lt;strong&gt;warning&lt;/strong&gt; if you do this to help you avoid it. Because of that I suggest that you use static methods instead to prevent this from accidently happening.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: I considered using static interfaces, but that requires that the instance is still a non-static class. It would also limit this library to use in .NET 7/C# 11 - which I didn’t want to do. It works in .NET 6 and above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you’ve created these classes, you can simple make two calls in startup to register all &lt;code&gt;IApi&lt;/code&gt; classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using UsingMinimalApiDiscovery.Data;
using WilderMinds.MinimalApiDiscovery;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddTransient&amp;lt;CustomerRepository&amp;gt;();
builder.Services.AddTransient&amp;lt;StateCollection&amp;gt;();

// Add all IApi classes to the Service Collection
builder.Services.AddApis();

var app = builder.Build();

// Call Register on all IApi classes
app.MapApis();

app.Run();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea here is to use reflection to find all &lt;code&gt;IApi&lt;/code&gt; classes and add them to the service collection. Then the call to &lt;code&gt;MapApis()&lt;/code&gt; will get all &lt;code&gt;IApi&lt;/code&gt; from the service collection and call Register.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The call to &lt;code&gt;AddApis&lt;/code&gt; simply uses reflection to find all classes that implement &lt;code&gt;IApi&lt;/code&gt; and add them to the service collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  var apis = assembly.GetTypes()
    .Where(t =&amp;gt; t.IsAssignableTo(typeof(IApi)) &amp;amp;&amp;amp; 
                t.IsClass &amp;amp;&amp;amp; 
                !t.IsAbstract)
    .ToArray();

  // Add them all to the Service Collection
  foreach (var api in apis)
  {
    // ...
    coll.Add(new ServiceDescriptor(typeof(IApi), api, lifetime));
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once they’re all registered, the call to &lt;code&gt;MapApis&lt;/code&gt; is pretty simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var apis = app.Services.GetServices&amp;lt;IApi&amp;gt;();

foreach (var api in apis)
{
  if (api is null) throw new InvalidProgramException("Apis not found");

  api.Register(app);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Futures
&lt;/h2&gt;

&lt;p&gt;While I’m happy with this use of Reflection since it is only a ‘startup’ time cost, I have it on my list to look at using a Source Generator instead.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have experience with Source Generators and want to give it a shot, feel free to do a pull request at &lt;a href="https://github.com/wilder-minds/minimalapidiscovery" rel="noopener noreferrer"&gt;https://github.com/wilder-minds/minimalapidiscovery&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m also considering removing the AddApis and just have the &lt;code&gt;MapApis&lt;/code&gt; call just reflect to find all the IApis and call register since we don’t actually need them in the Service Collection.&lt;/p&gt;

&lt;p&gt;You can see the complete source and example here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/wilder-minds/minimalapidiscovery" rel="noopener noreferrer"&gt;https://github.com/wilder-minds/minimalapidiscovery&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>rest</category>
      <category>aspnetcore</category>
      <category>dotnetcore</category>
    </item>
    <item>
      <title>Digging Into Nullable Reference Types in C#</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/digging-into-nullable-reference-types-in-c-2b3d</link>
      <guid>https://forem.com/shawnwildermuth/digging-into-nullable-reference-types-in-c-2b3d</guid>
      <description>&lt;p&gt;This topic has been on my &lt;code&gt;TODO:&lt;/code&gt; list for quite a while now. As I work with clients, many of them are just ignoring the warnings that you get from Nullable Reference Types. When Microsoft changed to make them the default, some developers seemed to be confused by the need. Here is my take on them:&lt;/p&gt;

&lt;p&gt;I also made a Coding Short video that covers this same topic, if you’d rather watch than read:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=tMKcLwlhoEs" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=tMKcLwlhoEs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Before Nullable Reference Types
&lt;/h2&gt;

&lt;p&gt;There has always been two different types of objects in C#: &lt;code&gt;value types&lt;/code&gt; and &lt;code&gt;reference types&lt;/code&gt;. Value types are created on the stack (therefore they go away without needing to be garbage collected); and Reference Types are created by the heap (needing to be garbage collected). Primative types and structs are value types, and everything else is a reference type, including strings. So we could do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int x = 5;
string y = null;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By it’s design, value-types couldn’t be null. They just where:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int x = null; // Error
string y = null;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There were occassions that we needed null on value types. So they introduced the &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; struct. Essentially, this allowed you to make value types nullable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nullable&amp;lt;int&amp;gt; x = null; // No problem

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They did add some syntactical sugar for &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; by just using a question mark:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int? x = null; // Same as Nullable&amp;lt;int&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But why nullability? So you can test for whether a value exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int? x = null; 

if (x.HasValue) Write(x);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this works, you could test for null as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int? x = null; 

if (x is not null) Write(x);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, this is what Nullable value types are, but reference types already support null. Reference types do support being null, but do &lt;strong&gt;not&lt;/strong&gt; support not allowing null. That’s the difference. By enabling Nullable Reference Types, all reference types (by default) do not support Null unless you use the define them with the question-mark:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;object x = null // Doesn't work

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But utilizing the null type definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;object? x = null // works

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As C# developers, we spend a lot of time worrying about whether an object is null (since anyone can pass a null for parameters or properties). So, enabling Nullable Reference Types makes that impossible. By default, new projects (since .NET 6) have enabled Nullable Reference Types by default. But how?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling Nullable Reference Types
&lt;/h2&gt;

&lt;p&gt;In C# 8, they added the ability to enable Nullable Reference Types. There are two ways to enable it: file-based declaration or a project level flag. For projects that want to opt into Nullable Reference Types slowly, you can use the file declarations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#nullable enable
object x = null; // Doens't work, null isn't supported
#nullable disable

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But for most projects, this is done at the project level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!--csproj--&amp;gt;
&amp;lt;Project Sdk="Microsoft.NET.Sdk"&amp;gt;

  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;OutputType&amp;gt;Exe&amp;lt;/OutputType&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net7.0&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;ImplicitUsings&amp;gt;enable&amp;lt;/ImplicitUsings&amp;gt;
    &amp;lt;Nullable&amp;gt;enable&amp;lt;/Nullable&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

&amp;lt;/Project&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;Nullable/&amp;gt;&lt;/code&gt; property is what enables the feature.&lt;/p&gt;

&lt;p&gt;When you enable this, it will produce warnings for appling null to reference types. But you can even turn these into errors to force a project to address the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;WarningsAsErrors&amp;gt;Nullable&amp;lt;/WarningsAsErrors&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Nullable Reference Types
&lt;/h2&gt;

&lt;p&gt;So, you’ve gotten this far so let’s talk some basics. When defining a variable, you can opt-into nullability by defining the type with nullability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string? x = null;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means anywhere you’re just defining the type (without inferring the type), C# will assume that null isn’t a valid value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string x = "Hello";

if (x is null) // No longer necessary, this can't be null
{
  // ...
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what happens when we infer the type? For value types, it is assumed to be a non-nullable type, but for reference type…nullable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var u = 15; // int
var s = ""; // string?
var t = new String('-', 20); // string?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is actually one of the reasons I’m moving to the new syntax for creating objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;object s = new(); // object - not nullable

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not exactly about nullable reference types, but in this case, the object is not null because we’re making sure it’s not nullable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classes and Nullable Reference Types
&lt;/h2&gt;

&lt;p&gt;When clients have moved here, the biggest pain they seem to run into is with classes (et al.). After spending so many years writing simple data classes like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Customer
{
  public int Id { get; set;}
  public string Name { get; set;} // Warning
  public DateOnly Birthdate { get; set;}
  public string Phone { get;set;} // Warning
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Properties that aren’t nullable are expected to be set before the end of the constructor. There are two ways to address make them nullable; and initalize the properties.&lt;/p&gt;

&lt;p&gt;Making the properties nullable has the benefit of being more descriptive of the actual usage of the property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Customer
{
  public int Id { get; set;}
  public string Name? { get; set;} // null unless you set it
  public DateOnly Birthdate { get; set;}
  public string Phone? { get;set;} // null unless you set it
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can set the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Customer
{
  public int Id { get; set;}
  public string Name { get; set;} = "";
  public DateOnly Birthdate { get; set;}
  public string Phone { get;set;} = "";
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Customer
{
  public int Id { get; set;}
  public string Name { get; set;} 
  public DateOnly Birthdate { get; set;}
  public string Phone { get;set;} 

  public Customer(string name, string phone)
  {
    Name = name;
    Phone = phone;
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may, at first, seem like trouble for certain types of classes. In fact, it’s is not uncommon to opt-out of nullability for entity classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#nullable disable
public class Customer
{
  public int Id { get; set;}
  public string Name { get; set;} // No Warning
  public DateOnly Birthdate { get; set;}
  public string Phone { get;set;} // No Warning
}
#nullable enable

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing for Null
&lt;/h2&gt;

&lt;p&gt;When you start using nullable properties on objects, you quickly run into warnings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

WriteLine($"Name: {customer.Name}"); // Warning

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The warning is because the compiler can’t confirm it is not null (Name is nullable). This is one of the uncomfortable parts of using Nullable Reference Types. So we can wrap it with a test for null (like you’ve probably been doing for a long time):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

if (customer.Name is not null)
{
  WriteLine($"Name: {customer.Name}");
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At that point, the compiler can be sure it’s not null because you tested it. But this seems a lot of work to determine null. Instead we can use some syntactical sugar to shorten this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

WriteLine($"Name: {customer?.Name}"); // Warning

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;?.&lt;/code&gt; is simply a shortcut. If Name is null, it jsut returns a null. This allows you to deal with nested nullable types pretty easily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

WriteLine($"Name: {customer?.Name?.FirstName}"); // Warning

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, you can see that the &lt;code&gt;?.&lt;/code&gt; is used at multiple places in the code as &lt;code&gt;Name&lt;/code&gt; could be null and &lt;code&gt;FirstName&lt;/code&gt; could also be null.&lt;/p&gt;

&lt;p&gt;This also affects how you will allocate a variable that might be null. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

string name = customer.Name; // Warning, Name might be null

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The null coalescing operator can be used here to define a default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

string name = customer.Name ?? "No Name Specified"; // Warning, Name might be null

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;??&lt;/code&gt; operator allows for the fallback in case of null. which should simplify some common scenarios.&lt;/p&gt;

&lt;p&gt;But sometimes we need to help the compiler figure out whether something is null. You might know that a particular object is not null even if it is a nullable property. There is an additional syntax that supports telling the compiler that you know better. Just use the &lt;code&gt;!&lt;/code&gt; syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

string name = customer.Name!; // I know it's never null

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This just tells the compiler what you expect. If the Name is null, it will throw an exception…so only use it when you’re sure. The bang symbol (e.g. &lt;code&gt;!&lt;/code&gt;) is used at the end of the variable. So if you need to string these, you’ll put the bang at each level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer customer = new();

string name = customer.Name!.FirstName!; // I know they're never null

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While using Nullable Reference Types could be seen as a way to over-complicate your code, these bits of syntactical sugar can simplify dealing with nullables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generics and Nullable Reference Types
&lt;/h2&gt;

&lt;p&gt;Just like any other code, you can use the question-mark to specify that a value is nullable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SomeEntity&amp;lt;TKey&amp;gt;
{
  public TKey? Key { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem with this is that the type specified in &lt;code&gt;TKey&lt;/code&gt; could also be nullable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SomeEntity&amp;lt;string?&amp;gt; entity = new();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this results in a warning because you can’t have a nullable of a nullable. The generated type might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SomeEntity&amp;lt;string?&amp;gt;
{
  public string?? Key { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the double question-mark. It also suggests that the generic class doesn’t quite know whether to initialize it or not since it doesn’t know about the nullability. To get around this, you can use the &lt;code&gt;notnull&lt;/code&gt; constraint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SomeEntity&amp;lt;TKey&amp;gt; where : notnull
{
  public TKey? Key { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way the generic type can be in control of the nullability instead of the caller.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope that this quick intro into Nullable Reference Types helps you get your head around the ‘why’ and ‘how’ of Nullable Reference Types. Please comment if you have more questions and/or complaints!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/shawnwildermuth/codingshorts/tree/main/nullability" rel="noopener noreferrer"&gt;Nullable Reference Types Example&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Using Vite's Plugin for Progressive Web Apps (PWAs)</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Thu, 09 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/using-vites-plugin-for-progressive-web-apps-pwas-j05</link>
      <guid>https://forem.com/shawnwildermuth/using-vites-plugin-for-progressive-web-apps-pwas-j05</guid>
      <description>&lt;p&gt;I’ve worked with Progressive Web Application plug-ins with several SPA frameworks. Most of them are pretty simple to implement. But when I learned about Vite’s plug-in, I was intrigued since that would work across different SPA frameworks. Let’s take a look at it.&lt;/p&gt;

&lt;p&gt;I also made a Coding Short video that covers this same topic, if you’d rather watch than read:&lt;/p&gt;

&lt;p&gt;The Vite plug-in for PWA works at the Vite/Build level, not for your specific framework (or lack of a framework). That means it will work for Vue, React, SvelteKit and Vanilla JS (and any other Vite-powered development). Before we do any of this, we have a working website:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgobv99g390vw109o7qo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgobv99g390vw109o7qo.jpg" alt="A example website" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To install it, you just need to add it to your development-time dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npm i vite-plugin-pwa --save-dev

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you can add it to your vite.config.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
import { VitePWA } from "vite-plugin-pwa";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    VitePWA()
  ],
  ...
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this installed, you’ll see that your builds will generate some extra files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build started...
✓ 30 modules transformed.
../wwwroot/registerSW.js 0.13 kB
../wwwroot/manifest.webmanifest 0.14 kB
../wwwroot/index.html 0.56 kB
../wwwroot/assets/index-cfd5afe3.css 7.14 kB │ gzip: 1.97 kB
../wwwroot/assets/index-25653f73.js 75.09 kB │ gzip: 30.04 kB
built in 1378ms.

PWA v0.14.1
mode generateSW
precache 5 entries (80.98 KiB)
files generated
  ..\wwwroot\sw.js
  ..\wwwroot\workbox-519d0965.js

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file generated by the plug-in include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;manifest.webmanifest&lt;/strong&gt; : Metadata about the app and an indication that it can be installed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sw.js&lt;/strong&gt; : A, required, service worker that supports running as an app (and offline).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;registerSW.js&lt;/strong&gt; : A new script that Vite injects into the index.html that registers the service worker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;workbox-*.js&lt;/strong&gt; : Workbox specific code to support the PWA.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this generated, you should see the “install icon” on supported browsers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s2e0vxnrc8gislmbz0j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s2e0vxnrc8gislmbz0j.jpg" alt="The Install Button on Chrome" width="442" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can customize the metadata that is used by just adding a metadata object in the plug-in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    VitePWA({      
      manifest: { 
        icons: [
          {
            src: "/icons/512.png",
            sizes: "512x512",
            type: "image/png",
            purpose: "any maskable"
          }
        ]
      }
    })],
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The properties that you can customize in the manifest are all defined here.&lt;/p&gt;

&lt;p&gt;If you run the example now, you can look at the manifest for errors or omissions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flphg7kc0iq8llojmnazf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flphg7kc0iq8llojmnazf.jpg" alt="Examining the Manifest" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click on the Application tab in the tools, you can see that it is complaining about missing icons for different operating systems.&lt;/p&gt;

&lt;p&gt;If you switch to the Service Worker, you can see it is running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgc2ctcqaww8gt9q2tf7j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgc2ctcqaww8gt9q2tf7j.jpg" alt="The Service Worker" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how does this work? The Service Worker can intercept network requests and serve the content necessary to load up the project. In fact, if you look at the “Cache Storage”, you’ll see the standard cache of the web page’s files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9bh2rrfkg0lkdwzypn0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9bh2rrfkg0lkdwzypn0.jpg" alt="workbox Cache" width="800" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The feature of the browser that supports all of this is called &lt;code&gt;workbox&lt;/code&gt;, so if you look at that cache, you’ll see the files that are being cached to load this offline (including .html, .js, .css, etc.). So, let’s try and making the app offline to see what happens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47yrh7rj4sx79wd1tf3p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47yrh7rj4sx79wd1tf3p.jpg" alt="workbox Cache" width="800" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can go offline in the Network tab by changing the networking to offline. If you refresh the page, you’ll get something that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlp7h6idv558ipe2qkfh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlp7h6idv558ipe2qkfh.jpg" alt="Offline Version of Site" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what happened? The cache (see earlier) is only caching the files needed to serve the page, not for any functionality.&lt;/p&gt;

&lt;p&gt;How do we fix this? Luckily, the plug-in supports changing the workbox settings to create your own caches (called runtimeCaching). To do this we return back to the &lt;code&gt;vite.config.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    VitePWA({
      manifest: {
        icons: [
          {
            src: "/icons/512.png",
            sizes: "512x512",
            type: "image/png",
            purpose: "any maskable",
          },
        ],
      },
      workbox: {
        runtimeCaching: [
          {
            urlPattern: ({ url }) =&amp;gt; {
              return url.pathname.startsWith("/api");
            },
            handler: "CacheFirst" as const,
            options: {
              cacheName: "api-cache",
              cacheableResponse: {
                statuses: [0, 200],
              },
            },
          },
        ],
      },
    }),
  ],'
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By creating a section for workbox, we can configure a number of things, but for us we want to create an API cache. You can see that i’m testing all requests for &lt;code&gt;/api&lt;/code&gt; and caching all &lt;code&gt;GET&lt;/code&gt;s into our own cache. By enabling this, the customers reappear. We can see (and interrogate) the cache in the Application tools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahb1chp2wmw1sr22odu1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahb1chp2wmw1sr22odu1.jpg" alt="The API Cache" width="800" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This sort of all encompassing cache might not be realistic, but you could be caching non-volatile API calls. This isn’t a solution for handling offline changes. You can use application-specific code to write it to session or local storage.&lt;/p&gt;

&lt;p&gt;I hope you’ve seen how the Vite PWA plug-in works anbd how you can use it to install your website as a local application!&lt;/p&gt;

&lt;p&gt;You can find the example of the project here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/shawnwildermuth/codingshorts/tree/main/vite-pwa" rel="noopener noreferrer"&gt;Module Example&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vite</category>
      <category>vue</category>
      <category>react</category>
      <category>sveltekit</category>
    </item>
    <item>
      <title>What Surprised Me About ECMAScript Modules</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Wed, 01 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/what-surprised-me-about-ecmascript-modules-27im</link>
      <guid>https://forem.com/shawnwildermuth/what-surprised-me-about-ecmascript-modules-27im</guid>
      <description>&lt;p&gt;I’ve spent the last couple of months working on a new &lt;a href="https://shawnl.ink/psauthor" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt; course about &lt;a href="https://shawnl.ink/jsmod" rel="noopener noreferrer"&gt;Modules in JavaScript&lt;/a&gt;. I’ve been writing JavaScript (and TypeScript) for a lot of years. But digging into the course made me understand how some of this modularity actually worked. Let’s talk about some things that surprised me.&lt;/p&gt;

&lt;p&gt;I also made a Coding Short video that covers this same topic, if you'd rather watch than read:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=JBFYyXEC9_8" rel="noopener noreferrer"&gt;Coding Short Video&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ECMAScript Modules in Node.js
&lt;/h2&gt;

&lt;p&gt;While &lt;strong&gt;Node.js&lt;/strong&gt; has had module support long before ECMAScript got it’s act together and started supporting modules. CommonJS was an early standard for exposing modules. So most of the &lt;strong&gt;Node.js&lt;/strong&gt; projects i’ve worked on just supposed that I had to use CommonJS. For example, a simple import using CommonJS (e.g. require()):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// index.js
const invoices = require("./invoices.js");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since EMCAScript Modules (ESM) are supported, you could just name your &lt;code&gt;index.js&lt;/code&gt; (in our case) to &lt;code&gt;index.mjs&lt;/code&gt; and it would allow us to use EMCAScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// index.mjs
import invoices from "./invoices.mjs";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, for me, I like that Node.js allows us to change the default module type to ESM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "before",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module", // commonjs is the default
  "scripts": {
    "start": "node ./index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "lodash": "^4.17.21"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can just use ESM in our code without the renaming:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// index.js
import invoices from "./invoices.js";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Consuming CommonJS from ECMAScript
&lt;/h2&gt;

&lt;p&gt;So, you can use ESM to load all your own code where you’ve defined your modules directly. This works with your own projects or npm packages. If you’re using it for your own projects, you can rename your project to .cjs and it will be treated as a CommonJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// invoices.cjs
module.exports = [...];

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, more commonly, npm packages are mostly defined as CommonJS modules. How do we use them? For example, we can bring in a npm package (in this case &lt;code&gt;lodash&lt;/code&gt;) like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import lodash from "lodash";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to use the lodash object as you like. But there is a limitation. Ordinarily, you could destructure it to get just the round function we need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { round } from "lodash";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But ESM with Node.js, it doesn’t work. It is because of a fundamental difference in how CommonJS defines named element and how ESM does it. So, to do it, you will need to import it as the default, but then you can destructure manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import lodash from "lodash";
const { round } = lodash; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a minor nit, but if you know how CommonJS modules defined names (as I show in my course), it actually makes sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deferred Imports
&lt;/h2&gt;

&lt;p&gt;I’ve been using ESM for a while and never ran into the &lt;code&gt;import()&lt;/code&gt; function. I used to think that CommonJS was the only module system that allowed for late binding imports. But, alas, I was wrong.&lt;/p&gt;

&lt;p&gt;The import function allows you to request an import at runtime, though it is asynchronous so you have to deal with the promise. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function calculateTotal(invoice) {
  const { taxRates } = await import("./taxRates.js");
  const rate = taxRates[invoice.state];
  const total = invoice.amount + invoice.amount * rate;
  return {
    rate,
    total,
  };
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that the import allows you to load the module the first time we use &lt;code&gt;calculateTotal()&lt;/code&gt;. This does mean that you have to deal with asynchrony with the caller too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invoices.forEach(async i =&amp;gt; {
  const { rate, total } = await calculateTotal(i);
  console.log(`Invoice: ${i.invoiceNumber}, Date: ${i.invoiceDate}
  Gross: $${round(i.amount,2)}
  Tax Rate: ${rate * 100}% 
  Net: $${round(total,2)}`);
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the foreach is now async and you can use await to deal with the asynchrony.&lt;/p&gt;

&lt;p&gt;You can find the example of the project here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/shawnwildermuth/codingshorts/tree/main/jsmod" rel="noopener noreferrer"&gt;Module Example&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javasscript</category>
      <category>ecmascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Generating Sample Data with Bogus</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Sun, 29 Jan 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/generating-sample-data-with-bogus-kh3</link>
      <guid>https://forem.com/shawnwildermuth/generating-sample-data-with-bogus-kh3</guid>
      <description>&lt;p&gt;Most of my job these days is creating tutorials or examples. This means I often start from scratch with a new type of project. I usually just cruft up some sample data for my project to start. While investigating some alternatives to Automapper (video and blog coming soon), I wanted to be able to create a bunch of sample data. I, luckily, ran into a tool that I was surprised I’d never heard of: Bogus. Let’s talk about it.&lt;/p&gt;

&lt;p&gt;I also made a Coding Short video that covers this same topic, if you’d rather watch than read:&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Bogus?
&lt;/h2&gt;

&lt;p&gt;Bogus is a library that works with C#, F# and &lt;a href="http://vb.net/" rel="noopener noreferrer"&gt;VB.NET&lt;/a&gt; that can be used to create repeatable, fake data for applications. It is somewhat a port of a similar library Bogus.js. It accompished this by creating generators (called Fakers) that have a set of rules for generating one or more fake objects. Built-into Bogus is a set of generalized rules for common data categories (i.e. Addresses, Companies, People, Phone Numbers, etc.). Enough talk, let’s see how it works. The full repo is at:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/bchavez/Bogus" rel="noopener noreferrer"&gt;Bogus&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To install Bogus, you can use the Package Manager or just the dotnet CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; dotnet add package Bogus

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Faker
&lt;/h2&gt;

&lt;p&gt;You start out by creating an instance of a class called &lt;code&gt;Faker&amp;lt;T&amp;gt;&lt;/code&gt;. From that class you would use a fluent syntax to set up rules on creating sample data. But let’s start with our POCO for a &lt;code&gt;Customer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Customer
{
  public int Id { get; set; }
  public string? CompanyName { get; set; }
  public string? Phone { get; set; }
  public string? ContactName { get; set; }
  public int AddressId { get; set; }
  public Address? Address { get;set;}
  public IEnumerable&amp;lt;Order&amp;gt;? Orders {get;set;}
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can notice that aside from simple properties, we have a one-to-one relationship to an &lt;code&gt;Address&lt;/code&gt; and a one-to-many relationship with &lt;code&gt;Orders&lt;/code&gt;. Let’s start by creating a faker for the &lt;code&gt;Customer&lt;/code&gt; object and the simple properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var customerFaker = new Faker&amp;lt;Customer&amp;gt;();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then use the &lt;code&gt;RuleFor&lt;/code&gt; method to specify a rule for the Company Name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var customerFaker = new Faker&amp;lt;Customer&amp;gt;()
  .RuleFor(c =&amp;gt; c.CompanyName, f =&amp;gt; f.Company.CompanyName())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first parameter of the &lt;code&gt;RuleFor&lt;/code&gt; method is a lambda to pick the property on &lt;code&gt;Customer&lt;/code&gt; that I want to fake. The second parameter is another lambda to pass in how to generate the property. While we could write any code we need here, the most-common case is to use the &lt;code&gt;Faker&lt;/code&gt; object passed to use the built-in semantics. In this case we are using the Company category to generate a company name.&lt;/p&gt;

&lt;p&gt;If we continue this, we can fake more simple properties like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var customerFaker = new Faker&amp;lt;Customer&amp;gt;()
  .RuleFor(c =&amp;gt; c.CompanyName, f =&amp;gt; f.Company.CompanyName())
  .RuleFor(c =&amp;gt; c.ContactName, f =&amp;gt; f.Name.FullName())
  .RuleFor(c =&amp;gt; c.Phone, f =&amp;gt; f.Phone.PhoneNumberFormat());

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see here that we’re using the Name category and the Phone category. The Bogus library has a large set of these built-in semantics. Sometimes we’ll need to use custom code to generate data we need. For example, we’ll want to generate IDs for the generated customers. One strategy is to just create a local integer and assign it with simple code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var id = 1;

var customerFaker = new Faker&amp;lt;Customer&amp;gt;()
  .RuleFor(c =&amp;gt; c.Id, _ =&amp;gt; id++)
  .RuleFor(c =&amp;gt; c.CompanyName, f =&amp;gt; f.Company.CompanyName())
  .RuleFor(c =&amp;gt; c.ContactName, f =&amp;gt; f.Name.FullName())
  .RuleFor(c =&amp;gt; c.Phone, f =&amp;gt; f.Phone.PhoneNumberFormat());

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see that we just have an integer (which will become a closure to the rule) and we just increment it everytime a new customer is created.&lt;/p&gt;

&lt;p&gt;To use the Faker, we can just call &lt;code&gt;Generate()&lt;/code&gt; with how many you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var customers = customerFaker.Generate(1000);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a thousand fake customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeatable Fake Data
&lt;/h2&gt;

&lt;p&gt;By default, the generation of customers is random. So that everytime you create an instance of the Faker object (e.g. &lt;code&gt;new Faker&amp;lt;Customer&amp;gt;&lt;/code&gt;), you would get different customers. When you want a consistent set of fake data, you can use a seeder to ensure that you get the same data every time. To do this, you just need to set a seed value to the same number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomerFaker : Faker&amp;lt;Customer&amp;gt;
{
    public CustomerFaker()
  {
    var id = 1;

    UseSeed(1969) // Use any number
      .RuleFor(c =&amp;gt; c.Id, _ =&amp;gt; id++)
      .RuleFor(c =&amp;gt; c.CompanyName, f =&amp;gt; f.Company.CompanyName())
      .RuleFor(c =&amp;gt; c.ContactName, f =&amp;gt; f.Name.FullName())
      .RuleFor(c =&amp;gt; c.Phone, f =&amp;gt; f.Phone.PhoneNumberFormat());
  }
}

var customers = new CustomerFaker().Generate(1000);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you do this, you can guarantee to get the same customers. But this affects the entire instance of the faker. This is because every call to &lt;code&gt;Generate&lt;/code&gt; will generate the &lt;strong&gt;next&lt;/strong&gt; set of faked data. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var customerFaker = new CustomerFaker();

var customers = customerFaker.Generate(1);
var companyName = customers.First().CompanyName;

var newCustomers = customerFaker.Generate(1);

Assert.IsTrue(companyName == newCustomers.First().CompanyName); // FAILS

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because the seed is the repeatable data is per-instance. So that the the first call to &lt;code&gt;Generate&lt;/code&gt; will give you the first repeatable object; and the second call to &lt;code&gt;Generate&lt;/code&gt; gives you the second object.&lt;/p&gt;

&lt;p&gt;But if you create a new instance, the names will be guaranteed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var customerFaker = new CustomerFaker();

var customers = customerFaker.Generate(1);
var companyName = customers.First().CompanyName;

var newFaker = new CustomerFaker();
var newCustomers = newFaker.Generate(1);

Assert.IsTrue(companyName == newCustomers.First().CompanyName); // TRUE

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This support the idea of repeatable sample data!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Related Sample Data
&lt;/h2&gt;

&lt;p&gt;In our &lt;code&gt;Customer&lt;/code&gt; class, we have a property for an &lt;code&gt;Address&lt;/code&gt;. We can create a Faker for the &lt;code&gt;Address&lt;/code&gt; too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AddressFaker : Faker&amp;lt;Address&amp;gt;
{
  public AddressFaker()
  {
    var id = 0;
    UseSeed(1969)
      .RuleFor(c =&amp;gt; c.Id, f =&amp;gt; ++id)
      .RuleFor(c =&amp;gt; c.Address1, f =&amp;gt; f.Address.StreetAddress())
      .RuleFor(c =&amp;gt; c.Address2, f =&amp;gt; f.Address.SecondaryAddress())
      .RuleFor(c =&amp;gt; c.City, f =&amp;gt; f.Address.City())
      .RuleFor(c =&amp;gt; c.StateProvince, f =&amp;gt; f.Address.State())
      .RuleFor(c =&amp;gt; c.PostalCode, f =&amp;gt; f.Address.ZipCode());
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, there is a category for the type of data we need and can decide how to generate sample addresses. One thing you might want is to optionally not create certain parts of the fake data. For example, for our addresses, I want some of the &lt;code&gt;Address2&lt;/code&gt; properties to be null to replicate some apartment/suite numbers and addresses that do not have them. To do this, you can use &lt;code&gt;OrNull()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(c =&amp;gt; c.Address2, f =&amp;gt; f.Address.SecondaryAddress()
                                        .OrNull(f, .5f))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;OrNull&lt;/code&gt; method takes the faker object and a value between 0 and 1 to determine how often to generate a &lt;code&gt;null&lt;/code&gt; value. In this example, we’re specifying that we want half (or 50%) of the Addresses to have a null for it’s secondary address.&lt;/p&gt;

&lt;p&gt;Now that we have a faker that does what we want, let’s use it to generate addresses too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CustomerFaker : Faker&amp;lt;Customer&amp;gt;
{
  AddressFaker _addrFaker = new AddressFaker();

    public CustomerFaker()
  {
    var id = 1;

    UseSeed(1969) // Use any number
      .RuleFor(c =&amp;gt; c.Id, _ =&amp;gt; id++)
      .RuleFor(c =&amp;gt; c.CompanyName, f =&amp;gt; f.Company.CompanyName())
      .RuleFor(c =&amp;gt; c.ContactName, f =&amp;gt; f.Name.FullName())
      .RuleFor(c =&amp;gt; c.Phone, f =&amp;gt; f.Phone.PhoneNumberFormat())
      .RuleFor(c =&amp;gt; c.Address, _ =&amp;gt; _addrFaker.Generate(1)
                                              .First()
                                              .OrNull(_, .1f));
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can notice that we’re creating an instance of the &lt;code&gt;AddressFaker&lt;/code&gt; and then using it when we specify the rule for the &lt;code&gt;Customer&lt;/code&gt;’s &lt;code&gt;Address&lt;/code&gt; property. We can even use &lt;code&gt;OrNull&lt;/code&gt; to only generate Addresses for 90% of the customers.&lt;/p&gt;

&lt;p&gt;There is a lot more to the Bogus library, but hopefully this will get you started. To get the example code from the video and this blog post, see the Github Repo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/shawnwildermuth/codingshorts/tree/main/bogus" rel="noopener noreferrer"&gt;FixingIt Code&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Vite-Powered SPAs in ASP.NET Core Projects</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Wed, 18 Jan 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/vite-powered-spas-in-aspnet-core-projects-4khc</link>
      <guid>https://forem.com/shawnwildermuth/vite-powered-spas-in-aspnet-core-projects-4khc</guid>
      <description>&lt;p&gt;If you’ve heard me talk about Vite in the past (and so commonly mispronouce it), you know I am a fan. With many Vue, React and SvelteKit applications are moving to Vite, I’ve been investigating how to integrate it for development and production into &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core applications. Let’s see what I found out.&lt;/p&gt;

&lt;p&gt;I also made a Coding Short video that covers this same topic, if you’d rather watch than read:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=8c73j7RHoSQ" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=8c73j7RHoSQ&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Short Intro to Vite
&lt;/h3&gt;

&lt;p&gt;Normally, we’ve used packagers (Webpack, Rollup) to at development-time to watch for changes and hot-swap or reload pages as necessary. For development time, approaches this differently. While Vite also does hot-swapping of code, but it approaches this with actually compiling the project. Instead it exposes a server for a project that relies on script modules.&lt;/p&gt;

&lt;p&gt;For example, to start a project, you need to just point at the entry file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body&amp;gt;
  &amp;lt;div id="app"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;script type="module" src="/src/main.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most modern browsers now support the script-type of module. In this case, Vite loads the main.js and then just follows imports and exports to load all the parts of the project that you need. This means that startup is incredibly fast since there really isn’t any compilation step.&lt;/p&gt;

&lt;p&gt;When you’re developing directly with Vite, you can just start it at the command-line and it will server the index.html as well as the script/resource files. Though Vite isn’t really a production ready web-server. The serving of the files is really to have a great development-time experience.&lt;/p&gt;

&lt;p&gt;For production time, it still compiles projects (by default with Rollup) in the same way that these frameworks have always done.&lt;/p&gt;

&lt;p&gt;With this different approach, integrating with &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core presents some challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating a Vite project for Production
&lt;/h3&gt;

&lt;p&gt;A little background: our project is a simple &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core project with a Vite project as a subdirectory called “Client”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufg4xadp968grx8ccihq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufg4xadp968grx8ccihq.jpg" alt="Figure 1" width="322" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we talk about how to get Vite working for development, let’s talk about how it will work when you publish your app for production (or other non-development builds).&lt;/p&gt;

&lt;p&gt;In a Vite project, you can use Vite to build your project by using the build command (shown here in a package.json file’s scripts):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vite uses Rollup (by default) to build and package your project for production. So we can configure Vite to output our project by modifying the vite.config.js file and adding a build configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    outDir: "../wwwroot/client",
    emptyOutDir: true
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;outDir&lt;/code&gt; is pointing at our wwwroot folder where the &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core project will have access to the build files. The &lt;code&gt;emptyOutDir&lt;/code&gt; is specifically to empty it before building so you don’t get any extra assets littering that folder.&lt;/p&gt;

&lt;p&gt;When we build the project, we get several files generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vite v4.0.4 building for production...
✓ 31 modules transformed.
../wwwroot/client/index.html 0.45 kB
../wwwroot/client/assets/index-ca646b5b.css 1.22 kB │ gzip: 0.48 kB
../wwwroot/client/assets/index-bdf9da80.js 77.78 kB │ gzip: 30.96 kB

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can just reference these files in the host page (a Razor page in this example):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page
@section Styles {
  &amp;lt;link rel="stylesheet" 
        href="/client/assets/index-ca646b5b.css"&amp;gt;
}
@section Scripts {
  &amp;lt;script src="/client/assets/index-bdf9da80.js"&amp;gt;
  &amp;lt;/script&amp;gt;
}
&amp;lt;h1&amp;gt;Film List&amp;lt;/h1&amp;gt;
&amp;lt;div id="app"&amp;gt;&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we’re also adding any markup (the &lt;code&gt;div#app&lt;/code&gt; in this example) that the Vite project needs.&lt;/p&gt;

&lt;p&gt;But we have a problem, the Vite build is giving a cache-busting name (the random string after &lt;code&gt;index-&lt;/code&gt;). On every build, this will change, so we can use a special tag helpers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@section Styles {
  &amp;lt;link rel="stylesheet" 
        asp-href-include="/client/assets/index-*.css"&amp;gt;
}
@section Scripts {
  &amp;lt;script asp-src-include="/client/assets/index-*.js"&amp;gt;
  &amp;lt;/script&amp;gt;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the &lt;code&gt;asp-href-include&lt;/code&gt; and &lt;code&gt;asp-src-include&lt;/code&gt; tag helpers, we can use a wildcard to include the right files for us.&lt;/p&gt;

&lt;p&gt;Lastly, we need to actually run the build. We can do this by just adding the build to the &lt;code&gt;.csproj&lt;/code&gt; file. By adding a Target for before publish, we can just execute the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Target Name='CompileClient' 
        BeforeTargets="Publish"&amp;gt; 
  &amp;lt;Exec WorkingDirectory="./client" 
        Command="npm install" /&amp;gt;
  &amp;lt;Exec WorkingDirectory="./client" 
        Command="npm run build" /&amp;gt;
&amp;lt;/Target&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we’re calling &lt;code&gt;npm install&lt;/code&gt; first to be sure that all the packages exist. And that we’re using the &lt;code&gt;WorkingDirectory&lt;/code&gt; to specify our &lt;code&gt;client&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Now, when you publish the project (manually or in a build script), the Vite project is built too!&lt;/p&gt;

&lt;p&gt;But we came to talk about development, let’s talk about that next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating Vite for Development
&lt;/h3&gt;

&lt;p&gt;Like we saw earlier, during development, you would run Vite and it would load scripts on demand using the &lt;code&gt;type=module&lt;/code&gt; method. When you run Vite in this mode, it is essentially running a server for the markup and a single, large SPA. If you’re creating APIs with &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core and just hosting your SPA as a single HTML file, this works perfectly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: There is a package called &lt;code&gt;Microsoft.AspNetCore.SpaServices.Extension&lt;/code&gt; that is meant to do this, but it is not well documented and may be depreciated by now. It didn’t work well with Vite, though it might for Angular and React using their CLIs&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But in many cases, you’ll want to host one or more SPAs on specific pages of your project. How do we handle this since both &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core and Vite will be serving files?&lt;/p&gt;

&lt;p&gt;During development you’ll want to run both servers, and just use the vite serving for the assets (.js/.css) for your project. To do this, let’s look at the Razor page again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page
@section Styles {
  &amp;lt;link rel="stylesheet" 
        asp-href-include="/client/assets/index-*.css"&amp;gt;
}
@section Scripts {
  &amp;lt;script asp-src-include="/client/assets/index-*.js"&amp;gt;
  &amp;lt;/script&amp;gt;
}
&amp;lt;h1&amp;gt;Film List&amp;lt;/h1&amp;gt;
&amp;lt;div id="app"&amp;gt;&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we want to do here is only use these styles and script tags during production, so we can surround it with an &lt;code&gt;environment&lt;/code&gt; tag for production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;environment include="Production"&amp;gt;
@section Styles {
  &amp;lt;link rel="stylesheet" 
        asp-href-include="/client/assets/index-*.css"&amp;gt;
}
@section Scripts {
  &amp;lt;script asp-src-include="/client/assets/index-*.js"&amp;gt;
  &amp;lt;/script&amp;gt;
}
&amp;lt;/environment&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will set it up to only use the build assets during production. We can then add an &lt;code&gt;environment&lt;/code&gt; tag for development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;environment include="Development"&amp;gt;
  &amp;lt;script type="module" 
          src="http://localhost:5000/src/main.js"&amp;gt;&amp;lt;/script&amp;gt;  
&amp;lt;/environment&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll notice that we’re using the Vite server to serve the main.js file. If you remember from earlier, this will load other assets on-demand and hot-swap them as necessary.&lt;/p&gt;

&lt;p&gt;In this way you get the best of both worlds. But we have a problem:&lt;/p&gt;

&lt;h3&gt;
  
  
  Dealing with Routing in Vite Projects
&lt;/h3&gt;

&lt;p&gt;In our example, we’re hosting the SPA on a page who’s URL is &lt;code&gt;http://localhost:8000/FilmList&lt;/code&gt;. This is related to the Razor page’s URL. But our Vite project (Vue in this case) is using history-type routing. That means, when it navigates, it takes over the URL. So when we navigate to our SPA’s home page, it changes it to &lt;code&gt;http://localhost:8000/&lt;/code&gt; and for the list page it changes the URL to &lt;code&gt;http://localhost:8000/films&lt;/code&gt; (which are based on the projects own routing, not server-side routing).&lt;/p&gt;

&lt;p&gt;The problem is if we refresh the page or open that URL, it fails because we’re not serving up our Razor page at those URLs. There are two fixes here. First, we need to tell the Vite project what the base address for our project is. We can do this in &lt;code&gt;vite.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base: "/FilmList",
  build: {
    outDir: "../wwwroot/client",
    emptyOutDir: true
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the addition of the &lt;code&gt;base&lt;/code&gt; property which let’s the app know what the base URL for the project is. In this way, the navigation will start at that base URL. This is better. But then our SPA’s route for the list of films is &lt;code&gt;http://localhost:8080/FilmList/films&lt;/code&gt;. But this isn’t a valid server-route either. We need a way to have inter-SPA URLs serve the SPA page (and the internal routing do the right thing).&lt;/p&gt;

&lt;p&gt;To do this, you can simply use fallback routes in the &lt;a href="http://asp.net/" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt; Core server. You’ll want to make sure that any fallbacks are specified after all your other routes (e.g. Razor Pages, Controllers and Minimal APIs). You to this by using the &lt;code&gt;MapFallback&lt;/code&gt; calls. For example, in our case (since we’re using Razor pages) we can use &lt;code&gt;MapFallbackToPage&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapGet("api/films", async (BechdelDataService ds, int? page, int? pageSize) =&amp;gt;
{
  //...
}).Produces&amp;lt;IEnumerable&amp;lt;Film&amp;gt;&amp;gt;(contentType: "application/json").Produces(404).ProducesProblem(500);

app.MapFallbackToPage("/FilmList");

app.Run();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, that this fallback is not redirecting, but just serving that page. That way the URL is preserved for the Vite project to use for it’s own routing.&lt;/p&gt;

&lt;p&gt;This will fallback to any page that isn’t found in routing to the FilmList Razor page that contains our SPA. That might be too broad though, you may want to use the fallback with a pattern too (so it only falls back to that page’s URLs) like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.MapFallbackToPage("/FilmList/{*path}", "/FilmList");

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first parameter of the &lt;code&gt;MapFallbackToPage&lt;/code&gt; allows you to specify a routing pattern to apply this fallback to. In this way, any urls that start with &lt;code&gt;/FilmList&lt;/code&gt; will just fallback to that page.&lt;/p&gt;

&lt;p&gt;I hope this helps some of you using Vite for your own projects. You can get the example for this project at:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/shawnwildermuth/codingshorts/tree/main/aspnetvite" rel="noopener noreferrer"&gt;https://github.com/shawnwildermuth/codingshorts/tree/main/aspnetvite&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m happy to answer any of your questions below if I’ve been unclear about any of this!&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aspnetcore</category>
      <category>javascript</category>
      <category>vite</category>
    </item>
    <item>
      <title>More on .NET 7 user-jwts Tool</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Tue, 10 Jan 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/more-on-net-7-user-jwts-tool-296</link>
      <guid>https://forem.com/shawnwildermuth/more-on-net-7-user-jwts-tool-296</guid>
      <description>&lt;p&gt;I recently released a Coding Short video and a blog post about the new JWT Tooling in .NET 7. It was received well, but I didn’t dig into some of the real details of what is happening. If you need to catch up, here is the blog post:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://wildermuth.com/2022/12/07/changes-in-jwt-bearer-tokens-in-dotnet-7/"&gt;Changes in JWT Bearer Tokens in .NET 7&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What I didn’t have a chance to explain is everything that the user-jwts tool actually does. It makes several changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds a section to the appsettings.developer.json file to add user-jwts as a valid issuer of JWTs.&lt;/li&gt;
&lt;li&gt;Adds secret key related properties to the user-secrets for the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it doesn’t do is wire up your startup to include JwtBearer authentication, it only sets up the tool as an issuer of the JWT. Let’s walk through this.&lt;/p&gt;

&lt;h3&gt;
  
  
  AppSettings.Developer.json
&lt;/h3&gt;

&lt;p&gt;The first step is it adds a new &lt;code&gt;Authentication&lt;/code&gt; section to the developer settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "Authentication": {
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "http://localhost:38015",
          "https://localhost:44384",
          "http://localhost:5241",
          "https://localhost:7254"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      }
    }
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It gets the valid audiences by looking at the &lt;code&gt;launchsettings.json&lt;/code&gt; (in the &lt;code&gt;Properties&lt;/code&gt; folder) of your project. The ValidIssuer is there to match the issuer of the JWT as configured in user settings (see next section for what I mean).&lt;/p&gt;

&lt;h3&gt;
  
  
  User Secrets
&lt;/h3&gt;

&lt;p&gt;In order to allow the JWT to be signed, it needs to have some security information. This information is in the &lt;code&gt;user-secrets&lt;/code&gt; file. If your project didn’t have support user-secrets yet, the tool adds the user-secret GUID to the project and then stores some information there. To see what they added, just list the secrets in this project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; dotnet user-secrets list

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, this returns the secret and valid issuer information (this is a throw-away project, so leaking this secret doesn’t matter):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication:Schemes:Bearer:SigningKeys:0:Value = R98yic+EGjR0asjN8eHe2nSLlhBB8tWcebIxHmcOSko=
Authentication:Schemes:Bearer:SigningKeys:0:Length = 32
Authentication:Schemes:Bearer:SigningKeys:0:Issuer = dotnet-user-jwts
Authentication:Schemes:Bearer:SigningKeys:0:Id = e1b964aa

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s interesting here, is that some of these defaults are configurable. By default, when the tool issues a JWT, it uses your machine name identification. If you don’t want that, you can simply override it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; dotnet user-jwts create -n shawn@aol.com

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even change the name of the Issuer with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; dotnet user-jwts create -n shawn@wildermuth.com --scheme YourIssuerName

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was able to use this information to just prototype issuing JWTs (via API) to just re-use the tools’ information. You can see here the GetSection matches the information in &lt;code&gt;user-secrets&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var bearer = _config.GetSection("Authentication:Schemes:Bearer");
if (bearer is not null)
{
  var uniqueKey = bearer.GetSection("SigningKeys")
    .Get&amp;lt;SymmetricSecurityKey[]&amp;gt;()?
    .First()
    .Key;
  var issuer = bearer["ValidIssuer"];
  var audiences = bearer.GetSection("ValidAudiences")
    .Get&amp;lt;string[]&amp;gt;();
  var key = new SymmetricSecurityKey(uniqueKey);
  var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope this answers some questions. Ping me below if you have questions!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1s4ZNDVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>aspnetcore</category>
      <category>authentication</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Changes in JWT Bearer Token Setup in .NET 7</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Wed, 07 Dec 2022 12:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/changes-in-jwt-bearer-token-setup-in-net-7-2n4i</link>
      <guid>https://forem.com/shawnwildermuth/changes-in-jwt-bearer-token-setup-in-net-7-2n4i</guid>
      <description>&lt;p&gt;If you’ve taken my &lt;a href="https://shawnl.ink/pscoreapi"&gt;“Building an API with ASP.NET Core”&lt;/a&gt; course over at Pluralsight, one of the more complicated tasks is to add support for JWT Bearer tokens. In .NET 7, they’ve simplified this quite a bit. Let’s take look.&lt;/p&gt;

&lt;p&gt;Instead of showing you how it used to work, let’s just talk about how to add JWT Bearer tokens to a new project. I started out with a simple Web API project (controller-based), though this technique is identical for gRPC or Minimal APIs. When we start out, authorization isn’t even enabled (unless you chose for it to scaffold authorization), but I’m going to assume that Program.cs looks similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// ...
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only hint about Authorization is the &lt;strong&gt;UseAuthorization&lt;/strong&gt; which is just the middleware to check for any Authentication Schemes that are added. You might also note that there is not a &lt;strong&gt;UseAuthentication&lt;/strong&gt; any longer. It is no longer necessary to include both.&lt;/p&gt;

&lt;p&gt;So let’s support JWT Bearer Tokens. First we still need to add the package to our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once added, we can wire up authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddAuthentication();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to note here is that you do not need to specify a default scheme any longer (the first scheme is assumed default). So we can call the &lt;strong&gt;AddJwtBearerToken&lt;/strong&gt; call that you might be used to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddAuthentication()
                .AddJwtBearer();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ordinarily, you would need to configure the token here but finally we have sensible defaults. We’ll get back to configuring it. But first, let’s head over to the Controller Action and add that magic &lt;strong&gt;Authorize&lt;/strong&gt; attribute (just like before):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if we open the API, we get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5l5vzd_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://wilderminds.blob.core.windows.net/img/2022/12/07/net7jwt-figure1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5l5vzd_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://wilderminds.blob.core.windows.net/img/2022/12/07/net7jwt-figure1.jpg" alt='Unauthorized"' width="755" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don’t worry, that’s what was supposed to happen!&lt;/p&gt;

&lt;p&gt;Since we setup JWT Bearer tokens, we should be able to just add a token to the request and it should work. But how do we get a token? Ah, another gem inside .NET 7: &lt;strong&gt;dotnet user-jwts&lt;/strong&gt;. The &lt;strong&gt;user-jwts&lt;/strong&gt; took is all about being able to look at a project and build a developer JWT from the configuration. Yes, this means you don’t have to build your API for returning tokens until you actually need to. To use it just call the create sub-command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;dotnet user-jwts create

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will spit out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Token: eyJhbGciOiJI...QpMdl0LRL7w1f1cnEu7dwJMvw4eSi1px56dneQ5tOQg

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No, this isn’t really my token. But you’ll see that it will paste out an entire JWT Bearer token that we can then use in the request testing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OeGIUuz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://wilderminds.blob.core.windows.net/img/2022/12/07/net7jwt-figure2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OeGIUuz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://wilderminds.blob.core.windows.net/img/2022/12/07/net7jwt-figure2.jpg" alt="Success" width="765" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last note, we can still configure the JWT Bearer token, but now we can use configuration like adults. In fact, the &lt;strong&gt;user-jwts&lt;/strong&gt; tool will add a section in your development &lt;strong&gt;appsettings.json&lt;/strong&gt; file the first time you create a JWT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "Authentication": {
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "http://localhost:64693",
          "https://localhost:44317",
          "http://localhost:5124",
          "https://localhost:7125"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      }
    }
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your exact settings will be a little different, but you can see that you can specify all the JWT settings here in configuration. Since this is in the &lt;strong&gt;appsettings.development.js&lt;/strong&gt; file, those tokens created by &lt;strong&gt;user-jwts&lt;/strong&gt; will never work in production as an added security gate (see how the &lt;strong&gt;ValidIssuer&lt;/strong&gt; is the &lt;strong&gt;user-jwts&lt;/strong&gt; tool). In fact, if we decode our JWT that it generated, we can see that it doesn’t have anything special except for machine user name which it uses as the unique id:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "unique_name": "shawn",
  "sub": "shawn",
  "jti": "be38d021",
  "aud": [
    "http://localhost:64693",
    "https://localhost:44317",
    "http://localhost:5124",
    "https://localhost:7125"
  ],
  "nbf": 1670459953,
  "exp": 1678235953,
  "iat": 1670459954,
  "iss": "dotnet-user-jwts"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of this should look familar! Let me know what you think!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1s4ZNDVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>jwt</category>
      <category>authentication</category>
    </item>
    <item>
      <title>C# 11 Strings in the Raw</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Sat, 26 Nov 2022 12:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/c-11-strings-in-the-raw-m5f</link>
      <guid>https://forem.com/shawnwildermuth/c-11-strings-in-the-raw-m5f</guid>
      <description>&lt;p&gt;With the release of C# 11, there is a new string in town. It might be getting crazy, but this new “Raw String Literals” is something interesting. Before we dig in, let’s have a refresher about strings:&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Strings
&lt;/h2&gt;

&lt;p&gt;Every language needs a type for storing text, that’s the &lt;strong&gt;String&lt;/strong&gt; class/ &lt;strong&gt;string&lt;/strong&gt; keyword. It’s what is used mainly in C# and has been there since day 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var text = "I thought we had literal strings";
WriteLine(text);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could use embedded quotes, but we needed to escape them (or other things like tabs, line breaks):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = "John \"Quincy\" Adams";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We didn’t have a good solution for multi-line, so we ended up with monstrosities (or using a &lt;strong&gt;StringBuilder&lt;/strong&gt; ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = "First Line\n";
text += "Second Line\n";
text += "Third Line";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  String Interpolation
&lt;/h2&gt;

&lt;p&gt;Some time, later C# introduced a way to have strings just use interpolation (instead of the dreaded &lt;strong&gt;string.Format(…)&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = $"This is an interpolated string: {someName} - {someName.Length}"; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dollar sign said that it should expect C# code inside brackets.&lt;/p&gt;

&lt;p&gt;But this introduced a need to double bracket if you needed a bracket in string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = $"This is an interpolated string: {{ {someName} }}"; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A compromise to support this better way of building strings. Of course, that made JSON in strings pretty ugly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = $"{{ \"name\": \"Shawn\" }}";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verbatim Strings
&lt;/h2&gt;

&lt;p&gt;In came Verbatim strings. This allowed you to have line breaks and look simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = @"This is a verbatim string.

This means you can have line breaks 
and use double ""'s to output quotes.";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While many things didn’t need to be escaped, you still needed something special for double-quotes. If you needed double-quotes you had to double them to get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is a verbatim string.

This means you can have line breaks
and use double "'s to output quotes.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not perfect, but worked in a lot of situations, but if you wanted to use a format like XML or JSON, it ended up with this ugliness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = @
{
  ""name"": ""Shawn"
}
";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verbatim Strings with Interpolation
&lt;/h2&gt;

&lt;p&gt;But you could mix verbatim and interpolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = $@"This is a verbatim 
interpolated string: {someName}";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worked, unless you needed brackets as text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Doesn't work, as it thinks that the whole thing is interpolated
text = $@"
{ 
  ""name"": ""{someName}"" 
}";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, now we need to double-quote as well as double curly-brace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Works
text = $@"
{{ 
  ""name"": ""{someName}"" 
}}";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hrmph…&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, Raw String Literals?
&lt;/h2&gt;

&lt;p&gt;Here’s where Raw String Literals come in. The idea is to allow anything between a set of delimiters. That delimiter is a triple-quote (yes, seriously, but it does make sense).&lt;/p&gt;

&lt;p&gt;When you triple-quote, everything is a literal, No magic here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = """This is pure text, which includes " and ' and other literals""";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but the rules are a tad different for multi-line, in that case the triple-quotes must be on their own lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = """
Everything between the quotes is literally interpreted, 
There is no need for escaping of anything.

Really!
  You can use "Whatever you Like"
""";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s important here is that the triple-quoted lines are not included in the string. The string starts on the first line after the triple-quote. This solves a lot of the messiness with commonly used things like JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = """
{
  "name": "Shawn"
}
""";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whew, that’s easy…almost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interpolated Raw String Literals?
&lt;/h2&gt;

&lt;p&gt;If you add interpolation to a raw string, you find an odd situation where the compiler must know what is an interpolated section (Raw String Literals assume &lt;em&gt;everything&lt;/em&gt; is just text). Like the other types of strings, you start interpolated strings with a dollar sign:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text = $"""&amp;lt;name&amp;gt;{someName}&amp;lt;/name&amp;gt;""";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, sure. But what if you need brackets?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Doesn't work, as it's expecting the brace
// to be part of the interpolation
text = $""" 
{
  "name": "{someName}"
}
""";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution? To do interpolation with brackets, the number of dollar-signs represents the number of brackets to indicate an interpolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Add number of $ for the depth of the braces needed
text = $$"""
{
  "name": "{{someName}}"
}
""";

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn’t a typo, this is valid C# 11. Solves a ton of situations, but still requires you to remember some stuff (I actually wish that had used the back-tick like JavaScript as it reads easier IMO).&lt;/p&gt;

&lt;p&gt;What do you think of new new syntax (and do you think you’ll be using it?) Tell me in the comments!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyni1qqta6cs71crnm8x9.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/" rel="noopener noreferrer"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com" rel="noopener noreferrer"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>New Videos: Coding Short and a Rant</title>
      <dc:creator>Shawn Wildermuth</dc:creator>
      <pubDate>Mon, 31 Oct 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/shawnwildermuth/new-videos-coding-short-and-a-rant-2bll</link>
      <guid>https://forem.com/shawnwildermuth/new-videos-coding-short-and-a-rant-2bll</guid>
      <description>&lt;p&gt;I can’t believe October is almost over! I forgot to post about a couple of videos I made this month. The first one is about new features in .NET 7 for Minimal APIs. The second one is a rant(ish) about support terms for Open Source projects (including .NET). Take a gander:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=8c73j7RHoSQ"&gt;https://www.youtube.com/watch?v=8c73j7RHoSQ&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=oR4dELwe57Q"&gt;https://www.youtube.com/watch?v=oR4dELwe57Q&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://shawnl.ink/yt"&gt;Subscribe to my YouTube Channel&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1s4ZNDVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/http://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png" alt="Creative Commons License" width="88" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This work by &lt;a href="http://wildermuth.com"&gt;Shawn Wildermuth&lt;/a&gt; is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/"&gt;Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
 Based on a work at &lt;a href="http://wildermuth.com"&gt;wildermuth.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you liked this article, see Shawn's courses on &lt;a href="http://shawnw.me/pscourses"&gt;Pluralsight&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>opensource</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
