European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core 9.0 Hosting - HostForLIFE :: Use and Examples of the Response Cache Attribute in .NET Core

clock September 11, 2024 06:52 by author Peter

Response caching is the technique by which a browser or other client stores a server's response in memory. As a result, requests for the same resources will be processed more quickly in the future. Additionally, this will spare the server from processing and producing the same response over and over again. ASP.NET Core uses the ResponseCache property to set the response caching headers. Moreover, we can use the Response Caching Middleware to control the caching behavior from the server side. Once we've configured clients and other proxies to determine how to cache the server response, they can read the response caching headers. The HTTP 1.1 Response Cache Specification stipulates that browsers, clients, and proxies need to have caching headers.

What Does "caching" Mean?
The process of temporarily storing frequently used data so that it can be rapidly retrieved is known as caching. The application's overall speed will be improved because there won't be as much need to fetch the same data from the database or other storage devices.

ASP.NET Core Caching Types

  • Multiple Caching Mechanism Types are Supported by ASP.NET Core. They are listed in the following order.
  • In-Memory Caching: The most basic type of caching, in-memory caching works well with a single server. The main memory of the web server houses the data. It is quick and appropriate for data that doesn't require persistence past the web server process' lifetime or require a lot of memory. It works well for storing modest volumes of information.
  • Distributed Caching: Applications that must share data across multiple servers in load-balancing or multi-server environments are best suited for distributed caching. It entails keeping data in an external system, like NCache, SQL Server, Redis, and so forth. Although it requires more work than in-memory caching, large-scale applications must use it to guarantee consistency between requests and sessions.
  • Response Caching: Response Caching is the process of keeping the result of a request-response cycle in the cache in order to serve the resource from the cache in response to subsequent requests rather than having to generate the response from scratch. This method can greatly enhance the performance of a web application, particularly for resources that are costly to produce and don't change frequently.

HTTP Based Response Caching
Now let's talk about the different HTTP Cache Directives and how to control the way caching behaves. Cache-control is the primary header parameter that we utilize to specify whether or not a response can be cached. The cache-control header should be respected and adhered to by clients, proxy servers, and browsers when it shows up in the response.

Let's now examine the standard cache-control directives.

  • public: denotes the ability for a cache to hold the response locally on the client or in a shared location.
  • private: denotes that the response may only be stored in a client-side private cache and not in a shared cache.
  • no-cache: The no-cache flag instructs a cache not to respond to any requests with a stored response.
  • no-store: The no-store flag instructs a cache not to keep the answer.

Browsers and clients understand no-cache and no-store differently, despite the fact that they sound and even behave similarly. We will discuss this in more depth as we go through the instances.

A few more headers, in addition to cache control, can regulate the caching behavior.

For backward compatibility with the no-cache directive and the HTTP 1.0 specification, the pragma header is used. It will disregard the pragma header if we supply the cache-control header.

Vary: This tells it that it can only send a cached response if every field in the header precisely matches the request that came in before. A new response is generated by the server if any of the fields are modified.

Illustrations of HTTP Cache Directives
We will now create an ASP.NET Core application to demonstrate how the cache directives work. Now let's add a controller action method to an ASP.NET Core Web API project that has been created.
public record EmployeeDto
{
    public Guid Id { get; init; }
    public string Name { get; init; }
    public EmployeeType Type { get; init; }
    public string Mno { get; init; }
    public decimal Salary { get; init; }
    public DateTime CurrentDate { get; init; } = DateTime.Now;
}

[HttpGet("{id}")]
public IActionResult GetById(Guid id)
{
    var emp = _employeeService.GetById(id);
    if (emp == null)
    {
        return NotFound();
    }

    return Ok(emp);
}

ResponseCache Attribute
The ResponseCache attribute for an ASP.NET Core application specifies the properties for configuring the relevant response caching headers. This attribute can be used for specific endpoints or at the controller level.

Let's update the API endpoint with the ResponseCache attribute.
[HttpGet("{id}")]
[ResponseCache(Duration = 120, Location = ResponseCacheLocation.Any)]
public IActionResult GetById(Guid id)
{
    var emp = _employeeService.GetById(id);

    if (emp == null)
    {
        return NotFound();
    }

    return Ok(emp);
}

The max-age header, which we use to set the cache duration for two minutes (120 seconds), is produced by this Duration property. In a similar manner, the cache-control header's location will be set by the Location property. Both the client and the server will be able to cache the response because we have the location set to Any, which is similar to the public directive of the cache-control header.

Let us now access the API endpoint and confirm these contents within the response headers.
cache-control: public,max-age=120

Furthermore, if the browser uses a cached response after we repeatedly invoke the endpoints, the response from the disk cache will be indicated in the status code.
200 is the status code (from disk cache).

Let's now examine the various ResponseCache parameter options.

All we have to do is update the Location property to ResponseCacheLocation.Client in order to change the cache location to private.
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Client)]

By doing this, the cache-control header value will be altered to private, indicating that the response can only be cached by the client.
cache-control: private,max-age=60

Let's now change ResponseCacheLocation.None as the Location parameter:
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.None)]

This will cause the client to be unable to use a cached response without revalidating with the server, as it will set the cache-control and pragma headers to no-cache:

We can confirm that the server always generates a fresh response in this configuration, and the browser never uses the cached response.
cache-control: no-cache,max-age=60

We can confirm that the server always generates a fresh response in this configuration, and the browser never uses the cached response.

NoStore Property
Let's now set the ResponseCache attribute's NoStore property to true.
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, NoStore = true)]

This will cause the response's cache-control header to be set to no-store, telling the client not to cache the response.
cache-control: no-store

Keep in mind that this will take precedence over the Location value we set. The client won't save the answer in its cache in this instance either.

Though the cache-control no-cache and no-store values might produce identical test results, different browsers, clients, and proxies interpret these headers in different ways. No-cache simply means that the client should not use a cached response without revalidating with the server, whereas no-store instructs clients or proxies to not store the response or any portion of it anywhere.

The VaryByHeader property of the ResponseCache attribute can be used to set the vary header.
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, VaryByHeader = "User-Agent")]

Here, we set the VaryByHeader property to User-Agent, which means that if the request originates from the same client device, it will use the cached response. The User-Agent value will alter and the client device will request a fresh response from the server. Let us confirm this.

Let's first see if the response headers contain the vary header.
cache-control: public,max-age=60
vary: User-Agent

Consequently, we can force the server to send a fresh response for a different device by configuring the VaryByHeader property to User-Agent.

VaryByQueryKeys Property
When the specified query string parameters change, we can force the server to send a new response by utilizing the VaryByQueryKeys property of the ResponseCache attribute. Naturally, if we set the value to "*," we can create a fresh response each time a query string parameter changes.

For instance, if the ID value in the URI changes, we might want to produce a fresh response.
    …/emp?id=53C68EE5-107B-42DB-821E-E1F893C5BDA3
    …/emp?id=6E5692FA-EEF6-426A-B280-EF444CB2BA1E

To do this, let's alter the Get action to add the id parameter and supply the ResponseCache attribute's VaryByQueryKeys property.
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, VaryByQueryKeys = ["id"])]

Recall that in order to set the VaryByQueryKeys property, we must activate the Response Caching Middleware. The code will raise a runtime exception if it doesn't.

Response Cache Middleware
When a response can be cached, the ASP.NET Core application's Response Caching Middleware establishes this and stores and serves the response from the cache.

The Response Caching Middleware can be enabled by adding a few lines of code to the Program class.

// service inject
builder.Services.AddResponseCaching();

// in the middleware
app.UseResponseCaching();

Using the AddResponseCaching() method, we must first add the middleware. Afterwards, we can use the UseResponseCaching() method to configure the application to use the middleware.

That is all. Now that the Response Caching Middleware has been turned on, the VaryByQueryKeys property ought to function.

Now that the application is running, let's check the response cache.

It is evident that if the query string remains unchanged, we will receive a cached response; however, if we modify the query string, the server will send a fresh response. Let's examine the response cache and modify the value of the query string.


Take note that the VaryByQueryKeys property does not have a corresponding HTTP header. Response Caching Middleware oversees managing this HTTP feature.

We learned the new technique and evolved together.

Happy coding!

HostForLIFE ASP.NET Core 9.0 Hosting

European Best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core 9.0 Hosting - HostForLIFE :: An Explanation of RSA Encryption and Decryption in the ASP.NET Core and Framework

clock September 2, 2024 08:39 by author Peter

An asymmetric cryptography algorithm is the RSA algorithm. In actuality, asymmetric refers to the fact that it operates on both the public and private keys. As implied by the name, the private key is kept secret while the public key is distributed to everybody. I've used the BouncyCastle package for RSA encryption and decryption in the sample below.

Notes

  • Key Size: The example uses a 2048-bit key, which is a common and secure size for RSA.
  • Encoding: Data is encoded as UTF-8 before encryption and decoded back after decryption.
  • Security: Always handle and store keys securely. Exposing private keys or mishandling encrypted data can compromise security.

Step 1. First, you need to install the BouncyCastle package. You can do this via NuGet.

Step 2. Import the required package into the service.
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;


Encryption Complete method
public  string EncryptRSA(string plaintext)
{
    string encryptedText = "";
    byte[] plaintextBytes = Encoding.UTF8.GetBytes(plaintext);

    // Load the public key from a PEM string or file
    string publicKeyPem = @""; // Replace your public key here
    AsymmetricKeyParameter publicKey;
    using (var reader = new StringReader(publicKeyPem))
    {
        PemReader pemReader = new PemReader(reader);
        publicKey = (AsymmetricKeyParameter)pemReader.ReadObject();
    }
    // Initialize the RSA engine for encryption with the public key
    IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaEngine());
    rsaEngine.Init(true, publicKey); // true for encryption
    // Encrypt the data
    byte[] encryptedData = rsaEngine.ProcessBlock(plaintextBytes, 0, plaintextBytes.Length);
    // Convert the encrypted data to a Base64 string for easy transmission/storage
    encryptedText = Convert.ToBase64String(encryptedData);
    return encryptedText;
}


Breakdown of the encryption method

Step 1
plaintextBytes: The input string is converted to a byte array using UTF-8 encoding. This byte array represents the data to be encrypted.
byte[] plaintextBytes = Encoding.UTF8.GetBytes(plaintext);

Step 2

StringReader: The publicKeyPem string is passed to a StringReader to create a text reader.
PemReader: This reads the PEM-formatted key and converts it into an AsymmetricKeyParameter object.
using (var reader = new StringReader(publicKeyPem))
{
    PemReader pemReader = new PemReader(reader);
    publicKey = (AsymmetricKeyParameter)pemReader.ReadObject();
}

Step 3

  • IAsymmetricBlockCipher: This interface represents the RSA encryption engine.
  • Pkcs1Encoding: This wraps the RsaEngine to add PKCS#1 padding, which is commonly used in RSA encryption.
  • Init Method: The RSA engine is initialized for encryption by passing true along with the public key.

IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaEngine());
rsaEngine.Init(true, publicKey); // true for encryption


Step 4

  • ProcessBlock: This method processes the data (encrypts it) using the initialized RSA engine. It takes the plaintext bytes and returns the encrypted byte array.
  • Convert.ToBase64String: The encrypted byte array is converted to a Base64 string. Base64 encoding is used to make the encrypted data easier to transmit or store, as it converts binary data into ASCII string format.

byte[] encryptedData = rsaEngine.ProcessBlock(plaintextBytes, 0, plaintextBytes.Length);
encryptedText = Convert.ToBase64String(encryptedData);

Output Sample for RSA Encryption

Decryption Complete method
public string DecryptRSA(string encryptedText)
{
    string decryptedText = "";
    try
    {

        string pemPrivateKey = @""; // Replace your private key here
        RsaPrivateCrtKeyParameters keyPair;
        using (var reader = new StringReader(pemPrivateKey))
        {
            keyPair = (RsaPrivateCrtKeyParameters)new PemReader(reader).ReadObject();
        }
        var rsaParams = DotNetUtilities.ToRSAParameters(keyPair);
        using (var rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(rsaParams);
            // Convert encrypted text from Base64
            byte[] encryptedData = Convert.FromBase64String(encryptedText);
            // Decrypt the data
            byte[] decryptedData = rsa.Decrypt(encryptedData, RSAEncryptionPadding.Pkcs1);
            return Encoding.UTF8.GetString(decryptedData);
        }
    }
    catch { }
    return decryptedText;
}


Output sample for decryption


Conclusion

  • The method loads a public RSA key from a PEM string.
  • It initializes an RSA encryption engine using BouncyCastle.
  • The plaintext is encrypted using the public key, and the resulting encrypted data is returned as a Base64-encoded string.

This encryption method ensures that the plaintext is securely transformed into an encrypted format using the RSA algorithm, which can then only be decrypted by the corresponding private key.

HostForLIFE ASP.NET Core 9.0 Hosting

European Best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in