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 Hosting - HostForLIFE :: Compare Core APIs with Code using ASP.NET SOAP Services

clock February 17, 2025 07:51 by author Peter

In enterprise application development, SOAP (Simple Object Access Protocol) services have long been an integral part of enterprise application development, especially in industries such as financial services, healthcare, and government, where structured communication is required. Ziggy Rafiq compares two critical approaches to SOAP service implementation in the .NET ecosystem: ASMX and CoreWCF for ASP.NET Core SOAP APIs. The purpose of this article is to help developers choose the best SOAP implementation for their application by providing practical examples of the two SOAP implementations.

The following are some of the things you will learn from this article:

  • Maintenance and enhancement of legacy SOAP services are done through the use of ASMX.
  • With CoreWCF, you can create ASP.NET Core APIs that are scalable, cross-platform, and compatible with multiple platforms.
  • Make sure you select the right framework for your application based on its requirements.

The guide is invaluable for developers integrating modern SOAP solutions with REST and gRPC or transitioning to modern SOAP solutions.

The ASP.NET SOAP Web Services (ASMX)
ASP.NET SOAP Web Services (ASMX), as part of the ASP.NET Framework, provide a method for exposing methods as SOAP services that clients can consume over HTTP; these services were the go-to solution for SOAP-based communication in early ASP.NET applications for SOAP-based communication over the internet.

ASMX Features
Built-in support for SOAP: ASMX services support SOAP by automatically generating SOAP envelopes and annotating methods with the [WebMethod] attribute.
Auto-generated WSDL: When you create an ASMX service, a WSDL file is automatically generated, which clients can use to understand how the service works.
Platform limitations: In cross-platform environments, ASMX services are less flexible because they require IIS (Internet Information Services) to host them, making them more limited.

ASMX Web Service Code Example
The following steps will guide you through creating an ASMX web service in the .NET Framework:
1. Visual Studio should be used to create an ASP.NET Web Forms project.

2. Assemble a calculator service by adding a .asmx file to your project (such as CalculatorService.asmx).

 

3. The service should be implemented with the [WebMethod] attribute.
An example of a simple calculator service is as follows:
using System.Web.Services;

namespace ASMXService
{
    /// <summary>
    /// Summary description for CalculatorService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    // [System.Web.Script.Services.ScriptService]
    public class CalculatorService : System.Web.Services.WebService
    {

        [WebMethod]
        public int Add(int a, int b)
        {
            return a + b;
        }

        [WebMethod]
        public int Subtract(int a, int b)
        {
            return a - b;
        }

    }
}


How to Create and Run a Program?

  • Visual Studio should be used to create an ASP.NET Web Forms project.
  • Make sure your project contains an ASSMX file.
  • The above code should be added to your service.
  • You can view the auto-generated WSDL by visiting the .asmx file in the browser after running the project.

How Do ASP.NET Core SOAP APIs Work?
In ASP.NET Core, Microsoft's cross-platform framework, SOAP services aren't built in, but developers can use CoreWCF to create SOAP-based APIs. The CoreWCF project brings WCF-like functionality to .NET Core, allowing developers to develop SOAP APIs in a modern, scalable, and cross-platform environment.

CoreWCF SOAP APIs for ASP.NET Core

  • Requires CoreWCF for SOAP implementation: In contrast to ASMX, ASP.NET Core does not come with SOAP support by default but can be added using CoreWCF.
  • Cross-platform support: CoreWCF services can be run on Windows, Linux, and macOS, making them suitable for modern cloud-native applications.
  • Integration with modern features: ASP.NET Core features such as middleware, dependency injection, and performance scalability are integrated into CoreWCF.

ASP.NET Core SOAP API Code Example
The following steps will help you create a SOAP API in ASP.NET Core using CoreWCF:

Step 1. The following NuGet packages are required to install CoreWCF:
dotnet add package CoreWCF
dotnet add package CoreWCF.Http


Step 2. Use the [ServiceContract] and [OperationContract] attributes to define the service contract:
using CoreWCF;

namespace CoreWCFService.Contracts.Interfaces;

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract]
    double Add(double a, double b);

    [OperationContract]
    double Subtract(double a, double b);

    [OperationContract]
    double Multiply(double a, double b);

    [OperationContract]
    double Divide(double a, double b);

}

Step 3. Creating a class that inherits from the service contract is the first step toward implementing the service:
using CoreWCFService.Contracts.Interfaces;

namespace CoreWCFService.Contracts;
public class CalculatorService : ICalculatorService
{
    public double Add(double a, double b) => a + b;
    public double Subtract(double a, double b) => a - b;
    public double Multiply(double a, double b) => a * b;
    public double Divide(double a, double b) => b != 0 ? a / b : throw new DivideByZeroException("It cannot be divide by zero.");

}

Step 4. Program.cs should be configured with CoreWCF. Configure CoreWCF by adding the following lines:
using CoreWCF;
using CoreWCF.Configuration;
using CoreWCFService.Contracts;
using CoreWCFService.Contracts.Interfaces;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddServiceModelServices();
builder.Services.AddServiceModelMetadata();

builder.Services.AddSingleton<CalculatorService>();


builder.Services.AddOpenApi();

var app = builder.Build();


((IApplicationBuilder)app).UseServiceModel(builder =>
{
    builder.AddService<CalculatorService>();
    builder.AddServiceEndpoint<CalculatorService, ICalculatorService>(
        new BasicHttpBinding(), "/CalculatorService");
});


app.MapGet("/calculate/add/{a}/{b}", (double a, double b, CalculatorService service) =>
{
    return Results.Ok(new { Result = service.Add(a, b) });
}).WithName("AddNumbers");

app.MapGet("/calculate/subtract/{a}/{b}", (double a, double b, CalculatorService service) =>
{
    return Results.Ok(new { Result = service.Subtract(a, b) });
}).WithName("SubtractNumbers");

app.MapGet("/calculate/multiply/{a}/{b}", (double a, double b, CalculatorService service) =>
{
    return Results.Ok(new { Result = service.Multiply(a, b) });
}).WithName("MultiplyNumbers");

app.MapGet("/calculate/divide/{a}/{b}", (double a, double b, CalculatorService service) =>
{
    if (b == 0)
        return Results.BadRequest("Cannot divide by zero.");

    return Results.Ok(new { Result = service.Divide(a, b) });
}).WithName("DivideNumbers");


if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();
app.Run();

# CoreWCFService.http Example
@CoreWCFService_HostAddress = http://localhost:5071

GET {{CoreWCFService_HostAddress}}/calculate/add/15/10
Accept: application/json

###
{
  "Result": 25
}

GET {{CoreWCFService_HostAddress}}/calculate/subtract/20/5
Accept: application/json

###
{
  "Result": 15
}

GET {{CoreWCFService_HostAddress}}/calculate/multiply/20/5
Accept: application/json

###
{
  "Result": 100
}

GET {{CoreWCFService_HostAddress}}/calculate/divide/20/4
Accept: application/json

###
{
  "Result": 5
}

GET {{CoreWCFService_HostAddress}}/calculate/divide/50/0
Accept: application/json

###
{
  "Error": "It cannot be divide by zero."
}


Step 5. Test the SOAP API. After running the application, navigate to /CalculatorService?wsdl to view the WSDL. Then, use tools like Postman or SOAP UI to test the SOAP service.

Differentiating ASMX from ASP.NET Core

Feature ASP.net SOAP Web Services (ASMX) ASP.net Core SOAP APIs (CoreWCF)
Framework .Net Framework ASP.net Core
Cross-Platform Support No Yes
Middleware and DI Support No Yes
Performance Moderate High
SOAP Support Built-In Require CoreWCF
Ideally User Case When looking after Legacy/Old Applications and System. Modern applications and systems are built in the current day.

When to Choose Which?

When to Choose Which?

  • In the following situations, you should use ASP.NET SOAP Web Services (ASMX):
  • ASMX is heavily used in legacy applications you maintain.

For your project, migrating to ASP.NET Core isn't feasible or cost-effective.

ASP.NET Core SOAP APIs (CoreWCF) are recommended if:

  • The SOAP-based services you are building are being developed.
  • A cross-platform solution must be scalable and support multiple platforms.
  • Modern technologies such as REST, gRPC, or message queues can be integrated with SOAP.

Summary

While ASMX Web Services can still be used to maintain legacy applications, ASP.NET Core SOAP APIs, which are driven by CoreWCF, provide greater performance, flexibility, and support for contemporary development techniques. CoreWCF is the ideal option for contemporary enterprise applications since it can produce scalable, cross-platform SOAP services. By using CoreWCF, developers can easily combine their SOAP solutions with more recent technologies like REST and gRPC, future-proofing their systems.

The code for this article can be found on Ziggy Rafiq's GitHub Repository https://github.com/ziggyrafiq/SOAP-Services-Comparison  This is for developers who need to maintain legacy SOAP services while transitioning to modern, scalable SOAP solutions or integrating SOAP into a broader ecosystem of modern web services.

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Configuring Dynamic CORS with JSON in.NET Core

clock February 10, 2025 06:26 by author Peter

A crucial component of online applications is Cross-Origin Resource Sharing (CORS), which permits or prohibits the sharing of resources between several origins (domains). The client and server of a contemporary web application are frequently housed on separate domains. When the client sends HTTP requests to the server, this may result in CORS problems. We'll look at how to set up CORS to dynamically permit numerous origins from your appsettings in this post.in a.NET Core JSON file.

Configure CORS in the appsettings.JSON

We must first specify the permitted origins in the appsettings.json file in order to permit multiple origins. The list of URLs (origins) from which cross-origin requests are permitted will be stored here.

{
  "Cors": {
    "AllowedOrigins": [
      "https://example1.com",
      "https://example2.com",
      "https://example3.com"
    ]
  }
}


Read the Configuration in Program.cs
var builder = WebApplication.CreateBuilder(args);
// Get allowed origins from appsettings.json
var allowedOrigins = builder.Configuration
    .GetSection("Cors:AllowedOrigins")
    .Get<string[]>();
// Add CORS policy
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowSpecificOrigins",
        builder => builder.WithOrigins(allowedOrigins) // Apply multiple origins dynamically
                          .AllowAnyMethod()
                          .AllowAnyHeader());
});
// Add services to the container (e.g., AddControllers)
builder.Services.AddControllers();
var app = builder.Build();
// Use CORS policy
app.UseCors("AllowSpecificOrigins");
// Configure the HTTP request pipeline
app.MapControllers();
app.Run();


Apply CORS Policy in the Middleware

// Apply the CORS policy globally
app.UseCors("AllowSpecificOrigins");
// Other middleware (e.g., UseRouting, UseEndpoints)


Conclusion
Using appsettings.json to manage CORS settings in your .NET Core 9 application allows for greater flexibility and better maintainability. You can easily add or remove origins without changing your application's code. This is particularly useful when deploying your application to different environments (development, staging, production) with different origin policies. By following these steps, you can dynamically configure and manage multiple allowed origins for your application.

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: KnightMoves.SqlObjects: An Improved.NET SQL Builder

clock February 5, 2025 05:47 by author Peter

KnightMoves.A.NET NuGet package library called SqlObjects implements an object-based SQL builder. This package uses a different approach than other SQL compilers, which rely on string manipulation techniques like concatenation and interpolation. This package wraps the syntax of the SQL language with C# objects instead of printing SQL strings, making a SQL query entirely composed of objects. In comparison to string manipulators, this enables a far more potent experience and set of capabilities.

Syntax Matching
Some ORMs and SQL builders use method names that are similar but different from the SQL language. This library matches the SQL syntax almost exactly, with some minor exceptions. The strategy for this library is that when you're using the SQL builder, you are able to think and code in SQL instead of trying to remember the new terminology of the SQL builder.

Let's dive in with some examples.

Examples
First, create a simple Console application in Visual Studio and add KnightMoves.SqlObjects NuGet package library from https://nuget.org.

Once you have a basic console application generated, you can add your code to the Main() method of the Program.cs file.

Start with importing the namespace.
using KnightMoves.SqlObjects;

Next, you add the code below to the Main() method.

The fluent SQL builder is available through the static TSQL class so you can begin there and code as much as though you’re coding in SQL.
var sql = TSQL

   .SELECT()
   .STAR()
   .FROM("Products")
   .Build()

;

Console.WriteLine(sql);

Run the application to see how the SQL is built. Here's the output:
SELECT
   *
FROM [Products]


That used a basic SELECT * but there are various ways to specify the columns of the select list. The most basic way is to use the COLUMN() method for each column you specify.

var sql = TSQL

   .SELECT()
     .COLUMN("ProductID")
     .COLUMN("ProductName")
   .FROM("Products")
   .Build()

;

Console.WriteLine(sql);


Here's the output:
SELECT
 [ProductID],
 [ProductName]
FROM [Products]


But we’re just getting started. You can provide a collection of column names and pass that to the COLUMNS() method (notice it is plural) and it will use those names to create the list of columns.

var columns = new List { "ProductID", "ProductName" };

var sql = TSQL

     .SELECT()
       .COLUMNS(columns)
     .FROM("dbo", "Products", "p")
     .Build()

;

Console.WriteLine(sql);


Output
SELECT
 [ProductID],
 [ProductName]
FROM [dbo].[Products] p


If you know SQL well, then you know that there are all manner of things you can do in the select list to make it a more robust query. This library handles them. Let’s start with a simple alias using .AS().

var sql = TSQL

   .SELECT()
     .COLUMN("ProductID").AS("Id")
     .COLUMN("ProductName")
   .FROM("Products")
   .Build()

;


Output
SELECT
 [ProductID] AS [Id],
 [ProductName]
FROM [Products]


You can see it correctly produces the line [ProductID] AS [Id]

Do you need to specify the schema and a multipart identifier? Easy. Suppose you’re using dbo as the schema and p as an alias for the Products table. Then you can do so like this.
var sql = TSQL

   .SELECT()
     .COLUMN("p", "ProductID", "Id")
     .COLUMN("p", "ProductName")
   .FROM("dbo", "Products", "p")
   .Build()

;

Console.WriteLine(sql);

Output
SELECT
 [p].[ProductID] AS [Id],
 [p].[ProductName]
FROM [dbo].[Products] p

You can also see an alternative to provide the alias. Instead of using .AS() you can provide the alias as a third parameter to the COLUMN() method.

It’s a pain to keep repeating the COLUMN() method call, and we know that we can use a collection of column names, but what if we need to prefix them with the table alias? Easy, we can do it like this.
var columns = new List { "ProductID", "ProductName" };

var sql = TSQL

     .SELECT()
       .COLUMNS("p", columns)
     .FROM("dbo", "Products", "p")
     .Build()

;

Console.WriteLine(sql);

Output
SELECT
 [p].[ProductID],
 [p].[ProductName]
FROM [dbo].[Products] p


The use of aliases becomes more important when you’re joining tables. So, let’s give that a try by joining Products and Categories.
var sql = TSQL

     .SELECT()
       .COLUMN("p", "ProductID")
       .COLUMN("c", "CategoryName")
     .FROM("dbo", "Products", "p")
     .INNERJOIN("dbo", "Categories", "c").ON("c", "CategoryID").IsEqualTo("p", "CategoryID")
     .Build()

;

Console.WriteLine(sql);


Output
SELECT
 [p].[ProductID],
 [c].[CategoryName]
FROM [dbo].[Products] p
INNER JOIN [dbo].[Categories] c ON [c].[CategoryID] = [p].[CategoryID]


If you need to join more tables, then all you have to do is slap another INNERJOIN() call exactly where you normally would if you’re coding in SQL with the schema and alias like so.
var sql = TSQL

 .SELECT()
   .COLUMN("p", "ProductID")
   .COLUMN("p", "ProductName")
   .COLUMN("c", "CategoryName")
   .COLUMN("s", "CompanyName")
 .FROM("dbo", "Products", "p")
 .INNERJOIN("dbo", "Categories", "c").ON("c", "CategoryID").IsEqualTo("p", "CategoryID")
 .INNERJOIN("dbo", "Suppliers", "s").ON("s", "SupplierID").IsEqualTo("p", "SupplierID")
 .Build()

;

Console.WriteLine(sql);

Output
SELECT
 [p].[ProductID],
 [p].[ProductName],
 [c].[CategoryName],
 [s].[CompanyName]
FROM [dbo].[Products] p
INNER JOIN [dbo].[Categories] c ON [c].[CategoryID] = [p].[CategoryID]
INNER JOIN [dbo].[Suppliers] s ON [s].[SupplierID] = [p].[SupplierID]


Notice that throughout this demo, you can see that when you're using this library, you can think in SQL terms. Some things will deviate slightly, such as the use of COLUMN() instead of just literally typing in the column name where it belongs and later you’ll see that we use a fluent method call for operators such as IsEqualTo() instead of the = string character, but the thought process is the same. You're thinking in SQL even though you're coding in C#.

For further assistance, because the library is SQL in C# dressing, its methods, and signatures pop up in the intelicode features of the IDE, where you can search through the options to find what you're looking for easily.


We are barely scratching the surface here. The library implements all DML statements of Microsoft's T-SQL language, which is fully documented here: KnightMoves.SqlObject Documentation. Head on over there to get started and see what you can do with the basics. Stay tuned for other articles in this series, where we’ll cover more and more features of this robust library. Thanks for reading this far. I sincerely hope you enjoy this library as much as I enjoyed making it.

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Dynamic Rules Engine for.NET Financial App User Workflows

clock January 20, 2025 07:55 by author Peter

You must create a system that enables flexible, dynamic rule generation and execution based on user context (such as roles, account details, transaction kinds, etc.) in order to use.NET to implement a Rules Engine for user-specific workflows in a financial application. For business logic, a rules engine offers an abstraction layer that makes upgrades, maintenance, and user-specific adaptations simple.

1. Understand the Financial Domain
Financial applications typically deal with transactions, account balances, regulatory requirements, fraud detection, and other rules that can be user- or context-specific. In this example, let’s assume we're building a rules engine for managing financial transactions where rules need to be applied based on.

  • Account type (savings, checking, business, etc.).
  • Transaction type (deposit, withdrawal, transfer, etc.).
  • Transaction amount.
  • User role (admin, regular user, auditor, etc.).
  • User-specific preferences (risk appetite, investment profile).

2. Define the Rule Structure

A rule typically contains.

  • Condition: The condition or predicate that must be true for the rule to execute (e.g., transaction amount > $500).
  • Action: The result or effect if the rule is triggered (e.g., send a notification, log an event, or block the transaction).
  • User Context: The context in which the rule is evaluated (e.g., user role, account type).

In the financial system, rules might look like.

  • If the transaction amount is> $1000 and the account type is business, fraud detection is triggered.
  • If the account balance is < $50 and the withdrawal request is for $100, block the withdrawal.

3. Create a Rule Interface
Create a base interface for rules that can be implemented for different types of rules.
public interface IRule
{
bool Evaluate(UserContext context, Transaction transaction);
void Execute(Transaction transaction);
}

4. Define Specific Rule Implementations
Implement specific rules based on the financial domain.

Example: Transaction Amount Limit Rule.
public class TransactionAmountLimitRule : IRule
{
private readonly decimal _limit;
public TransactionAmountLimitRule(decimal limit)
{
    _limit = limit;
}
public bool Evaluate(UserContext context, Transaction transaction)
{
    return transaction.Amount > _limit;
}
public void Execute(Transaction transaction)
{
    Console.WriteLine($"Transaction amount exceeds the limit of {_limit}. Action required.");
}
}

Example: Account Type and Fraud Detection Rule.
public class FraudDetectionRule : IRule
{
public bool Evaluate(UserContext context, Transaction transaction)
{
    return transaction.Amount > 1000 && context.AccountType == "Business";
}

public void Execute(Transaction transaction)
{
    Console.WriteLine($"Fraud detection triggered for transaction of {transaction.Amount} on business account.");
    // Integrate with a fraud detection system here
}
}


5. Create the User Context and Transaction Classes
Define classes to represent user and transaction data. These objects will be passed to the rules engine to evaluate whether a rule should fire.
public class UserContext
{
public string Role { get; set; }
public string AccountType { get; set; }
public decimal AccountBalance { get; set; }

// Other user-specific data...
}

public class Transaction
{
public decimal Amount { get; set; }
public string TransactionType { get; set; }
public string AccountId { get; set; }

// Other transaction details...
}

6. Rules Engine Execution
The core of the rules engine is to evaluate the conditions and execute the rules. You can use a chain of responsibility pattern, a strategy pattern, or a simple loop to apply the rules.
public class RulesEngine
{
private readonly List<IRule> _rules;
public RulesEngine()
{
    _rules = new List<IRule>();
}
public void AddRule(IRule rule)
{
    _rules.Add(rule);
}
public void ExecuteRules(UserContext context, Transaction transaction)
{
    foreach (var rule in _rules)
    {
        if (rule.Evaluate(context, transaction))
        {
            rule.Execute(transaction);
        }
    }
}
}


7. Implementing User-Specific Workflow
Depending on the user’s role or account type, different rules might be triggered. For example.
A "Premium User" might have different transaction limits.
An "Admin" may be exempt from certain fraud detection rules.

var userContext = new UserContext
{
Role = "Regular",
AccountType = "Business",
AccountBalance = 1200
};
var transaction = new Transaction
{
Amount = 1500,
TransactionType = "Withdrawal",
AccountId = "12345"
};
// Initialize rules engine and add rules
var rulesEngine = new RulesEngine();
rulesEngine.AddRule(new TransactionAmountLimitRule(1000));
rulesEngine.AddRule(new FraudDetectionRule());
// Execute rules for the given context and transaction
rulesEngine.ExecuteRules(userContext, transaction);

8. User-Specific Workflow Example
In practice, rules can be set up to dynamically adjust based on the user context.
if (userContext.Role == "Premium")
{
rulesEngine.AddRule(new TransactionAmountLimitRule(5000));  // Higher limit for premium users
}
else if (userContext.Role == "Admin")
{
rulesEngine.AddRule(new NoFraudDetectionRule());  // Admin users may not be subject to fraud detection
}
// Then, execute the rules for the user's specific context
rulesEngine.ExecuteRules(userContext, transaction);


9. Persisting and Managing Rules Dynamically
For flexibility, you can store the rules in a database, and even allow rules to be edited via an admin UI. This allows you to modify workflows without changing the application code.

  • Store rules as JSON, XML, or database records.
  • Load rules dynamically based on the user or transaction type.
  • Allow admins to manage rules from a UI or API.

For dynamic rule evaluation.
public class DynamicRuleLoader
{
public IEnumerable<IRule> LoadRules(UserContext userContext)
{
    // Query database or external source to load applicable rules for the user
    return new List<IRule>
    {
        new TransactionAmountLimitRule(1000),
        new FraudDetectionRule()
    };
}
}


10. Testing and Maintenance

  • Unit Testing: Each rule can be unit tested independently by mocking user contexts and transactions.
  • Performance Considerations: Optimize for performance if the rules engine is large or if rules are complex. For example, caching user-specific rules, batching rule evaluations, or implementing a priority queue for rule execution.
  • Audit Logging: For financial systems, ensure that rule evaluations and their outcomes are logged for compliance and auditing purposes.

Incorporating a dynamic and flexible rules engine for user-specific workflows in a . NET-based financial application can significantly enhance the system's ability to handle diverse business logic, user contexts, and complex transaction scenarios. By leveraging a well-structured rules engine, financial institutions can ensure that transaction processing, fraud detection, and user-specific workflows are handled efficiently and consistently.

The system can be tailored to meet evolving business demands, regulatory compliance, and user preferences by defining rules based on a variety of user factors (like roles, account types, and preferences) and transaction characteristics (like amount, type, and status). Business rules can be updated without requiring significant modifications to the underlying software thanks to the separation of business rules from core application logic, which also makes maintenance and future scaling easier.

Additionally, businesses can modify and adapt the workflow to changing requirements or user-specific scenarios by putting in place a dynamic rules-loading system and providing administrative interfaces for controlling rules. In addition to improving user experience and operational efficiency, this guarantees that the application remains responsive to evolving requirements and regulatory changes.

In the end, this strategy not only gives financial institutions the opportunity to automate and streamline decision-making procedures, but it also permits increased control, transparency, and auditability—all of which are essential for upholding compliance and confidence in the heavily regulated financial sector.

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: The .NET Build Tools 8.0.0 to 8.0.11 Breaking Changes

clock January 15, 2025 06:16 by author Peter

Builds and applications stopped working when I upgraded to.NET 8.0.11, and I began to receive errors. I was seeing errors like "error MSB4018: …" and "hostpolicy.dll...not found." I was unable to locate singlefilehost.exe.

1. Problem description
Build project settings all worked well somewhere around .NET 8.0.0. Later, with the upgrade of .NET runtime to later versions of .NET 8.0 and .NET 9.0 and an upgrade to Visual Studio, some of the projects stopped working. It looks like they introduced breaking changes in the build tools. Logic is still sound, and build types are the same; just the build tools started to behave a bit differently. New build configurations and build scripts are needed. I think I can locate the change in behavior somewhere between (.NET Framework 8.0.0/.NET SDK 8.0.100) and (.NET Framework 8.0.11/.NET SDK 8.0.404). Not all, but some project builds failed.

1.1. The environment

The typical environment to which this article applies is C#/VS2022.

.NET version 8.0.11 or later
And you are building project type SelfContained or SIngleFile.

1.2. Problem manifestation
You get Errors/Exceptions

  • The library 'hostpolicy.dll' required to execute the application was not found.
  • error MSB4018: …. Could not find file ….. singlefilehost.exe.

+++Error1, When running the application:++++++++++++++++++++

A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application
was not found in 'C:\Program Files\dotnet\'.
Failed to run as a self-contained app.
  - The application was run as a self-contained app because
  'C:\tmpNetBundle\BundleExample02_NET90\ConsoleApp2C\
  SelfContained_SingleFile_win-x64\ConsoleApp2C.runtimeconfig.json'
  was not found.
  - If this should be a framework-dependent app, add the 'C:\tmpNetBundle\BundleExample02_NET90\ConsoleApp2C\
  SelfContained_SingleFile_win-x64\ConsoleApp2C.runtimeconfig.json'
  file and specify the appropriate framework.

PS C:\tmpNetBundle\BundleExample02_NET90\ConsoleApp2C\
SelfContained_SingleFile_win-x64>

+++Error2, During build++++++++++++++++++++

error MSB4018: The "GenerateBundle" task failed unexpectedly.
[C:\tmpNetBundle\BundleExample01_NET_8.0.0_SDK_8.0.100\ConsoleApp2\ConsoleApp2.csproj]
error MSB4018: System.IO.FileNotFoundException: Could not find file
'C:\tmpNetBundle\BundleExample01_NET_8.0.0_SDK_8.0.100\ConsoleApp2\
obj\Release\net8.0-windows\win-x64\singlefilehost.exe'.


1.3. Cause of problem and resolution
It looks like the flag <PublishSingleFile>true</PublishSingleFile> in the project file .csproj stopped to work in some cases. I was relying on that flag in my build scripts after that. No problem, we can anticipate that thing, just when we know what to expect.

It looks like the build process invoked “dotnet publish” from .NET SDK 9.* for projects that I was building for .NET 8.* framework. So, I decided to use a global.json file to explicitly specify which SDK I want to use.

2. Code Samples
These are old build settings that worked in NET_8.0.0/SDK_8.0.100 but stopped working in later versions.
// NET_8.0.0/SDK_8.0.100
// NOTE: These project settings all worked well somewhere around .NET 8.0.0.
// Later, with the upgrade of .NET runtime to later versions of .NET 8.0 and .NET 9.0
// and an upgrade to Visual Studio, some of projects stopped working. It looks like
// they introduced breaking changes in the build tools. Logic is still sound and build
// types are the same, just the build tools started to behave a bit differently. A new
// build configurations and build scripts are needed.

<!--ConsoleApp2C.csproj +++++++++++++++++++++++++++++++++++++-->
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0-windows</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PlatformTarget>x64</PlatformTarget>
        <Platforms>AnyCPU;x64</Platforms>
        <RuntimeIdentifier>win-x64</RuntimeIdentifier>
        <DebugType>embedded</DebugType>
        <PublishSingleFile>true</PublishSingleFile>
        <PublishTrimmed>true</PublishTrimmed>
        <IsTrimmable>true</IsTrimmable>
        <SelfContained>true</SelfContained>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
    </PropertyGroup>

    <ItemGroup>
        <ProjectReference Include="..\ClassLibrary1\ClassLibraryA.csproj" />
    </ItemGroup>

    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command="echo +++Post-Build+++++&#xD;&#xA;
        if $(ConfigurationName) == Debug (
        &#xD;&#xA;echo +++++Debug+++++                    &#xD;&#xA;) &#xD;&#xA;&#xD;&#xA;
        if $(ConfigurationName) == Release (&#xD;&#xA;
        echo +++++SelfContained_SingleFile_win-x64.cmd+++++    &#xD;&#xA;
        call SelfContained_SingleFile_win-x64.cmd         &#xD;&#xA;
        echo +++++SelfContained_SingleFile_win-x64_Trimmed.cmd+++++    &#xD;&#xA;
        call SelfContained_SingleFile_win-x64_Trimmed.cmd         &#xD;&#xA;)    " />
    </Target>

</Project>

+++++Script: SelfContained_SingleFile_win-x64.cmd
dotnet publish ConsoleApp2C.csproj --no-build --runtime win-x64 --configuration Release
   -p:PublishSingleFile=true -p:SelfContained=true -p:PublishReadyToRun=false
   -p:PublishTrimmed=false --output ./SelfContained_SingleFile_win-x64

+++++Script: SelfContained_SingleFile_win-x64_Trimmed.cmd
dotnet publish ConsoleApp2C.csproj --no-build --runtime win-x64 --configuration Release
   -p:PublishSingleFile=true -p:SelfContained=true -p:PublishReadyToRun=false
   -p:PublishTrimmed=true --output ./SelfContained_SingleFile_win-x64_Trimmed


These are new build settings that work in NET_8.0.11/SDK_8.0.404.
// NET_8.0.11/SDK_8.0.404

<!--ConsoleApp2C.csproj +++++++++++++++++++++++++++++++++++++-->
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0-windows</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PlatformTarget>x64</PlatformTarget>
        <Platforms>AnyCPU;x64</Platforms>
        <RuntimeIdentifier>win-x64</RuntimeIdentifier>
        <DebugType>embedded</DebugType>
        <PublishSingleFile>true</PublishSingleFile>
        <PublishTrimmed>true</PublishTrimmed>
        <IsTrimmable>true</IsTrimmable>
        <SelfContained>true</SelfContained>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
    </ItemGroup>

    <ItemGroup>
        <ProjectReference Include="..\ClassLibrary1\ClassLibraryA.csproj" />
    </ItemGroup>

    <Target Name="RunAfterBuild1" AfterTargets="Build">
        <Exec Command="call SelfContained_SingleFile_win-x64.cmd"
        Condition=" '$(BuildingInsideVisualStudio)' == 'true' "/>
    </Target>

    <Target Name="RunAfterBuild2" AfterTargets="Build">
        <Exec Command="call SelfContained_SingleFile_win-x64_Trimmed.cmd"
        Condition=" '$(BuildingInsideVisualStudio)' == 'true' "/>
    </Target>

</Project>

+++++Script: SelfContained_SingleFile_win-x64.cmd
echo .NET SDK version:
dotnet --version
dotnet publish ConsoleApp2C.csproj --nologo --no-restore --runtime win-x64
--configuration Release   -p:PublishSingleFile=true -p:SelfContained=true
-p:PublishReadyToRun=false  -p:PublishTrimmed=false
--output ./SelfContained_SingleFile_win-x64

+++++Script: SelfContained_SingleFile_win-x64_Trimmed.cmd
echo .NET SDK version:
dotnet --version
dotnet publish ConsoleApp2C.csproj --nologo --no-restore --runtime win-x64
 --configuration Release   -p:PublishSingleFile=true -p:SelfContained=true
 -p:PublishReadyToRun=false  -p:PublishTrimmed=true
 --output ./SelfContained_SingleFile_win-x64_Trimmed

+++++Configfile: global.json
{
  "sdk": {
    "version": "8.0.404"
  }
}

These are new build settings that work in NET_9.0.0/SDK_9.0.101.
// NET_9.0.0/SDK_9.0.101

<!--ConsoleApp3C.csproj +++++++++++++++++++++++++++++++++++++-->
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0-windows7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PlatformTarget>x64</PlatformTarget>
        <Platforms>AnyCPU;x64</Platforms>
        <RuntimeIdentifier>win-x64</RuntimeIdentifier>
        <DebugType>embedded</DebugType>
        <PublishSingleFile>true</PublishSingleFile>
        <PublishTrimmed>true</PublishTrimmed>
        <IsTrimmable>true</IsTrimmable>
        <SelfContained>true</SelfContained>
        <PublishReadyToRun>true</PublishReadyToRun>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
    </ItemGroup>

    <ItemGroup>
        <ProjectReference Include="..\ClassLibrary1\ClassLibraryA.csproj" />
    </ItemGroup>

    <Target Name="RunAfterBuild1" AfterTargets="Build">
        <Exec Command="call SelfContained_SingleFile_win-x64_ReadyToRun.cmd"
        Condition=" '$(BuildingInsideVisualStudio)' == 'true' " />
    </Target>

    <Target Name="RunAfterBuild2" AfterTargets="Build">
        <Exec Command="call SelfContained_SingleFile_win-x64_Trimmed_ReadyToRun.cmd"
        Condition=" '$(BuildingInsideVisualStudio)' == 'true' " />
    </Target>

</Project>

+++++Script: SelfContained_SingleFile_win-x64_ReadyToRun.cmd
echo .NET SDK version:
dotnet --version
dotnet publish ConsoleApp3C.csproj --nologo --no-restore --runtime win-x64
--configuration Release   -p:PublishSingleFile=true -p:SelfContained=true
-p:PublishTrimmed=false -p:PublishReadyToRun=true
--output ./SelfContained_SingleFile_win-x64_ReadyToRun

+++++Script: SelfContained_SingleFile_win-x64_Trimmed_ReadyToRun.cmd
echo .NET SDK version:
dotnet --version
dotnet publish ConsoleApp3C.csproj --nologo --no-restore --runtime win-x64
--configuration Release   -p:PublishSingleFile=true -p:SelfContained=true
-p:PublishReadyToRun=true  -p:PublishTrimmed=true
--output ./SelfContained_SingleFile_win-x64_Trimmed_ReadyToRun

+++++Configfile: global.json
{
  "sdk": {
    "version": "9.0.101"
  }
}

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Moq Unit Testing in .NET Core with xUnit

clock January 6, 2025 07:21 by author Peter

The smallest steps in the software development process are tested using a software design pattern known as unit testing. Unit testing is used to verify functionality and produce expected results before the QA Team and production environment proceed. It is advantageous to identify issues early in the software development cycle.

NUnit, xUnit, and numerous additional unit test tools are included with the.NET Framework.

xUnit
For .NET development, xUnit is a free and open-source unit testing framework. There are numerous features in xUnit that make it easier to write clear and effective unit test cases. It offers a mechanism to create our own attributes in addition to numerous attributes, such as fact, theory, and many more, to help write test cases clearly and efficiently.

Features of the xUnit

  • xUnit in.NET uses the [Fact] attribute to specify the unit test method.
  • The test procedure's parameters are provided by the [Theory] attribute.

Creating a Testing Project
At last, we reach the stage where our tests will require the creation of a new project. We will take advantage of the handy xUnit testing project template that comes with Visual Studio 2022 when we use it. An open-source unit testing tool for the.NET framework called xUnit makes testing easier and frees up more time to concentrate on creating tests.

Moq
Fundamentally, the mocking library is called Moq.
If our application depends on one or more services, we can use the Moq library to mock certain classes and functionality using fake data instead of having to initialize everything associated with it.

Write some more unit tests, please! As you can see, the interface is being injected into our controller via Dependency Injection. Thus, through that injected interface, our controller is essentially dependent on the repository logic. That method is also highly advised and has no issues at all. However, we should isolate those dependencies when writing tests for our controller or any other class in a project.

The following are some benefits of dependency isolation in test code.

  • Our test code is significantly simpler because we don't need to initialize every dependency in order to return accurate values.
  • If our test fails and we don't isolate the dependency, we won't know if the failure was caused by a controller error or by the dependency itself.
  • Test code may run more slowly when dependent code interacts with an actual database, as our repository does. This may occur as a result of poor connections or just taking too long to retrieve data from the database.

You get the idea, though there are more justifications for isolating dependencies in test code.

Having said that, let's add the Moq library to the project Tests.

Install-Package Moq

OR

We are now prepared to write tests for our EmpController's first GetAll method.

The xUnit framework uses the [Fact] attribute, which we will use to decorate test methods to identify them as the real testing methods. In the test class, in addition to the test methods, we can have an infinite number of helper methods.

The AAA principle (Arrange, Act, and Assert) is typically followed when writing unit tests.

  • Arrange: this is the part where you usually get everything ready for the test or put another way, you get the scene ready for the test (making the objects and arranging them as needed).
  • Act: Here is where the procedure that we are testing is carried out.
  • Assert: In this last section of the test, we contrast the actual outcome of the test method's execution with our expectations.

Testing Our Actions
We will want to confirm the following in the Get method, which is the first method we are testing.

  • Whether the method yields the OkObjectResult, a response code of 200 for an HTTP request.
  • Whether the returned object includes every item in our list of Emps.

Testing the GET Method
using Microsoft.AspNetCore.Mvc;
using Moq;
using System.Linq.Expressions;
using WebApplication1.Contract;
using WebApplication1.Controllers;
using WebApplication1.Database;
using WebApplication1.Model;
using WebApplication1.Repository;

namespace TestDemo
{
    public class EmpControllerTest
    {
        private readonly EmpController _empController;
        private readonly Mock<IEmpRepository> _empRepository;

        public EmpControllerTest()
        {
            _empRepository = new Mock<IEmpRepository>();
            _empController = new EmpController(_empRepository.Object);
        }

        [Fact]
        public void GetAll_Success()
        {
            // Arrange
            var expectedResult = GetEmps().AsQueryable();
            _empRepository.Setup(x => x.GetAll(It.IsAny<FindOptions>())).Returns(expectedResult);

            // Act
            var response = _empController.Get();

            // Assert
            Assert.IsType<OkObjectResult>(response as OkObjectResult);
        }
    }
}

[Theory]
[InlineData("503df499-cabb-4699-8381-d76917365a9d")]
public void GetById_NotFound(Guid empId)
{
    // Arrange
    Emp? emp = null;
    _empRepository
        .Setup(x => x.FindOne(It.IsAny<Expression<Func<Emp, bool>>>(), It.IsAny<FindOptions?>()))
        .Returns(emp!);

    // Act
    var response = _empController.Get(empId);

    // Assert
    Assert.IsType<NotFoundObjectResult>(response as NotFoundObjectResult);
}

In case all of the unit test cases are passed, then it looks like the screenshot below.

In case any of the unit test cases fail, then it looks like the screenshot below.

Together, we evolved after learning the new method. Have fun with your coding!

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Introduction to ASP.NET Core's Minimal API

clock December 13, 2024 06:18 by author Peter

What is Minimal API?
ASP.NET Core Minimal APIs provide a streamlined approach to developing web APIs with minimal code. They prioritize conciseness, focusing on the core functionality of handling HTTP requests and responses.

Here are some key aspects of Minimal APIs:

  • Concise Syntax: They leverage top-level statements and lambda expressions to define endpoints in a very compact manner.
  • Reduced Boilerplate: Minimal APIs significantly reduce the amount of boilerplate code compared to traditional ASP.NET Core controllers.
  • Focus on Functionality: They encourage developers to prioritize the essential logic of handling requests and generating responses.
  • Flexibility: While concise, they still provide flexibility for more complex scenarios by allowing the use of middleware, dependency injection, and other features of the ASP.NET Core framework.

Let me explain with a CRUD example. (I have used .NET 9 as the target framework)
Create an ASP.NET Core Web API project with the following endpoints. In the program.cs file, add the following code.

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/api/apple/products",()=>Results.Ok("Get all Apple products"));
app.MapGet("/api/apple/products/{id}",(int id)=>Results.Ok($"Get Apple Product by id {id}"));
app.MapPost("/api/apple/products",()=>Results.Ok("Create an Apple product"));
app.MapPut("/api/apple/products/{id}",(int id)=>Results.Ok($"Update Apple product by id {id}"));
app.MapDelete("/api/apple/products/{id}",(int id)=>Results.Ok($"Delete Apple product by id {id}"));

app.Run();


Code Explanation

1. app.MapGet("/api/apple/products", () => Results.Ok("Get all Apple products"));

  • Endpoint: /api/apple/products
  • HTTP Method: GET
  • Action: This endpoint handles HTTP GET requests to the specified URL.
  • Response: It returns a 200 OK response with the message "Get all Apple products".

2. app.MapGet("/api/apple/products/{id}", (int id) => Results.Ok($"Get Apple Product by id {id}"));

  • Endpoint: /api/apple/products/{id}
  •     {id} is a route parameter that captures the ID of the product in the URL.
  • HTTP Method: GET
  • Action: This endpoint handles GET requests to the URL with a specific product ID.
  • Response: It returns a 200 OK response with a message indicating the ID of the retrieved product, e.g., "Get Apple Product by id 123".

3. app.MapPost("/api/apple/products", () => Results.Ok("Create an Apple product"));

  • Endpoint: /api/apple/products
  • HTTP Method: POST
  • Action: This endpoint handles POST requests to the URL.
  • Response: It returns a 200 OK response with the message "Create an Apple product".

4. app.MapPut("/api/apple/products/{id}", (int id) => Results.Ok($"Update Apple product by id {id}"));

  • Endpoint: /api/apple/products/{id}
  • HTTP Method: PUT
  • Action: This endpoint handles PUT requests to the URL with a specific product ID.
  • Response: It returns a 200 OK response with a message indicating the ID of the updated product, e.g., "Update Apple product by id 123".

5. app.MapDelete("/api/apple/products/{id}", (int id) => Results.Ok($"Delete Apple product by id {id}"));

  • Endpoint: /api/apple/products/{id}
  • HTTP Method: DELETE
  • Action: This endpoint handles DELETE requests to the URL with a specific product ID.
  • Response: It returns a 200 OK response with a message indicating the ID of the deleted product, e.g., "Delete Apple product by id 123".

Key Points

  • Minimal API Syntax: The code utilizes the concise syntax of Minimal APIs in ASP.NET Core.
  • Route Parameters: The {id} placeholder in the URL allows for dynamic routing based on the product ID.
  • Lambda Expressions: The endpoints are defined using lambda expressions, making the code more concise.
  • Results.Ok(): This helper method returns a 200 OK HTTP response with the specified message.

This is a basic example. In a real-world scenario, you would typically implement more complex logic within these endpoints, such as:

  • Data Access
  • Data Validation
  • Error Handling
  • Business Logic

Organizing Minimal APIs with MapGroup
MapGroup is a powerful feature in Minimal APIs that allows you to group related endpoints under a common path. This improves organization and readability, especially as your API grows in complexity.

Let me organize the above endpoints with MapGroup.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var appleProductsGroup = app.MapGroup("/api/apple/products");

appleProductsGroup.MapGet("",()=>Results.Ok("Get all Apple products"));
appleProductsGroup.MapGet("{id}",(int id)=>Results.Ok($"Get Apple Product by id {id}"));
appleProductsGroup.MapPost("",()=>Results.Ok("Create an Apple product"));
appleProductsGroup.MapPut("{id}",(int id)=>Results.Ok($"Update Apple product by id {id}"));
appleProductsGroup.MapDelete("{id}",(int id)=>Results.Ok($"Delete Apple product by id {id}"));

app.Run();


var appleProductsGroup = app.MapGroup("/api/apple/products");

This line creates a new route group named "appleProductsGroup" that will handle requests under the path "/api/apple/products".

Key Benefits

  • Improved Code Readability: Makes the API definition more organized and easier to understand.
  • Reduced Code Duplication: Avoids repeating middleware configurations for individual routes.
  • Enhanced Maintainability: It is easier to modify or add new routes within a specific group.

Minimal APIs in ASP.NET Core provide a refreshing approach to building web APIs, emphasizing simplicity, efficiency, and a focus on core HTTP concepts.By employing MapGroup, you can establish a well-defined hierarchy within your Minimal API routes, facilitating better code organization and easier maintenance.

Happy Coding!

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Build a Worker Service and Launch it as a Windows Service .NET Core Application

clock December 5, 2024 07:36 by author Peter

In Visual Studio 2022 or 2019, create a .Net Worker service project and give it whatever name you like. The worker service was first implemented in Visual Studio 2019 and is compatible with the most recent versions. A worker service is a background service that performs ongoing background tasks while operating as a service.

Worker.cs
namespace MyWorkerService
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

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

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                if (_logger.IsEnabled(LogLevel.Information))
                {
                    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                }

                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

To install the Worker service in Windows, the background service installs the below-mentioned Hosting package from the Nuget package.
Microsoft.Extensions.Hosting.WindowsServices

Add the code below to the program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<YourWorkerService>();
        });


Build and Publish the worker service project and make sure MyWorkerService.exe is placed inside the publish folder. Then, Open the Command prompt with administrative privileges and execute the mentioned command lines.
sc.exe create MyWorkerService binpath=C:\MyWorkerService\MyWorkerService.exe
sc.exe start MyWorkerService


In case of any error, if you want to delete or stop a service, follow the command lines.
sc.exe delete MyWorkerService
sc.exe stop MyWorkerService


To ensure the smooth running of the worker service, open a service from the start of a window, check the name of the service (Example: MyWorkerService), and confirm the service is running.

Output

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Knowing How to Use.http Files in.NET 8

clock December 2, 2024 06:19 by author Peter

To improve HTTP request testing, Microsoft has added an exceptional power feature. This post will explain how to use a http file and provide an example of a REST API. It is appropriate for users of all skill levels, including novices, intermediates, and experts.

We will cover.

  • What is a .http file?
  • Advantages of .http files?
  • How to Create and Use .http files?
  • How to send a request using .http files?

Prerequisites

  • Visual Studio 2019 or a later version.
  • Basic understanding of REST API.

Let’s start with

What is a .http file?

Let me ask you a question, do you know how you test APIs before a .http file? The answer would be third-party tools like Postman, Swagger, Insomnia, etc.
Microsoft has now introduced the. http file for conveniently sending HTTP requests and testing APIs directly from Visual Studio or an Integrated Development Environment. This feature enables developers to write and execute HTTP requests directly within the code editor, simplifying testing and ensuring accuracy.

Advantages of .http files?

  • Effortless API Testing
  • Reusability
  • Increase development accuracy
  • Consistency
  • Seamless Workflow Integration

How to Create and Use .http files?
Let’s start by creating an "Asp. Net Core Web API" project for demonstration purposes.

Step 1. Create an “Asp.Net Core Web Api” project by selecting the below template.

Step 2. Select “Additional Information” and click the “Create” button to create a .Net project.

You have observed that we have chosen the check box “Enable OpenAPI support”. If this check box is selected, Visual Studio generates an ASP. The net core web API project is accompanied by a. http file.

Let’s keep this checked box checked for now.

Step 3. The Asp.Net Core Web Api project was created successfully with weatherForcast Controller and DemoAPI.http file.

Let's open the weather forecast controller file.

WeatherForcastcontroller.cs
using Microsoft.AspNetCore.Mvc;
namespace DemoAPI.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
        private readonly ILogger<WeatherForecastController> _logger;
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}


DemoApi.http
@DemoAPI_HostAddress = https://localhost:7063
# Send request or Debug
GET {{DemoAPI_HostAddress}}/weatherforecast/
Accept: application/json
###


Nice, Visual Studio has created a .http file for the controller WealthForcast. You have observed that we have two links.
    “Send Request”: Send the request and open a new window with output. This will help to test the API,
    “Debug”: It will allow you to debug the api.

Step 4. Let’s click on the “Send Request” link and observe the output.

You can see the output with Header, Raw, Formatted, and request details. Let’s click on the Raw.


Now we can Raw details in JSON. It is nice and helpful. Isnt it?

Step 5. Now we will add a new endpoint and then create a .http file.

Please add the below code in the Wealthforcast. cs file.
[HttpGet("{ID}")]
public WeatherForecast Get(int ID)
{
    return new WeatherForecast
    {
        Date = DateOnly.FromDateTime(DateTime.Now.AddDays(ID)),
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
    };
}


Step 6. Now we will add a new endpoint in the .http file.

Microsoft has provided “Endpoints Explorer” to generate an endpoint in the .http file.

In the visual studio “View->OtherWindows->Endpoint Explorer”.


Step 7. Click on the “Endpoints Explorer” and click on “Generate Request”.

The file code below will be added in the “demo. http” file.
@DemoAPI_HostAddress = https://localhost:7063
# Send request for the default weather forecast
###
Send request | Debug
GET {{DemoAPI_HostAddress}}/weatherforecast/
Accept: application/json
###
# Send request for a specific weather forecast (ID = 0)
###
Send request | Debug
GET {{DemoAPI_HostAddress}}/weatherforecast/0
Accept: application/json
###


Output

Similarity POST, PUT, and DELETE endpoints can be created.
That’s all for this article. Hope you learn and enjoy this article.

HostForLIFE ASP.NET Core 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 Hosting - HostForLIFE :: Use Polly to implement a retry strategy in .NET 6 applications

clock November 26, 2024 06:27 by author Peter

In this post, I'll demonstrate how to use Polly to handle errors in.NET 6 apps. In the fast-paced digital world of today, systems must be accessible around-the-clock to satisfy the needs of cherished users. In today's technology environment, making sure software applications are dependable and resilient has become crucial.

Using Polly to Provide Fault Tolerance in.NET 6 Applications
In the ever-changing digital world of today, developing robust applications is crucial. While preserving dependable performance and a flawless user experience, applications must efficiently handle problems such as temporary errors, timeouts, or resource unavailability. A robust.NET framework called Polly makes it easier to deploy fault-tolerance techniques in.NET 6 applications. This post explores Polly's capabilities and shows you how to use it in your projects.

What Is Polly?
Polly is a powerful and flexible .NET library designed to help developers implement fault-tolerance and resilience strategies in their applications. It provides a rich set of features that allow you to define policies to handle various types of transient faults, such as network interruptions, timeouts, and resource unavailability. These policies enable applications to recover gracefully from unexpected errors, ensuring stability, reliability, and an enhanced user experience.

You can integrate Polly into your projects.

  • Automatically retry failed operations caused by transient issues.
  • Use circuit breakers to prevent cascading failures within the system.
  • Set time limits for operations to minimize unnecessary delays.
  • Implement fallback mechanisms to handle failures when primary operations are unsuccessful.
  • Manage resource consumption with bulkhead isolation to ensure overall system stability.

In this article, I will explain Retry Policies and walk you through a step-by-step implementation of Polly in a .NET 6 application.

Integrating Polly into .NET 6 Applications

Follow these steps to add fault tolerance with Polly in your .NET 6 application.

Create a console application using ASP.NET 6

Install Polly
Add the Polly NuGet package to your project.

After successfully installing the required package, the next step is to implement a retry policy. This policy is designed to attempt the operation up to three times if an error occurs during its execution. The retry mechanism ensures that transient issues, such as network glitches or temporary unavailability of resources, are handled gracefully by retrying the operation before failing completely.

How to Implement Retry Policies?

using Polly;
var retryPolicy = Policy
    .Handle<Exception>()
    .Retry(3, (exception, retryCount) =>
    {
        Console.WriteLine($"Retry {retryCount} due to: {exception.Message}");
    });
retryPolicy.Execute(() =>
{
    // Code, method, or logic that might fail
    // In this example, I have created a method designed to throw an exception.
    PerformYourOperation();
});
void PerformYourOperation()
{
    throw new Exception("Simulated failure");
}

The output for the retry policy configuration with 3 attempts.

How does the above code work?

  • First Attempt: The policy executes PerformYourOperation(). Since it always throws an exception, the first attempt fails.
  • Retries: The retry policy catches the exception and retries up to 3 times. After each failure, it logs a message to the console indicating the retry count and the reason for the failure.
  • Final Outcome: If all 3 attempts fail, the exception is propagated, and the retry process stops. Without additional fallback mechanisms, the application will fail.

Summary
In this article, we explored how the Retry Policy in Polly for .NET enables the automatic handling of transient failures by retrying an operation multiple times before it ultimately fails. This pattern ensures that applications can recover from temporary issues without negatively affecting overall system performance.

HostForLIFE ASP.NET Core 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