Access data with managed identity – Azure App Service

This post is about connecting and accessing data from SQL Service using Azure App Service Managed Identity feature. Azure SQL supports Azure AD authentication, which means it also supports the Managed Identity feature of Azure AD. With Managed Identity, we no longer need the User Id and Password as part of your connection string. The credential is managed automatically by Azure and allows us to connect to resources.

First you need to create the SQL Server and SQL Database with SQL Server authentication. Once it is done, you can create Azure App Service. And then you need to enable identity in the app service. You can do this from Identity menu of the App Service. Right now I am using System Assigned – A system assigned managed identity is restricted to one per resource and is tied to the lifecycle of this resource. You can grant permissions to the managed identity by using Azure role-based access control (Azure RBAC). The managed identity is authenticated with Azure AD, so you don’t have to store any credentials in code. Once you enable the Identity, you will get an Object Id.

Next you can configure the Identity to your SQL Server. To do this, select the SQL Server and select the Azure Active Directory option.

By default there won’t be any users, you can click on the set admin option and from the Azure Active Directory user list, search for the Object Id – which from the App Service. And then click Select button and select the user as Azure Active Directory admin for the Sql Server.

Next you need to configure some permissions for the web app to the database. You can connect with Sql Server Management Studio or the query editor in Azure Portal and execute following code.

ALTER ROLE db_datareader ADD MEMBER [appservicename];
ALTER ROLE db_datawriter ADD MEMBER [appservicename];
ALTER ROLE db_ddladmin ADD MEMBER [appservicename];

And finally you can modify the code in your database context like this.

public class MyDatabaseContext : DbContext
{
public MyDatabaseContext(DbContextOptions<MyDatabaseContext> options)
: base(options)
{
var connection = (Microsoft.Data.SqlClient.SqlConnection)Database.GetDbConnection();
var credential = new DefaultAzureCredential();
var token = credential
.GetToken(new Azure.Core.TokenRequestContext(
new[] { “https://database.windows.net/.default” }));
connection.AccessToken = token.Token;
}

public DbSet<Todo> Todo { get; set; }
}

Now you’re done with the configuration. You can modify the connection string like this – remove the User Id and Password.

Using Managed Identities you can connect to SQL Server without configuring the user name and password which helps you to improve your application security and management of credential management can be avoided.

Happy Programming 🙂

Dew Drop – November 5, 2021 (#3553)

Top Links

Introducing the .NET Tech Community Forums (James Montemagno)

Why Evolve to .NET MAUI? (Sam Basu)

Visual Studio Code October 2021 (VS Code Team)

OneAPI/L0, OpenVINO and OpenCL coming to the Windows Subsystem for Linux for Intel GPUs (Steve Pronovost)

What’s New in C# 10? | One Dev Question (Kathleen Dollard)

Web & Cloud Development

Getting Started With jQuery – Advanced Ajax (Ian Elliot)

Build and Debug ASP.NET MVC 5 Framework Web Application 4.x in VS Code (Johan Danforth)

Microsoft Publishes New Documentation for Blazor, ASP.NET Core (David Ramel)

What’s New in Angular 13 (Alyssa Nicoll)

Introducing Svelte, and Comparing Svelte with React and Vue (Chris Coyier)

WebStorm 2021.3 Beta (Ekaterina Ryabukha)

GraphQL On The Front-End (React and Apollo) (David Atanda)

Implementing a Sidecar Pattern Without Kubernetes (Paul Michaels)

Pulumi Recommended Patterns: The basics (Aurélien Requiem)

Sendinblue Launches Email API (ProgrammableWeb)

GoLand 2021.3 Goes Beta! (Sergey Kozlovskiy)

WinUI, .NET MAUI & XAML

Xamarin.iOS – How to save Device Token as NSData type (Almir Vuk)

Consolonia UI – TUI (Text User Interface) (GUI Framework) implementation for Avalonia UI (Evgeny Gorbovoy & Wieslaw Šoltés)

Visual Studio & .NET

A quick review of C# 10 new language features (Thomas Levesque)

Caller Argument Expressions – A Look at New Language Features in C# 10 (Matthias Koch)

Using The Roslyn C# Compiler (Munib Butt)

Discovering new C# String Pattern Matching Features (Rick Strahl)

Breaking changes in .NET 6 (Note: This article is a work-in-progress) (.NET Team)

String Performance: Combining Strings with the StringBuilder (David McCarter)

Design, Methodology & Testing

Creating an Agile Transformation Roadmap (Brian Cottmeyer)

How to set up your Sketch Workspace for teams — the definitive guide (Sketch Team)

Trustworthiness is a feature (Eric Sink)

Parameterized Tests In xUnit WebDriver Part 4 (Anton Angelov)

How Mob Programming Collective Habits Can be the Soil for Growing Technical Quality (Ben Linders)

10 GitHub Actions resources to bookmark from the basics to CI/CD (Brian Douglas)

How To Improve UX With Sketching (Nancy Young)

Are Canary Releases an Alternative to Testers? (Vaishali Desarda)

The Future Of Work Is Asynchronous—And These Companies Are Leading The Way (Amy Rigby)

Mobile, IoT & Game Development

Microsoft finally brings Android apps to Windows 11 Dev Channel Insiders (Arif Bacchus)

The Raspberry Pi Build HAT and LEGO® components at our CoderDojo (Mark Calleja)

Podcasts, Screencasts & Videos

CppCast – Visual Studio 2022 with Sy Brand (Rob Irving)

.NET Core Podcast – Real-World Blazor with Steve Peirce (Jamie Taylor)

The Stack Overflow Podcast 390: Web3 won’t save us (Ben Popper)

Smashing Podcast Episode 43 With Matthew Phillips: What Is Astro? (Drew McLellan)

Hanselminutes – Climbing high while staying grounded with Annyce Davis (Scott Hanselman)

Software Engineering Daily – Angular Dev Tools with Minko Gechev (Jeff Meyerson)

Get Those Good Reviews for Your Xamarin App with Store Review Plugin (Gerald Versluis)

Reusable Controls and Data Template Selectors in Xamarin.Forms & .NET MAUI (James Montemagno)

How VS Code Can Keep You From Making Coding Mistakes in Angular – Adventures in Angular 331 (Charles Max Wood)

How can I make my Blazor WebAssembly apps run fast? | One Dev Question (Daniel Roth)

Yet Another Podcast – Visual Studio 2022!! (with Mads Kristensen) (Jesse Liberty)

Introduction to SQL Server 2022 (Ep.1) | Data Exposed (Anna Hoffman & Bob Ward)

DAWbench Radio Show Episode 13 : The Art of Analog Modeling : Softube : Tubes & Transistors to Digital Artistry ! (Vin Curigliano & Pete Brown)

Rocket 358: Anna Delvey’s Crypto Corner (Christina Warren, Brianna Wu & Simone De Rochefort)

Who is using .NET? | One Dev Question (Immo Landwerth)

Talk Python to Me #339: Making Python Faster with Guido and Mark (Michael Kennedy)

UX Podcast #275 – VR in Healthcare with Almira Osmanovic Thunström (James Royal-Lawson & Per Axbom)

Community & Events

Addressing the Rumors that I Have Been Removed from the MVP Program (Kendra Little)

GitHub Announces Improvements At Universe 2021 (Kay Ewbank)

Microsoft Ignite 2021 now all up for bingeing! (Steve Litchfield)

Saying goodbye to The .NET Stacks (Dave Brock)

Auth0 Announces the Winners of the Actions Hackathon (Ed Armstrong)

How Two Interns Are Helping Secure Millions of Lines of Code (Gregg Horton)

Datadog Acquires Ozcode (Omer Raviv)

What to Expect at .NET Conf 2021 (Caitlyn Depp)

Join the Online Event: TeamCity – 15 Years of CI (Yegor Naumov)

Database

Time zones in SQL Server, Oracle and PostgreSQL (Andrea Gnemmi)

SharePoint & MS Teams

[Released] v5.0 Beta branch with SharePoint Server Subscription Edition support (Yorick Kuijs)

PowerShell

#PowershellBasics: Select the columns in the output. (Kenneth Fisher)

Miscellaneous

Releasing Windows 11 KB5008295 to Beta and Release Preview Channels (Brandon LeBlanc)

Windows 11 Build 22494 adds a new mute/unmute feature to Taskbar (Kunal Chowdhury)

Previewing Citations in Microsoft Edge (Microsoft Edge Team)

More Link Collections

The Morning Brew #3347 (Chris Alcock)

.NET App Developer Links – 2021-11-05 (Dan Rigby)

Collective #686 (Mary Lou)

The Wolf Report – November 5th, 2021 (Michael Wolfenden)

Code Maze Weekly #100 (Vladimir Pecanac)

The Geek Shelf

 C# 10 and .NET 6 – Modern Cross-Platform Development: Build apps, websites, and services with ASP.NET Core 6, Blazor, and EF Core 6 using Visual Studio 2022 and Visual Studio Code, 6th Ed (Mark J. Price) – Referral Link

How to Alter Column Datatypes in Snowflake

Snowflake is a great and ease to use platform. I am constantly moving workloads from Teradata, SQL Server, and Oracle to this platform.

However, I have encountered an interesting situation with an Oracle migration, specifically when you specify a column like number, such as in the following situation:

CREATE TABLE AS TEST_TABLE(A NUMBER, T VARCHAR2(10));

INSERT INTO TEST_TABLE(A,T) VALUES(10.123,‘A’);

INSERT INTO TEST_TABLE(A,T) VALUES(10.123567,‘B’);

In Oracle, when no precision is specified, numbers are stored as given.
In Snowflake, if we run the same code, NUMBER will be interpreted as NUMBER(38,0).
When you use SnowConvert, it will turn those column types to NUMBER(38,19) because the tool does not have enough information to determine the right precision.

But you might know which is the right precision. Let’s say NUMBER(20,4). I had hoped it would be as easy as using an ALTER COLUMN statement, but… sadly it is not. Snowflake’s ALTER COLUMN does not allow you to do that. So what can be done? Let’s take a look.

I came up with this solution. I can use a Snowflake JS procedure that will get the table definition, create a statement that will change my table, and run it.

CREATE OR REPLACE PROCEDURE ALTER_COLUMN(TABLE_NAME VARCHAR, TABLE_SCHEMA VARCHAR, TABLE_COLUMN VARCHAR, NEW_VALUE VARCHAR) RETURNS STRING
LANGUAGE JAVASCRIPT AS
$$
var EXEC = (sql,…binds)=>snowflake.execute({sqlText:sql,binds:binds});
var cols = EXEC(`SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=UPPER(‘${TABLE_NAME}’) AND TABLE_SCHEMA=UPPER(‘${TABLE_SCHEMA}’)`);
var newSQL = `CREATE OR REPLACE TABLE ${TABLE_SCHEMA}.${TABLE_NAME} ASn SELECT n`;
var count = cols.getRowCount();
while (cols.next())
{
count–;
if (cols[‘COLUMN_NAME’] == TABLE_COLUMN)
newSQL += NEW_VALUE + “AS “ + cols[‘COLUMN_NAME’];
else
newSQL += cols[‘COLUMN_NAME’];
if (count > 0) { newSQL += “,n”;}
}
newSQL+=`n FROM ${TABLE_SCHEMA}.${TABLE_NAME}`;
EXEC(newSQL);
return `Column ${TABLE_COLUMN} change using expression ${NEW_VALUE}`;
$$;

(You can get the code from here.)

For the previous example, you can just run the following:
CALL ALTER_COLUMN(‘TEST_TABLE’,’PUBLIC’,’A’,’A::NUMBER(20,4)’);
Notice that the first parameter is the table name, the second is the table schema, the column name is the third, and finally the expression that will be used for conversion. Usually just a CAST expression, but it can be used for any conversion expression.

This proc has been a great timesaver for me, so I hope it is a good addition for your Snowflake Toolbox.

Dew Drop – November 4, 2021 (#3552)

Top Links

Angular v13 is now Available (Mark Thompson)

Building the next phase of GitHub, together (Thomas Dohmke)

Microsoft Tech Community – .NET (Microsoft)

Announcing TypeScript 4.5 RC (Daniel Rosenwasser)

More flexible and inclusive ways to manage your documents (Grace Taylor)

Web & Cloud Development

Azure Tips & Tricks – Tip 340 – How to get started with Azure Maps (Azure Team)

How to Handle File Uploads from Node.js to Express (Ashley Boucher)

Considerations for Migrating .NET Applications to App Service or Azure Container Instances (ACI) (Walter Myers)

Exploring Fiddler Jam: What’s New? (Dave Brock)

Markdown Code Block Syntax Highlighting and Diff (Steve Smith)

Handling HTTP API Errors with Problem Details (Derek Comartin)

A Deep Dive Into Serverless UI With TypeScript (Ikeh Akinyemi)

Adding a Custom Domain and SSL to Static Web Apps (Jason Gaylord)

Logging Microservices: The Challenges and Solutions (Joydip Kanjilal)

Working with JSON files in Go (Manoj Debnath)

WinUI, .NET MAUI & XAML

Xamarin.Nuke: a Xamarin binding for the iOS image caching library (Jean-Marie Alfonsi)

Visual Studio & .NET

NSwag generated C# client: Open API property name clashes and decimal types rather than double (John Reilly)

C# Evolution (Miguel Teheran)

C++ from the beginning – your first program (Chris Noring)

String Performance: Formatting and Internationalization and Localization: Overview and String Performance: Concatenating Strings (David McCarter)

Two Ways to Restart Numbered Lists in TX Text Control (Malin Teegen)

Microsoft Launches VSCode.Dev, Visual Studio Code in the Browser (Sergio De Simone)

SpeedyGenerators (Raffaele Rialdi)

Design, Methodology & Testing

The DevOps Platform for agile business (Cormac Foster)

How to automate CI/CD tasks with C# Scripting in TeamCity (Maria Kudryavtseva)

Challenge: The code review bug that gives me nightmares–The fix (Oren Eini)

Advanced Installer 18.8.1 (Advanced Installer Team)

Test Studio R3 2021 Brings You Closer to the Ultimate Continuous Testing Setup (Iliyan Panchev)

Mobile, IoT & Game Development

Expert tips on optimizing your game graphics for consoles (Thomas Krogh-Jacobsen)

Podcasts, Screencasts & Videos

Syntax Podcast – STUMP’D Interview Questions – CSS Edition (Wes Bos)

.NET Rocks! – Azure Infrastructure as Code with Eduard Keiholz, Erwin Staal and Henry Been (Carl Franklin & Richard Campbell)

Software Engineering Daily – The Future of Quality Engineering with Liliya Frye (Jeff Meyerson)

Working Code Podcast – Episode 047: Email Ruins Everything (Ben Nadel)

Web Rush Episode 158: Svelte and Elder.js with Nick Reese (John Papa, Ward Bell, Dan Wahlin & Craig Shoemaker)

Are there any tools or technologies that can help accelerate my development process with WinUI? | One Dev Question and How can I use WinUI to build apps that are accessible for everyone? | One Dev Question and What are some note worthy community contributions to WinUI? | One Dev Question (Ana Wishnoff)

Unhandled Exception Podcast – UX with Jessica Engstrom (Dan Clarke)

Design Details 418: Fictional User Interfaces (Brian Lovin & Marshall Bock)

The Happy Engineer Podcast 019 – Get Into Big Tech with Mauricio Nunes (Kae Lynne Sapino)

RunAs Radio – Show 800! (Richard Campbell & Jeffrey Snover)

Community & Events

Splunker Stories: Sarah Scholz (Alicja Nelka)

Positive online civility trends reversed one year into the pandemic, new Microsoft study shows (Jacqueline Beauchere)

Dapr joins CNCF as an incubating project (Dapr Team)

Microsoft to hold “Reimagine” education event on November 9, promises “innovative technology” (Arif Bacchus)

Now on demand! Windows at Microsoft Ignite: November 2021 (Heather Poulsen)

Dapr (Distributed Application Runtime) joins CNCF Incubator (Cloud Native Computing Foundation)

Best of NodeConf Remote: The 30-second review (Lucas Holmquist, Michael Dawson & Bethany Griggs)

Thank you, GitHub (Nat Friedman)

GitHub CEO Nat Friedman steps down; Julia Liuson named president of Microsoft Developer Division (Todd Bishop)

Database

SQL Server 2022 is a game changer (Kathi Kellenberger)

Empower Modern App Developers with Document Databases (Andrew Davidson)

What’s new in SQL Server 2022 (Zachary Cavanell)

SharePoint, M365 & MS Teams

The Microsoft Teams desktop app will support multiple work accounts next year (Rabia Noureen)

Microsoft Loop is Rebrand of Fluid Framework (Russell Smith)

PowerShell & Terminal

PowerShell 7.1 runbook support in Azure Automation available in public preview (Azure Team)

Azure PowerShell Ignite release (Damien Caro)

Add/remove Open in Windows Terminal in Windows 11 (Kapil Arya)

Exchange Online PowerShell v2 Module Preview – Now More Secure (MS Exchange Team)

Miscellaneous

Announcing Windows 11 Insider Preview Build 22494 (Brandon LeBlanc)

Why Devs Love Their Newsletters (DeveloperMedia)

Stardock Releases Start11 (Paul Thurrott)

More Link Collections

The Morning Brew #3346 (Chris Alcock)

The Wolf Report – November 4th, 2021 (Michael Wolfenden)

The Geek Shelf

 When They Win, You Win: Being a Great Manager Is Simpler Than You Think (Russ Laraway) – Referral Link

REST Web API in Practice: Improving towards Perfection

Introduction

Designing REST Web APIs in practice has many challenges. Usually, various questions are born for different parts of the project. Our decisions can determine, among others, the usability, extensibility, and performance of our APIs.

In our previous articles, we saw how the REST architectural style guides us to create Web APIs by defining six constraints (principles) and some key points that we can consider when designing APIs (.NET Nakama, 2021 September 4). Furthermore, we saw some practical suggestions for adopting consistent naming conventions in our URLs (API endpoints) and how to perform filtering, sorting, and pagination (.NET Nakama, 2021 October 4).

This article examines several topics that developers usually deal with when designing REST Web APIs. The topics include HTTP status codes, Media Types, HATEOAS, and Caching.

The catchy title about perfection is an excuse to remind us that there is no perfection in software development. There will always be bugs and space for improvement as the software and business requirements evolve. So, we can continuously improve our knowledge and code. However, our choices can take our Web APIs to the next level, but it requires always keeping in mind the following rules:

Understand the needs of the API users.
Do not follow the API best practices blindly.
Examine and document each decision.
Design APIs with consistent behavior.

HTTP Status Codes

The HTTP protocol defines a standard list of HTTP status codes that a server can respond to the client. The status codes indicate whether the client requests have been successfully received and processed by the server, an error has occurred, or some other action is needed. The HTTP status codes are grouped in the following five classes depending on the:

1xx (i.e., 100-199), Informational Response.

2xx (i.e., 200-299), Successful: The request was successfully received, understood, and accepted.

3xx (i.e., 300-399), Redirection: Further action is required to complete the request.

4xx (i.e., 400-499), Client Error: The client request contains a wrong syntax or cannot be fulfilled (i.e., the resource cannot be found).

5xx (i.e., 500-599), Server Error: The server failed to complete an apparently valid request (e.g., due to an internal error, timeout error, etc.).

Tip: The System.Net namespace contains the HttpStatusCode Enum, which includes the values of status codes defined for HTTP.

Successful HTTP Status Codes

Any Web API needs to return consistent and meaningful HTTP status codes based on their standard definition. So, for example, we shouldn’t produce a 200 OK response when returning an error. In the following table, we can see the most appropriate (for most cases) used Success HTTP status codes per HTTP method.

HTTP Method
Success HTTP Status Codes for Synchronous Operations
Success HTTP Status Codes for Asynchronous Operations

GET

200 OK or 206 Partial Content when the contentare too big to be delivered in one response

POST

201 Created or 200 OK when we are not creating aresource.
202 Accepted

PUT
200 OK
202 Accepted

PATCH
200 OK
202 Accepted

DELETE

204 No Content, meaning that we are not returning a response body (as the resource has been deleted).
202 Accepted

We are returning a 202 Accepted status code for the asynchronous operations to inform the client that the requests have been received but not yet completed. In such case, we are also returning a Location header with the URI, which the client should periodically call (using a GET method) to “ask” the server about the status of his original request (short polling). For more information about asynchronous operations, you can read the (Price E., et al., 2018).

Error HTTP Status Codes

Design APIs with consistent error handling and helpful information can eliminate confusion from the API clients when errors occur. I believe that we all had faced errors in APIs, which was almost impossible to understand the actual issue or the information was misleading. For that reason, we should use the Error HTTP Status Codes (4xx and 5xx) appropriately. In the following table, we can see some commonly used error status codes and how we should use them.

Error HTTP Status Code
Description

400 Bad Request
The client’s request is not valid based on the server’s input validations.

401 Unauthorized
The user’s credentials are not valid (not authenticated), or the user did not provide credentials.

403 Forbidden
The user is authenticated (logged id) but doesn’t have the necessary permissions for this resource.

404 Not Found
The requested resource is not found on the server.

405 Method Not Allowed
An HTTP method is being requested that isn’t allowed for the authenticated user. For example, when a POST or PUT method is used on a read-only resource.

410 Gone
The requested resource is no longer available and will not be available again. This status code can be used for deprecated API calls (e.g., old API versions).

500 Internal Server Error
An unhandled exception occurs on the server, and a generic error message is returned.

502 Bad Gateway
The server acted as a gateway or proxy to another server from which it received an invalid response.

503 Service Unavailable
The server cannot handle the request (e.g., overloaded, down for maintenance, system failure, etc.).

504 Gateway Timeout
The server acted as a gateway or proxy to another server from which it didn’t receive a response in a specific timeframe.

When implementing .NET Core applications, you could use the open-source Consistent API Response Errors (CARE) NuGet library to centralize the error handling (validation errors, application exceptions, and unhandled exceptions) and return consistent and valuable error information.

Returning HTTP Status Code from ASP.NET Core Methods

ASP.NET Core supports methods to initialize responses for the most common status codes at the ControllerBase class (of the Microsoft.AspNetCore.Mvc namespace), such as the following.

Initialize Response to Return
Produced HTTP Status Code

Ok(Object)
200 OK

Created(Uri, Object)
201 Created

CreatedAtAction(String, Object, Object)
201 Created

NoContent()
204 No Content

BadRequest()
400 Bad Request

Unauthorized(Object)
401 Unauthorized

Forbid()
403 Forbidden

NotFound()
404 Not Found

StatusCode(Int32)
Based on the provided Status Code.

StatusCode(Int32, Object)
Based on the provided Status Code with the objectresult.

Media Types, Accepts, and Content-Type Headers

In REST Web API, we transfer resources from the client to the server and vice versa. A resource is any information that can be named, an entity (e.g., person, ticket, product, etc.), document, file, etc. We can represent a resource in different formats, such as JSON (JavaScript Object Notation), XML (Extensible Markup Language), CSV (comma-separated values), etc. In the following example, we can see a C# class and its representations in JSON and XML.

public class ProductDto
{
public int ProductId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public List<string> Sizes { get; set; }
}

JSON
XML

[
{
“productId”: 2,
“title”: “.NET T-Shirt”,
“price”: 10,
“sizes”: [
“M”,
“L”
]
}
]

<ArrayOfProductDto>
<ProductDto>
<ProductId>2</ProductId>
<Title>.NET T-Shirt</Title>
<Price>10</Price>
<Sizes>
<string>M</string>
<string>L</string>
</Sizes>
</ProductDto>
</ArrayOfProductDto>

As we can understand, we should inform the server and the client about the format of the transferred data to transform it accordingly to their native object(s) (parsing).

In the HTTP protocol, formats are specified through media types (also known as a Multipurpose Internet Mail Extensions or MIME type). A media type is a standard (RFC 6838) that indicates the nature and format of a document, file, or bytes. The following table shows the most common formats that are used for Web APIs and their media type.

Format
Media Type

JSON
application/json

XML
application/xml

The clients include the Accept HTTP header in their requests to determine the media type(s) that they can support. The Content-Type header is used in the client requests or server responses to define the format of the transferred data. When the accepted or requested media types are not supported, the server responds with an appropriate HTTP status code (as shown in the following table) (Price E., et al., 2018).

HTTP Header
Description
Example
Server HTTP Status Error Code

Accept
Determine the media type(s) that the client supports.
application/json
406 (Not Acceptable)

Content-Type
The format of the transferred data (in the request body).
application/json; charset=utf-8
415 (Unsupported Media Type).

In .NET Core Web APIs, we specify which media types are supported in each controller using the Consumes and Produces attributes, as shown in the following example.

[ApiController]
[Route(“[controller]“)]
[Consumes(“application/json”)]
[Produces(“application/json”)]
public class SimpleController : ControllerBase
{
// The code of the controller

}

If you would like to support multiple response formats based on the client requests (e.g., from the URL), you can read the Andrew Lock (2017, August 01) article.

HATEOAS or Not HATEOAS

One of the REST architectural style constraints to provide a uniform interface between components is Hypermedia as the Engine of Application State (HATEOAS). Based on the HATEOAS constraint, the server should provide information for all available actions of each resource.

For example, when retrieving data of a bank account (e.g., balance information), the server could also return the URLs of possible actions, such as to deposit, withdraw, etc., as we can see in the following example (Wikipedia, 2021).

HTTP/1.1 200 OK

{
“account”: {
“account_number”: 12345,
“balance”: {
“currency”: “usd”,
“value”: 100.00
},
“links”: {
“deposits”: “/accounts/12345/deposits”,
“withdrawals”: “/accounts/12345/withdrawals”,
“transfers”: “/accounts/12345/transfers”,
“close-requests”: “/accounts/12345/close-requests”
}
}
}

Currently, there are no general-purpose standards that define how to model the HATEOAS principle (Price E., et al., 2018). From my perspective, the most controversial and challenging to follow REST constrain is the HATEOAS. It adds a lot of complexity to the server project, and sometimes the clients do not use it. For that reason, several backend developers do not apply it. In such cases, the APIs are referred to as REST-Based (.NET Nakama, 2021 September).

Using HATEOAS offers several advantages, such as (SOA Bits and Ramblings, 2013):

Explorable APIs,
Inline documentation,
Simpler client logic,
Server ownership of URL structures,
Easier versioning in the URI.

However, let’s keep in mind the key-point of “Do Not Follow the API-Best-Practices Blindly” (.NET Nakama, 2021 September) and the “Keep It Simple Stupid (KISS)” principle. Based on the needs of our clients and our project’s requirements, we should examine if the HATEOAS is worth implementing and then decide. Do not just try to make a RESTful API just for the name!

Tip: Do not just try to make a RESTful API just for the name!

Caching

Caching is the process of temporarily storing data or files in storage to be accessed more quickly. This process is used when the computation or/and the retrieval of the data or files require significant time or/and resources (e.g., CPU, network bandwidth, etc.). However, it is essential to cache data or files for a duration related to each case (how frequently the specific data changes, its importance, etc.) because otherwise, they might be outdated (staled).

In client-server communication, we can perform caching on both sides for different reasons.

In the server: We could cache (in Redis, MemoryCache, etc.) the data retrieved from a database or a third-party system to faster respond to the client.
In the client: We could cache the retrieved data from the server to reduce the following requests.

The cache constraint in the REST architectural style is related to client caching guided by the server using HTTP headers to label the response data as cacheable or non-cacheable. In this way, the client can reuse the same data in later equivalent requests (usually for a limited timeframe), with partial or no interaction with the server (.NET Nakama, 2021 September). The HTTP client caching is generally performed for the GET HTTP requests.

In the following sections, we will focus on the response HTTP headers that guide the clients caching.

Cache-Control

The Cache-Control header value (RFC-7234) can contain several directives (comma separated) to configure the caching policies of the requests and responses. The main idea is to cache the response until it becomes stale (based on the Cache-Control directives and the Expires HTTP Header). After that, stale resources can either be validated or fetched again (see Cache Validation section).

The following table presents the most common Cache-Control directives (Fielding R. et al., 2014).

Directive
Example
Description

no-store
Cache-Control: no-store
A cache must not store any part of either the immediate request or response.

no-cache
Cache-Control: no-cache
The response must not be used to satisfy a subsequent request without successful validation on the server (it is always stale). In case it is used on a request, the server should regenerate the response for the client and store it in its cache.

public
Cache-Control: public
Any cache may store the response.

private
Cache-Control: private
The response message is intended for a single user and must not be stored by a shared cache. However, a private cache may store and reuse the response.

max-age
Cache-Control: max-age=5
Determine the number of seconds (e.g., five in the example) that a response can be cached. After that period, the cached value is considered stale.

must-revalidate
Cache-Control: must-revalidate
This indicates that once the cache has become stale, it cannot be used as a cached response to satisfy subsequent requests without successful validation on the origin server.

Expires HTTP Header

The Expires HTTP header contains the date/time after which the response is considered stale. In general, staled resources should not be used (Mozilla.org, 2021). If a Cache-Control header exists with a max-age directive in the response, then the Expires header is ignored.

Cache Validation

When a resource is staled (expired), it can either be validated or fetched again. The validation is performed to the server by providing some information in the request (as HTTP headers) about the specific resource (e.g., an identifier or the last modification date).

This information is provided by the server (in the original response) as HTTP headers, and specifically, it is the ETag and the Last-Modified.

ETag

The ETag HTTP response header is an identifier for a specific version of a resource. This identifier is usually a hash of the resource (see the following example). Thus, when the resource changes (different versions of the data), a new hash is generated.

ETag: “e4d16978735c9e008be608c3a7eb59a89b277fe7ffd6744b655006065de88d75”

Using the ETag value in an “If-None-Match” header to the following GET requests, the server can save network bandwidth by not resending the complete response when the content was not changed. In such cases, the server returns a 304 Not Modified HTTP status code which is used as a 200 OK response telling the client to use the cached resource.

If-None-Match: “e4d16978735c9e008be608c3a7eb59a89b277fe7ffd6744b655006065de88d75”

Also, when transferring resources to the server, cache validation can be performed (e.g., POST, PUT, etc.) by sending the ETag value in an “If-Match” header. The server will compare the provided ETag value with the current resource ETag value, and if they match (i.e., it has not changed in the meantime), the update will be performed. On the other hand, if the ETag values do not match, the server will respond with a 412 Precondition Failed HTTP status code.

If-Match: “e4d16978735c9e008be608c3a7eb59a89b277fe7ffd6744b655006065de88d75”

Last-Modified

The Last-Modified response HTTP header contains a date and time when the server believes the resource was last modified. It is used similarly with the ETag HTTP header, but it is less accurate.

Last-Modified: Wed, 20 Oct 2021 06:17:00 GMT

The Last-Modified value can be used in the same way in correspondence with the ETag value by using the following HTTP headers: If-Unmodified-Since and If-Modified-Since.

Summary

This article focused on HTTP status codes, Media Types, HATEOAS, and Caching to improve our REST Web APIs. Decisions on these topics can influence our Web APIs usability, extensibility, and performance.

The consistent and meaningful use of the HTTP status codes can make a huge difference in our API’s usability. For example, the server would inform better the API consumer applications and their developer(s) about what happened to perform the appropriate actions in case of errors.

Using HATEOAS offers several significant advantages regarding extensibility. However, it adds a lot of complexity, and sometimes the clients do not use it. Therefore, we should examine if the HATEOAS is worth implementing in each project separately and then decide. We should not just try to make a RESTful API just for the name!

Caching can improve the performance of our applications by temporarily storing data or files to be accessed more quickly. The cache constraint in the REST architectural style is related to client caching guided by the server. For that purpose, we examined the response HTTP headers that guide the clients caching.

There will always be space for improvement in our Web APIs and software development in general. However, we can continuously improve our technical skills, understand how things work, and gain experience, reflecting in our code and decisions.

References

.NET Nakama (2021, September 4). Designing a RESTful Web API. https://www.dotnetnakama.com/blog/designing-a-restful-web-api/

Fielding R., et al. (2014, June). Hypertext Transfer Protocol (HTTP/1.1): Caching. https://datatracker.ietf.org/doc/html/rfc7234#section-5.2.2

Lock A. (2017, August 01). How to format response data as XML or JSON, based on the request URL in ASP.NET Core. https://andrewlock.net/formatting-response-data-as-xml-or-json-based-on-the-url-in-asp-net-core/

Mozilla.org (2021, October 20). HTTP caching. https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching

SOA Bits and Ramblings (2013, December 06). Selling the benefits of hypermedia in APIs. http://soabits.blogspot.com/2013/12/selling-benefits-of-hypermedia.html

Price E., et al. (2018, December 1).RESTful web API design. https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design

Wikipedia (2021, October 10). HATEOAS. https://en.wikipedia.org/wiki/HATEOAS#Example

340: With George Francis

Chris gets to chat with George Francis, an incredible digital artist in the generative art space as well as educator and all-around developer. George has been all over the place lately, producing really outstanding work (CSS-Tricks uses a Houdini paint worklet from George in the header and footer). Not only does George make art that has that little special something that turns heads, he helps you do it too by sharing all the tools and techniques he uses in blog posts.

Time Jumps

00:28 Guest introduction

01:35 Do you like the term Generative Code?

03:27 Limiting the randomness

06:04 How do I random blob?

10:52 Sponsor: Netlify

12:22 Which blobs get popular on CodePen

16:00 Working with Houdini

23:08 What goals do you have with your work?

26:49 NFTs and generative code

29:46 Tell us about your day job

Sponsor: Netlify

Netlify has used the slogan “Static without limits” — which I really like. It’s useful to think of Netlify as a static file host as the foundation. That’s what Jamstack is, after all. But it doesn’t mean that you are limited in what you can build. You can make a site that is every bit dynamic as any other architecture out there, and Netlify not only encourages it but will help you do it with features like hosted cloud functions.

The post 340: With George Francis appeared first on CodePen Blog.

Dew Drop – November 3, 2021 (#3551)

Top Links

Announcing SQL Server 2022 preview: Azure-enabled with continued performance and security innovation (Peter Carlin)

Microsoft Edge celebrates customers moving to IE mode, Linux, and new search innovations (Colleen Williams & Sean Lyndersay)

.NET 6 Hot Reload in Visual Studio 2022, VS Code, and NOTEPAD?!? (Scott Hanselman)

Microsoft Cloud at Ignite 2021: Metaverse, AI and hyperconnectivity in a hybrid world (Frank X. Shaw)

Microsoft Ignite Book of News (Microsoft)

Web & Cloud Development

What’s new in Svelte: November 2021 (Daniel Sandoval)

Add GitHub OpenID Auth For ASP.NET Core Apps (Khalid Abuhakmeh)

Public preview: GraphQL passthrough support in Azure API Management and Public preview: Dapr extension for AKS (Azure Team)

Role-Based Authorization for ASP.NET Web APIs (Andrea Chiarelli)

Search via querystring with Sveltekit (Andrew Williams)

Sega, Microsoft Announce Strategic Alliance To Develop ‘Super Game’ Initiative On Azure (BeauHD)

Responsible JavaScript (Chris Coyier)

How to Show/Hide Elements in Vue (Dmitri Pavlutin)

Announcing the Public Preview of Azure Chaos Studio (John Kemnetz)

Final Blazor Improvements Before .NET 6 (Jon Hilton)

New Azure OpenAI Service combines access to powerful GPT-3 language models with Azure’s enterprise capabilities (Jennifer Langston)

Deploying new Azure Container Apps with familiar languages (Mikhail Shilkov)

Recognizing and Removing Friction Points in the Developer Experience on Kubernetes (Nivedita Ghosh)

Modernize Applications with Windows containers and Kubernetes (Thomas Maurer)

What’s new and what’s next for Microsoft Graph connectors (Bill Baer)

Load Balancing: Using Different TCP Service Locations using a Custom WebSocketHandler (Bjoern Meyer)

W3C updates its Process Document (Coralie Mercier)

Netflix Video Quality at Scale with Cosmos Microservices (Christos G. Bampis, Chao Chen, Anush K. Moorthy & Zhi Li)

Announcing Knative 1.0! (María Cruz)

WinUI, .NET MAUI & XAML

Everything You Need to Know About WinUI Badge Control (Niranjan Kumar Gopalan)

Visual Studio & .NET

Improving logging performance with source generators: Exploring .NET Core 6 – Part 8 (Andrew Lock)

Collection Performance: Creating Collections with Capacity & AddRange() (David McCarter)

Anomaly Detection Using ML.NET (Robert Krzaczyński)

Design, Methodology & Testing

Compliance in a DevOps Culture (Martin Fowler)

Overcoming the Common Microservices Anti-Patterns (Joydip Kanjilal)

Challenge: The code review bug that gives me nightmares–the issue (Oren Eini)

Get started with your Sketch Workspace (Sketch Team)

A Modern Leader’s Guide To Organizational Transparency (Genevieve Michaels)

What’s your career plan? (Eric Brechner)

Rebase vs. Merge: Integrating Changes in Git (Tobias Günther)

Mobile, IoT & Game Development

15% off Microsoft HoloLens 2 for a limited time. Get started today! (Ronan Jenkins)

Podcasts, Screencasts & Videos

Kubernetes Podcast from Google – Knative 1.0, with Ville Aikas (Craig Box & Adam Glick)

Microsoft Cloud Show Episode 433 | Managing Insane Pandemic Teams Growth With Michal Pisarek (Andrew Connell & Chris Johnson)

Visual Studio was written using Visual Studio (Mads Kristensen)

ReWork Podcast – Scratch Your Own Itch (Jason Fried & David Heinemeier Hansson)

FreeCodeSession – Episode 312 (Jason Bock)

Windows Insider Podcast – The Kitchen Sink of Conversations (Windows Insider Team)

8 Bits with Sam Julien (again!) (Pj Metz & Brandon Minnick)

The future is in WebAssembly – Adventures in .NET 093 (Shawn Clabough & Wai Liu)

Windows 11 application confidence with Test Base and App Assure (Carla DiFranco)

Community & Events

My Top 5 Sessions to Attend at PASS Data Community Summit (Pinal Dave)

My message to the world at COP26 (Bill Gates)

Ignite 2021: Building apps for collaboration in a hybrid world (Ben Summers)

.NET Conference 2021 – All You Need to Know About The Event (Jason Beres)

Database

Find Queries with Index Hints in SQL Server (Aaron Bertrand)

What’s New in SQL Server 2022 (Brent Ozar)

Make Your Azure SQL Managed Instance Passwordless (Srdan Bozovic)

CosmosDB: New developer productivity, cost-savings, and advanced analytics features announced at Microsoft Ignite (Nikisha Reyes-Grange)

SharePoint & MS Teams

Q&A in Teams is in Public Preview. Try it now! (Sameer Sitaram)

Our new and enhanced Microsoft Teams integration (Vasudha Swaminathan)

Viva Learning now generally available! (John Mighell)

PowerShell

Automating Windows Task Scheduler with PowerShell (Steve Fenton)

Miscellaneous

Facebook wants to build a metaverse. Microsoft is creating something even more ambitious (Mark Wilson)

Windows 10 and 11 players: Minecraft is now included in Game Pass for PC (Athima Chansanchai)

Understanding Windows 11 deployment, management, servicing, and lifecycle (Dave Backman)

More Link Collections

The Morning Brew #3345 (Chris Alcock)

The Wolf Report – November 3rd, 2021 (Michael Wolfenden)

.NET Annotated Monthly | November 2021 (Rachel Appel)

The Geek Shelf

 Purely Functional Data Structures (Chris Okasaki) – Referral Link

Automatically add #Sedo verification to a batch of domain names using #NameCheap #API

If you are listing domains on Sedo, it’s likely that you have a number of domains, and perhaps instead of going through the process of manually adding the CNAME record to every domain, you can use NameCheap’s API in C# to automatically add CNAME records.

This is a follow-on to the previous blog post, shown below; Classes mentioned in this post will not be repeated, so you should follow this first;

Given a list of domains in a text file (one domain per line), add this to the project with the build action “copy always”.

var domains = File.ReadAllLines(“domainList.txt”);
foreach (var domain in domains)
{
Console.WriteLine(domain);
var domainTld = Regex.Match(domain, @”.w+$”).Value;
var domainWithoutTld = domain.Replace(domainTld, “”);
domainTld = domainTld.Substring(1);
var hosts = GetHostsFromDomain(domainWithoutTld, domainTld);
Thread.Sleep(TimeSpan.FromSeconds(1));
hosts.Add(new HostRecord { Name = “***ID***”, Type = “CNAME”, Value = “verify.sedo.com” });
Thread.Sleep(TimeSpan.FromSeconds(1));
SetHostRecords(domainWithoutTld, domainTld, hosts);
Thread.Sleep(TimeSpan.FromSeconds(1));
}

Where evidently ***ID*** is replaced with your own personal ID from Sedo. The one second delays are to help prevent throttling, which the NameCheap API uses to prevent abuse.

And, if you’re interested, this is the list of domains that is going on sale;

webserverdown.com
vatapi.co.uk
universaltravelsearch.com
u2fapi.com
tweetjs.com
tempemailaddress.com
resxtranslate.com
printfromwindowsphone.com
printfromipad.com
outsourcetranslation.com
omadataobjects.com
listoftaxis.info
listofpubs.info
listofhotels.info
listofhauliers.info
listofestateagents.info
listofdevelopers.info
listofcardealers.info
listofbanks.info
javatiger.com
installipa.com
gotoeuro.net
freetextuk.com
freebiesms.com
freebiebitcoin.com
electoralrollapi.com
domaindeflect.com
dns-js.com
derrycreativescollective.com
createfreeapp.com
burnersms.com
airportdelays.org

Dew Drop – November 2, 2021 (#3550)

Top Links

.NET 6 Launches at .NET Conf, November 9-11 (Beth Massi)

Mapping UWP features to the Windows App SDK (Steven White)

John Miller on Microsoft Teams Apps with Blazor – Azure DevOps Podcast Episode 165 (Jeffrey Palermo)

GitHub keeps getting better for open source maintainers (Nick Holden)

Visual Studio 2022 Launch Event Agenda (Andy Sterland)

Web & Cloud Development

Building a Woodworking Site with Vue and Netlify CMS (Andrew Evans)

Using Azure Functions Middleware to Access ClaimsPrincipal in Azure Static Web Apps (Adam Storr)

Keystone on Azure: Part 1 – Local Dev and Keystone on Azure: Part 2 – Hosting (Aaron Powell)

Is Next.js Here to Stay? A Closer Look at JavaScript Development Frameworks (Anton Lucanus)

Usage Of CancellationToken In Asp.Net Core Applications (Naveen Bommidi)

Syncfusion Blazor Code Snippets in Visual Studio Code for MAC: An Overview (Abishake Dakshinamoorthy)

Build client web assets for your Razor Class Library (Javier Calvarro Nelson)

100 days of TypeScript (Day 5) (Peter O’Hanlon)

WinUI, .NET MAUI & XAML

Using State Machine in Xamarin Forms (Part 3) (Rendy Del Rosario)

Visual Studio & .NET

ICYMI C# 9 New Features: Create Immutable Objects with Records (Jason Roberts)

Bite-Size .NET 6 – MaxBy() and MinBy() in LINQ (Matthew Jones)

Collection Performance: Looping Over Other Collection Types (David McCarter)

Diagnostics tools for App Service on Linux (Mark Downie)

Design, Methodology & Testing

Running Windows Unit tests for Kubernetes on Windows (James Sturtevant)

Challenge: The code review bug that gives me nightmares (Oren Eini)

Clean Code Tip: Don’t use too many method arguments (Davide Bellone)

Flex Your DevSecOps Muscles With Bicep (and get started with our cheat sheet) (Barry Smart)

Why SOLID principles are still the foundation for modern software architecture (Daniel Orner)

The Change Benefits Canvas (How To Visualize the Narrative of Business Change) (JD Meier)

Leadership Tip 15: Reward Meeting Behavior You Want to See (Johanna Rothman)

Leadership is a choice (Seth Godin)

Mobile, IoT & Game Development

Easily Reschedule Appointments with Drag-and-Drop and Resizing in Flutter (Nijamudeen)

Announcing Stencil v2.10 (Anthony Giuliano)

Podcasts, Screencasts & Videos

Syntax Podcast – Hasty Treat – How to Setup a PNPM Monorepo (Wes Bos)

Revision Path – Terresa Moses (Maurice Cherry)

The Stack Overflow Podcast 389: The big problem with only being able to solve big problems (Ryan Donovan)

Armchair Architects: Hybrid and Multi-Cloud Architectures – Observability | Azure Enablement Show (David Blank-Edelman, Uli Homann & Eric Charran)

Modern Web Dev with Blazor and .NET 6 with Jason Taylor (SSW TV)

Getting Started with Firebase Realtime Database and Xamarin.Forms (Gerald Versluis)

The Work Item #42 – Building The World You Want To See, with Jeff Atwood (Den Delimarsky)

Monsters Weekly 229 – Where is my Program Main method? (James Chambers, Simon Timms & David Paquette)

Google Cloud Security Podcast Episode 41 – Beyond Phishing: Email Security Isn’t Solved (Anton Chuvakin)

DevTalk Podcast 74 – Being a software consultant. With Tobias Hoppenthaler (Kerry Lothrop)

Radical Candor S3, Mini Ep. 4: How to Give Feedback (Kim Scott, Jason Rosoff & Amy Sandler)

From Marketing Major to Microsoft MVP (Microsoft Developer)

Microsoft Mechanics – See Why Microsoft Visio is Now Available to More People. Plus Recent Updates (Jeremy Chapman & Mukul Kumar)

Microsoft Mechanics – Stop Cloud & Hybrid Apps from being Cyber Attack Entry Points (Jeremy Chapman)

MidDay Café Episode 26 – Ignite, Ignite, Ignite! (Mike Gannotti)

The 6 Figure Developer Episode 218 – mTLS and K8s with William Morgan (John Callaway)

Microsoft 365 PnP Weekly – Episode 141 – Joel Rodrigues (Storm Technologies) (Vesa Juvonen & Waldek Mastykarz)

Community & Events

.NET Conf 2021, .NET 6, Uno Platform. Prizes Available! (Uno Platform Team)

Adobe MAX 2021 sneaks: A peek into what’s next (Adobe Communications Team)

.NET Conf 2021 Agenda – Conference at a glance (.NET Conf Team)

Vim at 30: Here’s Why It’s Still Relevant (Alex Baldwin)

We Are Thankful for Our Team (Eugenio Pace)

Our 3rd annual bug bounty contest: the swagtastic sequel to the sequel (Heather Simpson)

Cybersecurity spotlight on bug bounty researcher @yvvdwf (Jeff Guerra)

Game Off 2021 theme announcement (Lee Reilly)

Database

Azure SQL Managed Instance CPU and RAM (Arun Sirpal)

The Curious Case of… the BULK_OPERATION lock during a heap NOLOCK scan (Paul Randal)

SharePoint & MS Teams

Introducing Microsoft Teams Real-time Call Quality Analytics (Siunie Sutjahjo)

More Link Collections

The Morning Brew #3344 (Chris Alcock)

.NET App Developer Links – 2021-11-02 (Dan Rigby)

Sands of MAUI: Issue #31 (Sam Basu)

The Wolf Report – November 2nd, 2021 (Michael Wolfenden)

[Last Week in .NET #66] – Halt and Crash Intellisense (George Stocker)

The Geek Shelf

 Elegant Objects (Yegor Bugayenko) – Referral Link

Implementing Content Security Policy (CSP) in ASP.NET Core

This post is about implementing content security policy in ASP.NET Core. Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware – Content Security Policy (CSP) MDN

A primary goal of CSP is to mitigate and report XSS attacks. XSS attacks exploit the browser’s trust in the content received from the server. Malicious scripts are executed by the victim’s browser because the browser trusts the source of the content, even when it’s not coming from where it seems to be coming from. CSP helps developers to configure the URL of the resources, and if some other resource which is not part of the configuration won’t be loaded into the browser. CSP also helps on mitigating packet sniffing attacks. Content Security Policy can be configured in ASP.NET Core with the help of Content-Security-Policy header.

Here is an example of the CSP Header of facebook.com

In ASP.NET Core, you can create middleware to set the header to http response, here is a minimal middleware to do this. You need to add this code to the Configure() method in Startup.cs before the UseEndpoints method.

app.Use(async (context, next) =>
{
context.Response.Headers.Add(“Content-Security-Policy”, “default-src ‘self’;”);
await next();
});

And when you run the app you will be able to see everything is working as expected – since the default template is loading everything from the app only. Let us modify the code and instead of loading the Bootstrap resources from local move them to CDN and will verify it. When loading any scripts or styles from CDN, browser will not load them, because you are configured the content security policy to load resources from the app only.

Since I configured the CSP Header to load resources from self which is the app, browser is not loading any resources from CDN. You can fix this by adding the CDN URL in the CSP Header – like this.

app.Use(async (context, next) =>
{
context.Response.Headers.Add(“Content-Security-Policy”, “default-src ‘self’ cdn.jsdelivr.net;”);
await next();
});

You can find more details about CSP and its various configuration in Content Security Policy (CSP) MDN. And you can validate your CSP Headers in SecurityHeaders.com. If you’re building a new application, you can configure CSP easily and write code adhering the CSP rules. But if you’re trying to apply CSP in an existing website it is quite overwhelming because most of the code – inline styles, scripts, events and all may not work. To avoid this issue, you can use Content-Security-Policy-Report-Only header with the report URL parameter – it will not ignore the script or resource instead it will display the error to the report URL.

app.Use(async (context, next) =>
{
context.Response.Headers.Add(“Content-Security-Policy-Report-Only”, “default-src ‘self'”);
await next();
});

Here is the screenshot of the app running with Content-Security-Policy-Report-Only header – It is loading the resources and logging the errors in the browser console as well.

You can configure an endpoint if you would like you to store the CSP violations in Database or tools like Application Insights. First you need to create a HTTP Post endpoint and you can write logic to store the information in database. Here is the implementation.

[HttpPost(“cspreport”)]
public IActionResult CSPReport([FromBody] CspReportRequest cspReportRequest)
{
_logger.LogInformation(@$”CSP Violation: {cspReportRequest.CspReport.DocumentUri},
{cspReportRequest.CspReport.BlockedUri}“);
return Ok();
}

And here is the CspReportRequest model class.

public class CspReportRequest
{
[JsonPropertyName(“csp-report”)]
public CspReport CspReport { get; set; }
}

public class CspReport
{
[JsonPropertyName(“document-uri”)]
public string DocumentUri { get; set; }

[JsonPropertyName(“referrer”)]
public string Referrer { get; set; }

[JsonPropertyName(“violated-directive”)]
public string ViolatedDirective { get; set; }

[JsonPropertyName(“effective-directive”)]
public string EffectiveDirective { get; set; }

[JsonPropertyName(“original-policy”)]
public string OriginalPolicy { get; set; }

[JsonPropertyName(“blocked-uri”)]
public string BlockedUri { get; set; }

[JsonPropertyName(“status-code”)]
public int StatusCode { get; set; }
}

And you can modify the middleware like this.

app.Use(async (context, next) =>
{
context.Response.Headers.Add(“Content-Security-Policy-Report-Only”,
“default-src ‘self’; report-uri /cspreport”);
await next();
});

Since the Post method in using another content type – application/csp-report you might get 415 error – to fix this you need to configure this content type in ASP.NET Core MVC, like this.

public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddMvcOptions(options =>
{
options.InputFormatters.OfType<SystemTextJsonInputFormatter>().First().SupportedMediaTypes.Add(
new Microsoft.Net.Http.Headers.MediaTypeHeaderValue(“application/csp-report”)
);
});
}

Now you can run the application and you will be able to see the CSP violations in logger. There are some nuget packages already available to configure the CSP in ASP.NET Core apps. It is recommended to enable CSP in web apps.

Happy Programming 🙂