Thursday, January 9, 2020

Add Logging to .NET Core Application

In this article, I will explain how to enable logging to the event log in a hosted .NET Core application (ASP.NET application).

First in the Program.cs file, add .ConfigureLogging to the CreateHostBuilder expression-bodied member.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging( logging =>
        {
            logging.ClearProviders();
            logging.AddEventLog(new Microsoft.Extensions.Logging.EventLog.EventLogSettings { SourceName = "Steves Application" });
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup();
        });


If you didn't do this, CreateDefaultBuilder would actually add some providers by default.  But since we want to use a custom source name, it is necessary to call ClearProviders and add our own explicitly.

Next, you need to make a change to your appSettings.json file.  Add an EventLog section like the following:

"Logging": {
  "LogLevel": {
    "Default": "Information",
    "Microsoft": "Warning",
    "Microsoft.Hosting.Lifetime": "Information"
  },
  "EventLog": {
    "LogLevel": {
      "AppName.Controllers.HomeController": "Information"
    }
  }
}

AppName.Controllers.HomeController is the fully qualified name of the class where you are logging from.  When you log to the event log in .NET Core, it assigns a category to the event.  It uses the fully qualified name of the class it is logging from as the category name.  By including this in the appSettings.json file, you are saying that you want any events with this category with a log level of Information or above to be logged.  By default, only events with a log level of Warning and above will be logged.  Since we do a lot of informational logging, it is necessary to override this default.

Now, all that is left to do it log.

You need to inject a ILogger object into the constructor of your class:

private readonly ILogger _logger;

public HomeController(ILogger<HomeController> logger)
{
    _logger = logger;
}

Then, it just a matter of calling the LogInformation or LogWarning method of the logger:

_logger.LogInformation("Testing");

Tuesday, March 26, 2019

Starting a New Sprint in TFS

This process is not intuitive and so difficult to remember, I have decided to document it here.  Let's say you have a sprint that is done.  Click the gear at the top of your project screen, and select Work.  You should see this:


This is followed by a list of your sprints.  Set the End Date of the most recent sprint to yesterday no matter when it was actually completed.  If this is all you did, this sprint would still not show up as the current sprint.  Click the "default team's settings."  Here you have to select the specific sprints that will be available to your team.  Now click "Project settings" to go back to where you were.  Now the sprint will show as your current iteration.


Wednesday, November 21, 2018

Prevent documents from opening in the browser from SharePoint 2013

I recently had a SharePoint document library that housed Excel files. The browser would try to open the file in a tab in the browser itself. However, an error would occur with the services that allow this to happen. So I decided to tell SharePoint that when a file is clicked on, open it using the client software if it is available. To do this, go to the library in question, and click Library Settings. Choose Advanced Settings and set "Opening Documents in the Browser" to "Open in the client application".

Friday, October 26, 2018

ASP.NET Prevent double-clicking of buttons

If you have a button that causes a record to be inserted into a table, you can sometimes run into duplicate records if the user happens to click the button twice (double-click).  This can be prevented by using javascript to disable the button as soon as the button is clicked the first time.  Use the following code:

<script>

    function disableButton() {
        document.getElementById("ID_OF_BUTTON").disabled = true;
    }

</script>


Then, use the OnClientClick property of the button to call this code:

<asp:Button ID="ID_OF_BUTTON" runat="server" Text="Click Me" OnClientClick="disableButton();" UseSubmitBehavior="false" />


NOTE: I have not used this on a form that has client validation, so I'm not sure how of if this would work in that situation.

Thursday, September 13, 2018

Serialize .NET object to JSON

Let's say you have following classes:

Public Class Output
    Public Property Query As QueryDetails
End Class

Public Class QueryDetails
    Public Property Count As Integer
    Public Property Created As DateTime
    Public Property Lang As String
End Class

And let's also say you have created an object and have assigned values as such:

Dim MyQueryDetails As New QueryDetails With {.Count = 1, .Created = Now, .Lang = "en"}
Dim MyData As New Output
MyData.Query = MyQueryDetails

To "serialize" the object as JSON use the following code.  You will need to add a reference to the JSON.net library located at https://www.newtonsoft.com/json.

Dim Results As String = Newtonsoft.Json.JsonConvert.SerializeObject(MyData)
Console.WriteLine(Results)
'{"Query":{"Count":1,"Created":"2018-09-13T10:26:13.2004198-05:00","Lang":"en"}}


Wednesday, September 12, 2018

Call a REST API from .NET

To call a REST API using the "GET" ("POST" is beyond the scope of this article) HTTP verb, use the following code:

Using Client As New System.Net.WebClient

    Dim Results As String =
        Client.DownloadString("API URL")

End Using

This will populate the Results variable with the output of the web service call.  Almost invariably, this will be in the JSON format.  Note that all input is contained in query parameters in the API URL.

Now we need to get the JSON into a .NET object that can be easily read.  This process is called deserialization.  You can do this using native .NET classes, but oddly, Microsoft seems to prefer that you use the JSON.net library.  This can be downloaded at https://www.newtonsoft.com/json.

Next you will need to create a series of classes that correspond to the structure of the JSON output.  For example, if your output JSON looks like this:

{"query":{
    "count":1,
    "created":"2018-09-07T15:51:40Z",
    "lang":"en-US"
    }
}

You should create two classes like this:

Public Class Output
    Public Property Query As QueryDetails
End Class

Public Class QueryDetails
    Public Property Count As Integer
    Public Property Created As DateTime
    Public Property Lang As String
End Class

Then, simply write the following code to deserialize the JSON output into the .NET Output object:

Dim MyOutput As New Output
Newtonsoft.Json.JsonConvert.PopulateObject(Results, MyOutput)

Thursday, August 9, 2018