• .Net,  c#

    Visual Studio and that Annoying Code Style

    Here were are long ago from my last post and what do I do?  Yes, complain about Visual Studio 2022 and MS removing yet again the only real coding style I… use?

    Yes, that thing one does when one creates a Constructor for a Class to set a private read only variable that is not “this.whatever” but using the camel case “_whatever”.
    Now I get it… it’s a style… not everyone like the _whatever variables when one does something like Dependency Injection… Ok I have no problem with that…

    The complaint here… is everything almost when MS releases yet another update to VS 2022- they reset my code style! Really!

    Anyway… a good post to explain how to put it back:

    Put the Style Back

     

  • Blazor

    The Error AspNetCore.Components.Forms Requires value for ‘ValueExpression’ on a Blazor Page

    What the hell is that?

    Let’s start with the full error throw from our Blazor Page:

    Microsoft.AspNetCore.Components.Forms.InputText requires a value for the ‘ValueExpression’ parameter. Normally this is provided automatically when using ‘bind-Value’.

    It’s here we see this in our little Blazor .Not 6 App:

    BlazorErr

    On our page we must have a @bind-Value that has gone off the tracks. Yes we do.

    Here’s the page Razor code in a EditForm – do you see the problem?

       <EditForm Model="hero" OnSubmit="HandleSubmit">
            <div>
                <label for="FirstName">First Name</label>
                <InputText id="FirstName" @bind-value ="hero.FirstName" class="form-control"></InputText>
            </div>
            <div>
                <label for="LastName">Last Name</label>
                <InputText id="LastName" @bind-Value="hero.LastName" class="form-control"></InputText>
            </div>
            <div>
                <label for="HeroName">Hero Name</label>
                <InputText id="HeroName" @bind-Value="hero.HeroName" class="form-control"></InputText>
            </div>
            <div>
                <label>Comic</label><br />
                <InputSelect @bind-Value="hero.ComicId" class="form-select">
                    @foreach (var comic in SuperHeroService.Comics)
                    {
                    <option value="@comic.Id">@comic.Name</option>
                    }
            </InputSelect>
        </div>
        <br />
        <button type="submit" class="btn btn-primary">@buttonText</button>
        <button type="button" class="btn btn-danger" @onclick="DeleteHero">Delete Hero</button>
    </EditForm>

     

    The Hint v3

    Look at that… Remembering that C# is a case sensitive language. The actual problem is that @bind-value is actually not a valid bind directive. Yes it is a small thing, but here it is… the real question WHY DOES THIS COMPILE WITHOUT AN ERROR? Or at least give you a “squiggle”. My goodness, you do anything slightly on the edge of not dealing with a potential NULL- and “squiggles” EVERYWHERE!! To the point of it being really annoying. But no squiggles for this actual serious error?

    Microsoft, please get your .Net 6 Blazor act together!

    ~SG

  • SQL Server

    SQLlocalDB – and How to add a latest version of a LocalDB instance

    For those that develop with a backend DB, localdb has always been a good ‘go to’ option. A Dev db hosted on a localDB instance provides a good base that is simple to move to Production. It also has a benefit of Migrations. (Yes, SQL Server is not the only DB engine to provide such, but we will talk about SQL Server here).

    LocalDB is a handy, for free, SQL instance that basically comes with VS installations (yes, now a days you do have to pick the correct workload).
    With that in mind, those of us that long ago installed the venerable LocalDB, we were often suck with older versions of the SQL instance.

    Well, not so much anymore does one have to work with a LocalDB based on 2012 (Yeah, one has been using Visual Studio for awhile).
    So what is the secret? Use the command line utility SQLlocalDB to create a new “more recent version” LocalDB instance. Yes, one can remove the older instances as well. Just remember, if you have databases that are still in use with other development, make sure you re-create those DB’s etc on your new instance. Now onto the secret sauce…

    SQLlocalDB Utility  The Microsoft page that gives full details on this SQL utility.

    From your favorite command line do a SQLlocalDB c <name of your instance>

    At this one will get a 15.0.4153.1 version of a SQL instance. Also, make note of SQLlocalDB i and SQLlocalDB s <instance name> and SQLlocalDB p <instance name>

    ~SG

  • .Net,  Microsoft

    Dotnet 6 API with a HttpDelete and that 405 Method not allowed error

    As we can tell from the title of the Post, we are going to talk about figuring out why in a client app one gets a Http Status code of 405 (Method Not Allowed).

    When does this happen? Usually when a http request does a  http PUT or DELETE. Yet, when one uses Swagger (openAPI) or Postman to directly call the same API Delete or Put, it works!  This is starting to feel like a CORS issue, right? Read On ==>

    So 405! Indeed looking at the surface of what is going on, one thinks Ah! CORS is at it again! Absolutely, this is what it feels like. After all, a Swagger/Postman GET/DELETE call under the same http domain works. But the moment one moves to a Client App coming in from a different domain (i.e. a different port on localhost, because different ports are also considered a different domain in terms of CORS), the Http PUT/DELETE stops working and throws a 405.

    We are using VS2022 with Dotnet 6.0.100-rc.2.21505.57 (so the latest VS2022 and Dotnet RC 6 as of the writing of this post)

    Wow… let’s step into how to rein in CORS…. We start in the API project in the Startup class.

    In Configure Services =>

    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder
            .AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod()
            .WithMethods("GET","PUT","DELETE","POST","PATCH") //not really necessary when AllowAnyMethods is used.
            );
    });
    

    We build a CORS policy  (yes one can remove the .WithMethods clause)

    And of course we add in the Configure method =>

    app.UseRouting();
    app.UseCors("CorsPolicy");

    And everything is right with the world… Let’s do a Delete in a client app. Meaning we are doing HttpClient Delete to a rest url that contains the id:

    Yeap a hard 405… What the what What?
    After digging through lots of readings on the topic of CORS 405 PUT/DELETE, DotNet 6 issues (with not much luck), I stepped upon the answer with a bit of thinking about the problem….

    In my Controller we have this as the delete method header =>

    [HttpDelete("id")]
    public async Task<IActionResult> Delete(int id)
    { ...

    Seems simple enough, it works in the Swagger interface for testing the API. I validated that the client is using and passing the correct url and id. WHAT!?

    Look closely at the [HttpDelete… tag. Notice anything? If one said, “Duh, ScottGeek- you need to wrap the “id” within {}” then YEAP!
    That would be the issue. The real question is why does this seem work in the Swagger UI for the api but not in a app using HttpClient?

    I have absolutely no idea why (yes I could get Fiddler out and start digging deep, nope) In this case what seems like a CORS acting up issue (405 on a cross domain request), yeah it’s not, or is it? This seems to be a bug somewhere, I suspect, in the OpenAPI (swagger) bits. Why in the OpenAPI? because it should reflect the same 405 when the API Method tag is not 100% correct.

    But let’s not just pick on OpenAPI. The fact that DotNet 6 allows both [HttpDelete(“id”)] and [HttpDelete(“{id}”)] without issuing some kind of build blowup or at least a green squiggle on the one that is in error… well I give it to ya… feels like a bug.

    Put the {} around the id and….

    Also, don’t forget to check one’s HttpPut as well…

    ~SG

  • Blazor,  Microsoft

    Blazor with dotnet watch run in the Pre-Dotnet 6 and VS 2022 days

    Oh, how we do wait for the release of dotnet 6 and most important VS 2022. Why? Well the promise of hot-reload without hoops to jump through.

    For the most part in VS 2019 16.10.4, “hot-reload” of a Blazor app is not too bad <= Circle that “not too bad”- it does actually work… mostly! Yes, I do refer to the “dotnet watch run”. It does detect changes in your Blazor files and reload the browser page… yeah, BUT it does have issues. Here comes the list….

    It doesn’t detect new files added… go ahead add a new razor page while your project is in “dotnet watch run” – nope it will not find it no matter how many times you hard refresh the browser. Not only razor pages, but new stylesheets- yeap, it’s not going to find those either!

    It has issues when you make too many complicated changes in your code. Yes compile errors that don’t go away.

    It interferes with an already “flaky” intellicode/intellisense… My goodness talking about annoying! Already half the time, bootstrap intellisense stops working on razor pages. And what the hell happened to code snippets? (Probably less about hot-reload than this version of VS being riddled with bugs!)

    Ok, I’m mostly over that now…. deep breath… 1…2…3…4… Alright.

    Let’s get to the point, the matter of always having to type in that “dotnet watch run”, stop it, and type it in again… what’s the point? Let’s create a launch profile so that we can tack this into VS (gee you think the Blazor Template should already have that? Yeap it should). Here we go:

     

    "Watch": {
          "commandName": "Executable",
          "launchBrowser": true,
          "launchUrl": "http://localhost:5000/",
          "commandLineArgs": "watch run",
          "workingDirectory": "$(ProjectDir)",
          "executablePath": "dotnet.exe",
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          }
        }

    In your launchSettings.Json file, place the code above in the “Profile” section…. Match sure this is in the “PROFILE” section!

    Now let the magic begin… well mostly… When you tap the “Watch” on the Build/Debug drop down… that lovely “dotnet watch run” will execute in a window… and now you to can experience the “buggy” hot-reload of a Blazor app. 😎
    ~SG

  • Microsoft,  SQL Server

    BCP and Clustered SQL Oh the Errors

    I got a curious message concerning problems that someone from work was having issues getting a relatively simple BCP (Bulk Copy for SQL) to work.

    So here we go:

    bcp "select top 5 [Data] from [ADataBase].[dbo].[ATable]  where [ProcessedTime] <= GetDate()-1 and MessageType=''SomeProduct'' order by [ProcessedTime] desc for xml raw, root(''MyexportRoot'')"' +
        ' QUERYOUT ""B:\BCPBatch\Data\sample.xml"" -T -c  -S TheSQL\Instance';
    

    It’s a little complicated… Basically pull data from a table in DB on a SQL Instance… and output as xml to an xml file.
    After spending, a few hours, getting all kinds of errors about drive not found, path not found, can’t open the file… bah bah bah. It’s like what the hell?!

    You take that statement and execute it on a console window or powershell window… and no problems, but you get into SSMS, and in a query window… and nothing but errors… So something like this:

    EXECUTE sp_configure 'show advanced options', 1;  
    GO  
    -- To update the currently configured value for advanced options.  
    RECONFIGURE;  
    GO  
    -- To enable the feature.  
    EXECUTE sp_configure 'xp_cmdshell', 1;  
    GO  
    -- To update the currently configured value for this feature.  
    RECONFIGURE;  
    GO  
    
      declare @cmd nvarchar(512);
    -- Please note that the fully qualified table name is needed
    select @cmd = 'bcp "select top 5 [Data] from [ADataBase].[dbo].[ATable] where [ProcessedTime] <= GetDate()-1 and MessageType=''SomeProduct'' order by [ProcessedTime] desc for xml raw, root(''MyexportRoot'')"' + ' QUERYOUT ""B:\BCPBatch\Data\sample.xml"" -T -c -S TheSQL\Instance';
    exec xp_cmdshell @cmd;
    go
    
    EXECUTE sp_configure 'xp_cmdshell', 0;  
    GO  
    -- To update the currently configured value for this feature.  
    RECONFIGURE;  
    GO  
    
    EXECUTE sp_configure 'show advanced options', 0;  
    GO  
    

    And let the errors happen… and they do. What’s the issue here… well nothing really with the code, but with the fact that my TheSql\Instance was in fact Clustered!

    So why is that a problem? It’s this part here:

    QUERYOUT “”B:\BCPBatch\Data\sample.xml””   – the syntax is correct, but on a clustered server file locations are problematic! Meaning, the cluster does not normally have full access to all of the drives. Now, will a network share work? Not sure. I didn’t test that.

    The solution I suggested was to move to another SQL instance that was not clustered, and the script worked.
    ~SG

     

  • Microsoft,  SQL Server

    A slight issue when one wants to install SQL 2019 Dev, etc The ODBC 17 SQL Driver

    On my way to getting the latest SQL Server installed on one of my Dev PC’s- I ran across the issue of getting prompt for:

    msoledbsql.msi

    What the hell…

    ODBC Driver 17 is what that is about. Apparently, the SQL installed is not smart enough to know that one already has ODBC 17 SQL Driver installed and runs into a major “cannot resolve” the problem. The end result is that one does not get the SQL instance installed…

    But after reading lots of “not really helping” blurbs from the Internet, the Solution is simple… well mostly.

    You have to uninstall the “Microsoft ODBC Driver 17 for SQL Server” – one can find it on windows 10 in the APPS & Features. Uninstall it and redo the SQL install. One should have better luck with moving forward with getting SQL installed…

    ~ScottGeek

  • Community Stand up Links

    More Blazor talk from the Community Stand up

    Links from the show.

    [visual-link-preview encoded=”eyJ0eXBlIjoiZXh0ZXJuYWwiLCJwb3N0IjowLCJwb3N0X2xhYmVsIjoiIiwidXJsIjoiaHR0cHM6Ly93d3cudGhldXJsaXN0LmNvbS9tYXJjaC05LWNvbW11bml0eS1saW5rcyIsImltYWdlX2lkIjotMSwiaW1hZ2VfdXJsIjoiaHR0cHM6Ly93d3cudGhldXJsaXN0LmNvbS9pbWFnZXMvbG9nby5wbmciLCJ0aXRsZSI6IlRoZSBVcmxpc3QgLSBDb250cmlidXRlIHRvIEJsYXpvciBMaW5rcyIsInN1bW1hcnkiOiJBU1AuTkVUIENvbW11bml0eSBTdGFuZHVwIC0gSG93IHRvIGNvbnRyaWJ1dGUgdG8gQmxhem9yIiwidGVtcGxhdGUiOiJ1c2VfZGVmYXVsdF9mcm9tX3NldHRpbmdzIn0=”]

  • Community Stand up Links

    Community links for .net Network API community standup

    [visual-link-preview encoded=”eyJ0eXBlIjoiZXh0ZXJuYWwiLCJwb3N0IjowLCJwb3N0X2xhYmVsIjoiIiwidXJsIjoiaHR0cHM6Ly93d3cudGhldXJsaXN0LmNvbS9hc3BuZXQtc3RhbmR1cC0yMDIxLTAyLTE2IiwiaW1hZ2VfaWQiOi0xLCJpbWFnZV91cmwiOiJodHRwczovL3d3dy50aGV1cmxpc3QuY29tL2ltYWdlcy9sb2dvLnBuZyIsInRpdGxlIjoiVGhlIFVybGlzdCAtIC5uZXQgbmV0d29yayBBUEkiLCJzdW1tYXJ5IjoiTGlua3MgZnJvbSBDb21tdW5pdHkgU3RhbmR1cCAyMDIxLTAyLTE2IiwidGVtcGxhdGUiOiJ1c2VfZGVmYXVsdF9mcm9tX3NldHRpbmdzIn0=”]

    And

    [visual-link-preview encoded=”eyJ0eXBlIjoiZXh0ZXJuYWwiLCJwb3N0IjowLCJwb3N0X2xhYmVsIjoiIiwidXJsIjoiaHR0cHM6Ly93d3cudGhldXJsaXN0LmNvbS9hc3BuZXQtc3RhbmR1cC0yMDIxLTAyLTIzIiwiaW1hZ2VfaWQiOi0xLCJpbWFnZV91cmwiOiJodHRwczovL3d3dy50aGV1cmxpc3QuY29tL2ltYWdlcy9sb2dvLnBuZyIsInRpdGxlIjoiVGhlIFVybGlzdCAtIFNoYXJlIHRoZSBpbnRlcm5ldCIsInN1bW1hcnkiOiJHcm91cCBsaW5rcyB0b2dldGhlciBpbiBhIGxpc3QgYW5kIGdldCBhIGN1c3RvbSBVUkwgdG8gc2hhcmUgdGhlbS4gRWRpdCB5b3VyIGxpc3RzIGF0IGFueSB0aW1lLiIsInRlbXBsYXRlIjoidXNlX2RlZmF1bHRfZnJvbV9zZXR0aW5ncyJ9″]