Accelerate time to insights with Azure Synapse Link for Dataverse

Josh Caplan, Sabin Nair, and Priyanka Langade join Scott Hanselman to show how you can use native Azure Synapse Analytical runtimes to analyze Dataverse data and get actionable insights.  Dataverse structures a variety of data and business logic to support interconnected applications and processes in a secure and compliant manner.  Azure Synapse Link for Dataverse is the fastest path to success for you to slice and dice large volumes of Dataverse data and run AI and ML on it. [0:00:00]– Intro[0:00:51]– Josh Caplan: Overview[0:03:20]– Sabin Nair: Dataverse and the Power Apps Portal[0:08:32]– Priyanka Langade: Azure Synapse Link for Dataverse[0:12:51]– Josh Caplan: Wrap-upAccelerate time to insight with Azure Synapse Link for DataverseWhat is Azure Synapse Link for Dataverse?Link a Microsoft Dataverse environment to Azure Synapse Analytics workspace and bring Dynamics 365 data to AzureCreate an Azure Synapse Link for Dataverse with your Azure Synapse Workspace (Preview)Microsoft Azure Synapse Link for Dataverse integration (YouTube)Create a free account (Azure)

Carter Community for ASP.NET Core means enjoyable Web APIs on the cutting edge

I blogged about the open source Carter Community Project in 2019. Let's check in and see what's going on today in 2021! The open source Carter Community Project adds opinionated elegance to ASP.NET Core routing With .NET 6 on the near horizon, one notes that Carter has a net6 branch. Per their website, this is the goal of the Carter framework: Carter is framework that is a thin layer of extension methods and functionality over ASP.NET Core allowing code to be more explicit and most importantly more enjoyable. As of today you can bring Carter into your .NET 6 projects like this:dotnet add package Carter --version 6.0.0-pre2And the .NET 6 samples are under active development! Let's bring it down with a clone, switch to the net6 branch and give it a go. Here's as simple Web API sample with Carter that returns a list of actors at localhost:5001/actorsusing Carter;using CarterSample.Features.Actors;using Microsoft.AspNetCore.Builder;using Microsoft.Extensions.DependencyInjection;var builder = WebApplication.CreateBuilder(args);builder.Services.AddSingleton<IActorProvider, ActorProvider>();builder.Services.AddCarter();var app = builder.Build();app.MapCarter();app.Run();Nice! This is using new .NET 6 features so there's no Main(), it's implied. The builder has an ActorProvider added as a Singleton. I bet we'll use that when we ask for /actors in our browser or favorite HTTP API client.public class ActorsModule : ICarterModule{ public void AddRoutes(IEndpointRouteBuilder app) { app.MapGet("/actors", (IActorProvider actorProvider, HttpResponse res) => { var people = actorProvider.Get(); return people; }); ... }}This is nice and clean. Everything is using Dependency Injection so no one is "newing up" an Actor. You'll note also that returning the Actors as JSON is implied when we return the IEmumerable<Actor> that comes from actorProvider.Get().In fact, the whole Actor Module is just 80 lines so I'll include it here:public class ActorsModule : ICarterModule{ public void AddRoutes(IEndpointRouteBuilder app) { app.MapGet("/actors", (IActorProvider actorProvider, HttpResponse res) => { var people = actorProvider.Get(); return people; }); app.MapGet("/actors/{id:int}", (int id, IActorProvider actorProvider, HttpResponse res) => { var person = actorProvider.Get(id); return res.Negotiate(person); }); app.MapPut("/actors/{id:int}", async (HttpRequest req, Actor actor, HttpResponse res) => { var result = req.Validate<Actor>(actor); if (!result.IsValid) { res.StatusCode = 422; await res.Negotiate(result.GetFormattedErrors()); return; } //Update the user in your database res.StatusCode = 204; }); app.MapPost("/actors", async (HttpContext ctx, Actor actor) => { var result = ctx.Request.Validate<Actor>(actor); if (!result.IsValid) { ctx.Response.StatusCode = 422; await ctx.Response.Negotiate(result.GetFormattedErrors()); return; } //Save the user in your database ctx.Response.StatusCode = 201; await ctx.Response.Negotiate(actor); }); app.MapDelete("/actors/{id:int}", (int id, IActorProvider actorProvider, HttpResponse res) => { actorProvider.Delete(id); return Results.StatusCode(204); }); app.MapGet("/actors/download", async (HttpResponse response) => { using (var video = new FileStream("earth.mp4", FileMode.Open)) //24406813 { await response.FromStream(video, "video/mp4"); } }); app.MapGet("/empty", () => Task.CompletedTask); app.MapGet("/actors/sample", () => Task.CompletedTask); app.MapPost("/actors/sample", () => Task.CompletedTask); app.MapGet("/nullable", () => Task.CompletedTask); }}Note the API example at /actors/download that shows how to return a file like an MP4. Nice and simple. This sample also includes thoughtful validation code with FluentValidation extension methods like ctx.Request.Validate().Carter is opinionated but surprisingly flexible. You can use two different routing APIs, or clean and performant Endpoint routing:this.Get("/", (req, res) => res.WriteAsync("There's no place like 127.0.0.1")).RequireAuthorization();It even supports OpenAPI out of the box! Carter has an active Slack as well as Templates you can add to make your next File | New Project easier!dotnet new -i CarterTemplateThe following template packages will be installed: CarterTemplateSuccess: CarterTemplate::5.2.0 installed the following templates:Template Name Short Name Language Tags--------------- ---------- -------- ------------------------------Carter Template carter [C#] Carter/Carter Template/NancyFXThere's a lot of great innovation happening in the .NET open source space right now. Carter is just one cool example. Go check out Carter on GitHub, give them a Star, try it out and get involved in open source!Sponsor: YugabyteDB is a distributed SQL database designed for resilience and scale. It is 100% open source, PostgreSQL-compatible, enterprise-grade, and runs across all clouds. Sign up and get a free t-shirt© 2021 Scott Hanselman. All rights reserved.     

Hanselminutes is Fresh Air for Developers and has over 800 episodes of fresh tech from fresh faces

Hey friends! I wanted remind you about my podcast! It's http://hanselminutes.com/ and just a few weeks ago I published my 800th episode! My first episode was in January of 2006 so that's over 15 years of shows. And, if I may be a little boastful for a moment, they are pretty darn good. Maybe the first 400 were a little rough but these last 400 have been ROCK SOLID. Just kidding. Seriously, though, this 30 minute long tech show has diverse topics and new faces you haven't heard on other podcasts. If you check out over 800 episodes here https://www.hanselminutes.com/episodes you can search by Title, Guest, OR search all the Transcripts! There's over 400 hours of shows and you can search for the topics you want. Subscribe with your favorite podcast app, the raw RSS is here. We're also available on basically every podcast app out there, including, but not limited to: iTunes Spotify Google Podcasts TuneIn iHeart Stitcher Player.FM Samsung Podcasts, and more! If you enjoy the show, the best thing you can do to help me is SPREAD THE WORD! Tell a friend, share and episode or favorite code, but above all GET FOLSK TO SUBSCRIBE. The world is littered with podcasts that gave up after 9 episodes. There's a ton of average talks shows that ramble on. I've worked really hard - at night, as this is not my day job! - to not only bring you the best guests, but to read their papers, books, and thesis, and ask the questions that YOU would have if you were here with me! Sometimes I even put the Hanselminutes Podcast on YouTube and the results are truly special and heartbreakingly emotional. Thanks for listening, and thanks for sharing! Sponsor: YugabyteDB is a distributed SQL database designed for resilience and scale. It is 100% open source, PostgreSQL-compatible, enterprise-grade, and runs across all clouds. Sign up and get a free t-shirt© 2021 Scott Hanselman. All rights reserved.     

An introduction to the unified Azure SDK

Connie Yau joins Scott Hanselman to demonstrate the advantages of using the new Azure SDK by comparing rewrites of the same application, one using the legacy library and the other using the unified Azure SDK. In this example, Connie uses the Azure SDK for Java.[0:00:00]– Introduction[0:01:45]– Cloud Clipboard sample app[0:03:07]– Adding authentication[0:06:02]– Common Azure core functions (pagination, logging, etc.)[0:07:51]– How it started vs. how it's going[0:08:54]– Idiomatic design principle[0:10:05]– Wrap-upDownload the Azure SDKAzure SDK for Java on GitHubAzure SDK code samplesAzure SDK design guidelinesConnie's Cloud Clipboard sample on GitHubCreate a free account (Azure)

Enable Zero Trust with Azure AD PIM and Azure Lighthouse

Azure AD Privileged Identity Management integration in Azure Lighthouse is now in public preview.  Meagan Olsen and Saif Kayani show Scott Hanselman how partners can now use just-in-time access permissions, combined with MFA, to securely deliver secure managed services.[0:00:00]– Introduction[0:00:43]– Overview with Meagan Olsen[0:04:50]– Demo with Saif Kayani[0:17:55]– Wrap-upCreate eligible authorizationsUse Azure Lighthouse with your managed service businessAzure Lighthouse overviewAzure Lighthouse on Azure FridayCreate a free account (Azure)

Exploring a minimal Web API with ASP.NET Core 6

I write about minimal Web APIs in 2016 and my goal has always been for "dotnet server.cs" to allow for a single file simple Web API. Fast forward to 2021 and there's some great work happening again in the minimal API space! Let's do a 'dotnet new web' with the current .NET 6 preview. I'm on .NET 6 preview 7. As mentioned in the blog: We updated .NET SDK templates to use the latest C# language features and patterns. We hadn’t revisited the templates in terms of new language features in a while. It was time to do that and we’ll ensure that the templates use new and modern features going forward. The following language features are used in the new templates: Top-level statements async Main Global using directives (via SDK driven defaults) File-scoped namespaces Target-typed new expressions Nullable reference types This is pretty cool. Perhaps initially a bit of a shock, but this a major version and a lot of work is being done to make C# and .NET more welcoming. All your favorite things are still there and will still work but we want to explore what can be done in this new space. Richard puts the reasoning very well: The templates are a much lower risk pivot point, where we’re able to set what the new “good default model” is for new code without nearly as much downstream consequence. By enabling these features via project templates, we’re getting the best of both worlds: new code starts with these features enabled but existing code isn’t impacted when you upgrade. This means you'll see new things when you make something totally new from scratch but your existing stuff will mostly work just fine. I haven't had any trouble with my sites. Let's look at a super basic hello world that returns text/plain:var builder = WebApplication.CreateBuilder(args);var app = builder.Build();if (app.Environment.IsDevelopment()){ app.UseDeveloperExceptionPage(); }app.MapGet("/", () => "Hello World!");app.Run();Slick. Note that I made line 3 (which is optional) just be one line to be terse. Not needed, just trying on these new shoes.If we make this do more and support MVC, it's just a little larger. I could add in app.MapRazorPages() if I wanted instead of MapControllerRoute, which is what I use on my podcast site.var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllersWithViews();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){ app.UseDeveloperExceptionPage();}else{ app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");app.Run();Back to the original Web API one. I can add Open API support by adding a reference to Swashbuckle.AspNetCore and then adding just a few lines:var builder = WebApplication.CreateBuilder(args);builder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();var app = builder.Build();if (app.Environment.IsDevelopment()){ app.UseDeveloperExceptionPage();}app.UseSwagger();app.MapGet("/", () => "Hello World!");app.UseSwaggerUI();app.Run();Then I hit https://localhost:5001/swagger and I get the SwaggerUI and a little WebAPI Tester:Anuraj has a great blog where he goes deeper and pokes around David Fowlers GitHub and creates a minimal WebAPI with Entity Framework and an in-memory database with full OpenAPI support. He put the source at at https://github.com/anuraj/MinimalApi so check that out.Bipin Joshi did a post also earlier in June and explored in a bit more detail how to hook up to real data and noted how easy it was to return entities with JSON output as the default. For example:app.UseEndpoints(endpoints => { endpoints.MapGet("/api/employees",([FromServices] AppDbContext db) => { return db.Employees.ToList(); });...snip...}That's it! Very clean. Dave Brock did a tour as well and did Hello World in just three lines, but of course, you'll note he used WebApplication.Create while you'll want to use a Builder as seen above for real work.var app = WebApplication.Create(args);app.MapGet("/", () => "Hello World!");await app.RunAsync();Dave does point out how nice it is to work with simple models using the C# record keyword which removes a LOT of boilerplate cruft. Check this out!var app = WebApplication.Create(args);app.MapGet("/person", () => new Person("Scott", "Hanselman"));await app.RunAsync(); public record Person(string FirstName, string LastName);That's it, and if you hit /person you'll get back a nice JSON WebAPI with this result:{ firstName: "Scott", lastName: "Hanselman"}Dig even deeper by checking out Maria Naggaga's presentation in June that's on YouTube where she talks about the thinking and research behind Minimal APIs and shows off more complex apps. Maria also did another great talk in the same vein for the Microsoft Reactor so check that out as well.Is this just about number of lines of code? Have we moved your cheese? Will these scale to production? This is about enabling the creation of APIs that encapsulate best practices but can give you the "middleware-like" performance with the clarity and flexibility that was previous available with all the ceremony of MVC.Here's some more resources:David Fowler's GitHub demo https://github.com/davidfowl/dotnet6minimalapi/tree/main/Dotnet6_Minimal_APIA ToDo API as a Minimal API https://github.com/davidfowl/CommunityStandUpMinimalAPIExploring what Integration Testing looks like in a .NET 6 world by Martin Costello https://github.com/martincostello/dotnet-minimal-api-integration-testing I'll be exploring Martin's codebase next!Have fun! Lots of cool things happening this year, even in the middle of the panini. Stay safe, friends.Sponsor: Pluralsight helps teams build better tech skills through expert-led, hands-on practice and clear development paths. For a limited time, get 50% off your first month and start building stronger skills.© 2021 Scott Hanselman. All rights reserved.     

Stringly Typed vs Strongly Typed

I used to call this technique "type tunnelling" and noted its use in XML in 2005. When you are using a strongly typed language but instead your types are stringly typed, you are passing strings around when a better type exists. Here's some examples of stringly typed method calls:Robot.Move("1","2"); //Should be int like 1 and 2Dog.InvokeMethod("Bark"); //Dispatching a method passing in a string that is the method's name. Dog.Bark()Message.Push("TransactionCompleted"); Could be an enum There's reasons to do each of these things, but as a general rule your sense of Code Smell should light up if you smell Stringly Typed things.Inline SQL is another where one language (a proper language with Syntax) is tunneled as a string within another. There's no good solution for this as most languages don't have a way to express SQL such that a compiler could noticed a problem. Sometimes we'll see Fluent APIs like LINQ try to solve this. RegEx is another example of a string language within a language. Sometimes one will see large switch statements that fundamentally change program flow via "magic strings." One misspelling and your switch case will never fire.Again, these have valid reasons for existence but you won't catch syntax issues until runtime.LinqPad has a great post on why strongly typed SQL via LINQ or other fluent syntaxes are often better than SQL. Here's some LINQ in C# that will eventually turn into SQL. You get autocomplete and syntax warnings throughout the authoring process:from p in db.Purchaseswhere p.Customer.Address.State == "WA" || p.Customer == nullwhere p.PurchaseItems.Sum (pi => pi.SaleAmount) > 1000select pSo why does it matter?Regex rx = new Regex(@"b(?<word>w+)s+(k<word>)b");This isn't to say all Stringly Typed code is bad. It's to say that you need to make sure it doesn't just happen on its own. Be prepared to justify WHY it was written that way. Is string the only data type the app uses? Are there potential uses where something should be a Message or an Event or a Something and it was just easier or simpler to use a string? And here's the rub - was this Stringly Typed data structure pass to another component or service? Did you intend for its semantic meaning to be retained across this logical (or physical) boundary?A great litmus test is "how would I catch a misspelling?" Compiler" Unit Test? Production ticket?What do you think about Stringly Typed code? Do we type Name and Surname? Is that too far? Do we string all the things?Sponsor: Pluralsight helps teams build better tech skills through expert-led, hands-on practice and clear development paths. For a limited time, get 50% off your first month and start building stronger skills.© 2021 Scott Hanselman. All rights reserved.