“In this article, we will extensively break down the concept of Nullable types in C#. We will discuss the kinds of Nullable types in C#, their characteristics, and how we can use them when building applications...”
“.NET 7 was freshly released but Microsoft does not sleep. .NET 8 is already in the making and I want to showcase to you one new area where the dotnet team is working on Frozen collections…”
A new nuget account has been created for publishing nuget packages. As of now there are no published packages yet. Sitemap Generator package can be expected soon. I do have some plans of NLog logger packages but cannot confirm yet. The URL of the nuget package repository is: https://www.nuget.org/profiles/ALightTechnologyAndServicesLimited.
Canceling abandoned requests in ASP.NET Core – Blog article on how to stop processing of abandoned requests in ASP.Net MVC i.e if a browser loads a page but clicks stop or presses escape key. This way, some server-side resources can be saved.
Two of my favorite and absolutely free desktop based (downloadable) software for diagrams – cloud architecture, UML, Database ER etc… Very useful for small startups and developers.
As a knowledge worker, I.T developer I have a need to stay up to date with the latest technologies. Similarly millions of I.T developers. I cannot cater to the needs of every knowledge workers or I.T developers but for .Net developers, I am planning to post recommended reads every day. The daily recommended reads would be posted almost every day. The links would be for 3rd party blog posts. The topics would be more about I.T computing, cloud computing, .Net, web development etc…
I have explained sitemaps in an earlier blog post – Sitemaps an intro! In this blog post we would look at some code snippets for generating XML sitemaps. Two approaches are mentioned. This blog post is about sample code snippets. Read the comments in the code.
I might consider creating a small library for generating XML sitemaps and open sourcing the library.
The general structure of a valid XML document contains a XML declaration i.e the <?xml….>. Then there would be one and exactly one root node and the root node would contain other child nodes.
With XML sitemap, we would have the XML declaration, the <urlset> root node. The <urlset> root node would have one or more <url> child nodes upto a maximum of 50,000. The <url> node would have one and only one mandatory <loc> node. The <lastmod>, <changefreq>, <priority> are optional. If the optional <lastmod>, <changefreq>, <priority> nodes are present, there can be a maximum of one child node per <url> node.
Business logic validations would be:
The <url> nodes can be between 1 and 50,000.
Unique URL’s
<loc> is mandatory and the value must be a valid http or https URL.
If present, <lastmod> must be in valid w3c format, there can be 0 or 1 <lastmod> per <url> node.
<changefreq> can be 0 or 1 per <url> node and must be one of the following:
always
hourly
daily
weekly
monthly
yearly
never
<priority> can be 0 or 1 per <url> node and must be a valid number between 0 and 1 such as 0.1 or 0.2 etc…
Approach – 1:
In the following code snippets we would not be dealing with the business logic. This is for purely creating.
XmlDocument xmlDoc = new XmlDocument();
var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
xmlDoc.AppendChild(declaration);
XmlNode urlSet = xmlDoc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
var url = xmlDoc.CreateElement("url");
var loc = xmlDoc.CreateElement("loc");
loc.InnerText = "https://www.google.com";
url.AppendChild(loc);
var lastMod = xmlDoc.CreateElement("lastmod");
lastMod.InnerText = $"{DateTime.UtcNow.ToString("s")}Z";
url.AppendChild(lastMod);
urlSet.AppendChild(url);
xmlDoc.AppendChild(urlSet);
// Append more <url> nodes.
// Move the logic of generating url nodes into a separate method, call the method repetitively, apply business logic etc...
xmlDoc.Save(@"C:\temp\sitemap.xml");
Approach – 2:
In this also we won’t be applying business logic, this is a sample code snippet.
UrlSet.cs
[XmlRoot(ElementName = "urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class Urlset
{
[XmlElement(ElementName = "url", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public List<Url> Url { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
public Urlset()
{
Xmlns= "http://www.sitemaps.org/schemas/sitemap/0.9";
Url = new List<Url>();
}
}
Url.cs
public class Url
{
[XmlElement(ElementName = "loc", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public string Loc { get; set; }
[XmlElement(ElementName = "lastmod", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public string Lastmod { get; set; }
[XmlElement(ElementName = "changefreq", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public string Changefreq { get; set; }
[XmlElement(ElementName = "priority", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public double Priority { get; set; }
public Url()
{
Lastmod = DateTime.Now.ToLongDateString();
Priority = 0.5;
Changefreq = "Never";
}
}
// Generation
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
//Adding an empty namespace
ns.Add("", "");
var urlSet = new Urlset();
urlSet.Url.Add(new Url { Loc = "https://www.sample.com" });
urlSet.Url.Add(new Url { Loc = "https://www.sample.com/page1" });
XmlSerializer serializer = new XmlSerializer(typeof(Urlset));
string utf8;
using (StringWriter writer = new Utf8StringWriter())
{
serializer.Serialize(writer, urlSet, ns);
utf8 = writer.ToString();
Console.WriteLine(utf8);
}
// DeSerialization - useful for modifications and deletions
XmlSerializer serializer = new XmlSerializer(typeof(Urlset));
var deserializedUrlSet = serialization.Deserialize(new StringReader(utf8));
// Here utf8 is a string with the xml, refer to the overloads of Deserialize for other ways of passing XML
Several search engines support sitemaps. Sitemaps are either xml documents or plain text files that contain a list of URL’s that need to be indexed by search engines. The text file version is simple and straight-forward. I will discuss both the text and xml versions.
Text:
A simple text file that contains one URL per line.
Year: YYYY (eg 1997) Year and month: YYYY-MM (eg 1997-07) Complete date: YYYY-MM-DD (eg 1997-07-16) Complete date plus hours and minutes: YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) Complete date plus hours, minutes and seconds: YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) Complete date plus hours, minutes, seconds and a decimal fraction of a second YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) where:
YYYY = four-digit year
MM = two-digit month (01=January, etc.)
DD = two-digit day of month (01 through 31)
hh = two digits of hour (00 through 23) (am/pm NOT allowed)
mm = two digits of minute (00 through 59)
ss = two digits of second (00 through 59)
s = one or more digits representing a decimal fraction of a second
TZD = time zone designator (Z or +hh:mm or -hh:mm)
changefreq – This value is optional and needs to be between 0 and 1.0. The default value is 0.5.
There are some restrictions on the number of entries and size. The maximum number of URL’s per file is 50,000 and the maximum size is 50 Mb (uncompressed).
I am planning to provide some C# code snippets for generating XML sitemaps in the next few days. I had some code and generated sitemaps for the alpha version of PodDB, but now I am kind of integrating into the application i.e now the codebase would handle every update, removal, addition, planned for version 0.2.3 (New Year’s release).
As part of implementing NIST Cyber Security Framework at ALight Technology And Services Limited, one of the important thing to audit / log was database server. I am currently ingesting some logs into CloudWatch. In a blog post / youtube video in the future, I would show how to ingest logs into CloudWatch.
As a one person I do multiple things, now, I digged into some DBA work 🙂
This blog post is about writing audit log for MariaDB. In this blog post MariaDB Audit Plugin would be enabled and configured.
Update conf file, usually /etc/mysql/mariadb.cnf on Ubuntu, but could be different. Add the following lines under [mysqld]:
[mariadb]
plugin_load_add = server_audit
server_audit=FORCE_PLUS_PERMANENT
server_audit_file_path=/var/log/mysql/mariadb-audit.log # path to the audit log
server_audit_logging=ON
server_audit_events = 'CONNECT,QUERY,TABLE'
server_audit_file_rotate_size=1000000 # in bytes
server_audit_file_rotations=10
That’s all. The variables are pretty much self-explanatory. There are few more variables that can be used. Here is a link explaining the variables: Audit Plugin Options.
plugin_load_add – loads the plugin.
server_audit – we want the plugin to be permanently activated.
server_audit_file_path – Path to the file.
server_audit_logging – ON – we want the logging to happen
server_audit_events – We are logging connection requests, queries including failed queries and the affected tables.
server_audit_file_rotate_size – Max file for log before generating new file.
server_audit_file_rotations – Number of older files to hold before deleting.
There is an option for writing into syslog, by settingserver_audit_logging = ‘syslog’ but that’s beyond the scope of current blog post and I would prefer having a seperate file instead of getting sql log mixed into syslog – Personal preference.
This blog post is about some monitoring and alerting tips for AWS workloads.
AWS Console Logins – Root or IAM user
SSH into an EC2 instance
The above mentioned are considered primary. In addition the following monitoring are necessary:
3. What actions were performed by users and/or AWS such as launching EC2 instances (manual or autoscaling) or configuring Route53 or Security Groups etc…
4. Web logs, Load Balancer logs, Cloudfront logs in rare cases of DDOS attacks by the baddies.
5. Application logs
6. Database logs
7. System logs
In the next few weeks, I would be writing or even live videos / tutorials on how to monitor and alert for 1, 2 and 3. Some of these are based on using existing systems and in some cases, I would show manual and programmatic (C# preferred language of choice) approaches.
I would also share some blog posts on how to ingest logs into AWS Cloudwatch (5 GB ingestion free and some other costs) and Grafana (50GB ingestion free), discuss advantages and disadvantages of both.
As part of implementing NIST cyber security framework at ALight Technology And Services Limited, I am implementing these. I like sharing my knowledge with others as I come across new things, learn new things, even existing knowledge when appropriate, sometimes a blend of existing knowledge and new things.
While I have been brainstorming about something, some small idea came to my mind. People who would read this blog post would either call me stooooopid or might say nice idea.
Anyway the point is, we use logging for various purposes – mostly for troubleshooting. Very verbose logs are a nightmare in terms of performance, storage, retrieval and digging through for the right information. Sometimes, issues troubleshooting becomes a pain because of inadequate information in logs.
What if we log Info and above under normal circumstances, trace and / or debug in certain conditions such as unexpected expectations or errors?
Here is a brief overview of how this might be implemented – in this case, there is a slight memory pressure.
Collect trace and / or debug into Memory log i.e for example if using NLog, use Memory target.
Have some static method that writes the logs from Memory target into a different log target such as File / Database etc…
In the specific conditions such as exception call the static method and in ASP.Net even implement a exception filter to perform the same.
This might be a win-win scenario i.e collecting detailed information in case of unexpected exceptions and error, for any other normal scenario normal logging. Because memory target is being used, very small performance hit, slightly higher memory usage are the drawbacks.
I would love to know how other developers are implementing or handling such use cases.
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept All”, you consent to the use of ALL the cookies. However, you may visit "Cookie Settings" to provide a controlled consent.
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
Cookie
Duration
Description
cookielawinfo-checkbox-advertisement
1 year
Set by the GDPR Cookie Consent plugin, this cookie is used to record the user consent for the cookies in the "Advertisement" category .
cookielawinfo-checkbox-analytics
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional
11 months
The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance
11 months
This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy
11 months
The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.