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 :: Restful API In .NET Core Using EF Core And Postgres

clock June 14, 2022 09:05 by author Peter

REST API is an application programming interface which can be used by multiple clients(or APPS) to communicate with a server. Rest API is a kind of web-service which stores and retrieves necessary data for your application in a convenient format (e.g. JSON or XML). It provides great flexibility to developers since it does not need any dependent code libraries to access the web-services as it is stateless.Amongst the many protocols supported by REST, the most common one is HTTP.

When a request is sent from the client using a HTTPRequest, a corresponding response is sent from the server using HTTPResponse. The most widely used machine readable format supported for requests and responses are JSON (Javascript Object Notification) and XML (Extensible Markup Language).

REST was created by computer scientist ROY FIELDING.
REST APIs can be used to perform different actions. Based on the actions, the relevant method should be used. The following are the 5 methods supported by REST.

  1. GET - This method is used to retrieve a data from database / server.
  2. POST - This method is used to create a new record.
  3. PUT - This method is used to modify / replace the record. It replaces the entire record.
  4. PATCH - This method is used to modify / update the record. It replaces parts of the record.
  5. DELETE - This method is used to delete the record.
Let us see this with an example. We know that mothers never get enough rest. But lets take these rest-less mommies as an example and see how they use Rest API. :)
Amongst the excessive demands by a newborn baby, diapering takes the first place on the leader board.

A mother wants everything best for the baby. So, it's obvious that the mother would want to choose the best diaper for her baby. So, she goes to a shopping website(assume: flipkart) and searches for diapers. This will send a HTTP Request to flipkart’s server to GET the list of all diapers. Flipkart’s server responds with a HTTP Response which will be a JSON object(assume) containing a list of diapers with some basic details. Flipkart’s website reads this Response and converts to human readable format and displays it on the webpage for the mother to see it.

After she chooses a particular diaper for her newborn baby and adds it to her list. This creates a POST request where a new record is created in flipkart’s database containing the diaper brand, size, quantity, price etc.

Her baby keeps growing and soon outgrows the newborn size. Suppose, the mother still likes the diaper brand and just wants to size up, all she has to do is just choose the new diaper size. When she updates the diaper size from size newborn to size 1, this triggers a PATCH method where everything else remains the same and only the size of the diaper is changed.

It is very common for the mother to change the current brand and decide to switch to an alternate the brand. Here, the mother will initiate a PUT request where the entire data containing previously chosen brand is modified and replaced with data corresponding to the newly chosen brand.

Finally, after a series of experiments involving several GETs, POSTs, PUTs and PATCHs, it's time for the mother to potty train the child. If she succeeds in training the child, then the diapers will no longer be required. This triggers a DELETE request.

PREREQUISITES
    Visual studio 2022
    .Net Core 6 : ASP.NET Core is a new version of ASP.NET, developed by Microsoft. It is an open-source framework for developing web applications and API's and it can be run on Windows, Mac, or Linux. Asp.Net Core is a cross platform, high-performance, open-source framework for building modern, cloud-based, internet-connected applications.
    Entity Framework core: Entity Framework (EF) Core is a lightweight, extensible, open source and cross-platform version of the popular Entity Framework data access technology.
    Postgres Database : PostgreSQL is a powerful, open source object-relational database system with over 30 years of active development that has earned it a strong reputation for reliability, feature robustness, and performance.

API CREATIONS STEPS
Step 1
Open Visual studio 2022 and create asp.net core webapi project.

Step 2
Install Npgsql.EntityFrameworkCore.PostgreSQL & Microsoft.EntityFrameworkCore.Tools from Nuget

Step 3
Create Product.cs and Order.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("product")]
public class Product {
    [Key, Required]
    public int id {
        get;
        set;
    }
    [Required]
    public string ? name {
        get;
        set;
    }
    public string ? brand {
        get;
        set;
    }
    public string ? size {
        get;
        set;
    }
    public decimal price {
        get;
        set;
    }
    public virtual ICollection < Order > orders {
        get;
        set;
    }
}

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("order")]
public class Order {
    [Key, Required]
    public int id {
        get;
        set;
    }
    public int product_id {
        get;
        set;
    }
    [Required]
    public string ? name {
        get;
        set;
    }
    public string ? address {
        get;
        set;
    }
    public string ? phone {
        get;
        set;
    }
    public DateTime createdon {
        get;
        set;
    }
    public virtual Product product {
        get;
        set;
    }
}

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("order")]
public class Order {
    [Key, Required]
    public int id {
        get;
        set;
    }
    public int product_id {
        get;
        set;
    }
    [Required]
    public string ? name {
        get;
        set;
    }
    public string ? address {
        get;
        set;
    }
    public string ? phone {
        get;
        set;
    }
    public DateTime createdon {
        get;
        set;
    }
    public virtual Product product {
        get;
        set;
    }
}

Step 4
Create EF_DataContext inherited from DbContext class
using Microsoft.EntityFrameworkCore;
public class EF_DataContext: DbContext {
    public EF_DataContext(DbContextOptions < EF_DataContext > options): base(options) {}
    protected override void OnModelCreating(ModelBuilder modelBuilder) {
        modelBuilder.UseSerialColumns();
    }
    public DbSet <Product> Products {
        get;
        set;
    }
    public DbSet <Order> Orders {
        get;
        set;
    }
}


Step 5
Open appsetting.json
"ConnectionStrings": {
    "Ef_Postgres_Db": "Server=localhost;Database=shopingpostgres;Port=5432;User Id=postgres;Password=qwerty1234;"
}

Step 6
Open Program.cs

builder.Services.AddDbContext < EF_DataContext > (o => o.UseNpgsql(builder.Configuration.GetConnectionString("Ef_Postgres_Db")));

Step 7
Run the 2 commands
Add-Migration InitialDatabase
Update-Database

Step 8
Create the API Product and Order Models that will be used for API communication
public class Product {
    public int id {
        get;
        set;
    }
    public string ? name {
        get;
        set;
    }
    public string ? brand {
        get;
        set;
    }
    public string ? size {
        get;
        set;
    }
    public decimal price {
        get;
        set;
    }
}

public class Order {
    public int id {
        get;
        set;
    }
    public int product_id {
        get;
        set;
    }
    public string ? name {
        get;
        set;
    }
    public string ? address {
        get;
        set;
    }
    public string ? phone {
        get;
        set;
    }
    public DateTime createdon {
        get;
        set;
    }
    public virtual Product product {
        get;
        set;
    }
}


Step 9
Add the DBhelper class that will talk to your database
using ShoppingWebApi.EfCore;
namespace ShoppingWebApi.Model {
    public class DbHelper {
        private EF_DataContext _context;
        public DbHelper(EF_DataContext context) {
            _context = context;
        }
        /// <summary>
        /// GET
        /// </summary>
        /// <returns></returns>
        public List < ProductModel > GetProducts() {
            List < ProductModel > response = new List < ProductModel > ();
            var dataList = _context.Products.ToList();
            dataList.ForEach(row => response.Add(new ProductModel() {
                brand = row.brand,
                    id = row.id,
                    name = row.name,
                    price = row.price,
                    size = row.size
            }));
            return response;
        }
        public ProductModel GetProductById(int id) {
            ProductModel response = new ProductModel();
            var row = _context.Products.Where(d => d.id.Equals(id)).FirstOrDefault();
            return new ProductModel() {
                brand = row.brand,
                    id = row.id,
                    name = row.name,
                    price = row.price,
                    size = row.size
            };
        }
        /// <summary>
        /// It serves the POST/PUT/PATCH
        /// </summary>
        public void SaveOrder(OrderModel orderModel) {
            Order dbTable = new Order();
            if (orderModel.id > 0) {
                //PUT
                dbTable = _context.Orders.Where(d => d.id.Equals(orderModel.id)).FirstOrDefault();
                if (dbTable != null) {
                    dbTable.phone = orderModel.phone;
                    dbTable.address = orderModel.address;
                }
            } else {
                //POST
                dbTable.phone = orderModel.phone;
                dbTable.address = orderModel.address;
                dbTable.name = orderModel.name;
                dbTable.Product = _context.Products.Where(f => f.id.Equals(orderModel.product_id)).FirstOrDefault();
                _context.Orders.Add(dbTable);
            }
            _context.SaveChanges();
        }
        /// <summary>
        /// DELETE
        /// </summary>
        /// <param name="id"></param>
        public void DeleteOrder(int id) {
            var order = _context.Orders.Where(d => d.id.Equals(id)).FirstOrDefault();
            if (order != null) {
                _context.Orders.Remove(order);
                _context.SaveChanges();
            }
        }
    }
}


Step 10
Create your Api Controller name it as ShoppingRestApi
using Microsoft.AspNetCore.Mvc;
using ShoppingWebApi.EfCore;
using ShoppingWebApi.Model;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ShoppingWebApi.Controllers {
    [ApiController]
    public class ShoppingApiController: ControllerBase {
        private readonly DbHelper _db;
        public ShoppingApiController(EF_DataContext eF_DataContext) {
            _db = new DbHelper(eF_DataContext);
        }
        // GET: api/<ShoppingApiController>
        [HttpGet]
        [Route("api/[controller]/GetProducts")]
        public IActionResult Get() {
            ResponseType type = ResponseType.Success;
            try {
                IEnumerable < ProductModel > data = _db.GetProducts();
                if (!data.Any()) {
                    type = ResponseType.NotFound;
                }
                return Ok(ResponseHandler.GetAppResponse(type, data));
            } catch (Exception ex) {
                return BadRequest(ResponseHandler.GetExceptionResponse(ex));
            }
        }
        // GET api/<ShoppingApiController>/5
        [HttpGet]
        [Route("api/[controller]/GetProductById/{id}")]
        public IActionResult Get(int id) {
            ResponseType type = ResponseType.Success;
            try {
                ProductModel data = _db.GetProductById(id);
                if (data == null) {
                    type = ResponseType.NotFound;
                }
                return Ok(ResponseHandler.GetAppResponse(type, data));
            } catch (Exception ex) {
                return BadRequest(ResponseHandler.GetExceptionResponse(ex));
            }
        }
        // POST api/<ShoppingApiController>
        [HttpPost]
        [Route("api/[controller]/SaveOrder")]
        public IActionResult Post([FromBody] OrderModel model) {
            try {
                ResponseType type = ResponseType.Success;
                _db.SaveOrder(model);
                return Ok(ResponseHandler.GetAppResponse(type, model));
            } catch (Exception ex) {
                return BadRequest(ResponseHandler.GetExceptionResponse(ex));
            }
        }
        // PUT api/<ShoppingApiController>/5
        [HttpPut]
        [Route("api/[controller]/UpdateOrder")]
        public IActionResult Put([FromBody] OrderModel model) {
            try {
                ResponseType type = ResponseType.Success;
                _db.SaveOrder(model);
                return Ok(ResponseHandler.GetAppResponse(type, model));
            } catch (Exception ex) {
                return BadRequest(ResponseHandler.GetExceptionResponse(ex));
            }
        }
        // DELETE api/<ShoppingApiController>/5
        [HttpDelete]
        [Route("api/[controller]/DeleteOrder/{id}")]
        public IActionResult Delete(int id) {
            try {
                ResponseType type = ResponseType.Success;
                _db.DeleteOrder(id);
                return Ok(ResponseHandler.GetAppResponse(type, "Delete Successfully"));
            } catch (Exception ex) {
                return BadRequest(ResponseHandler.GetExceptionResponse(ex));
            }
        }
    }
}


Step 11
Add the response model and response handler that will handle your API responses
namespace ShoppingWebApi.Model {
    public class ApiResponse {
        public string Code {
            get;
            set;
        }
        public string Message {
            get;
            set;
        }
        public object ? ResponseData {
            get;
            set;
        }
    }
    public enum ResponseType {
        Success,
        NotFound,
        Failure
    }
}


Now test the API's using POSTMAN as shown is video.

HostForLIFE.eu 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 :: Caching In Entity Framework Core Using NCache

clock June 13, 2022 08:33 by author Peter

It will be explained in this article how to integrate Entity Framework Core with a caching engine using NCache. The article will give a practical example of how we could set up our Entity Framework Core in a Console application and how to make use of NCache to make faster requests to the database with its native in-memory distributed cache.

What is Entity Framework Core?

Entity Framework Core is Microsoft's most recent ORM - Object Relational Mapper, that helps software applications map, connect, and manage entities to a wide range of databases. Entity Framework Core is open source and cross-platform, being the top 1 ORM used by software using Microsoft technologies.

At the moment of writing this article, Entity Framework Core offers two ways to connect your entities to the database:

Code First, writing your project's entities first and then reflecting those objects in the database;
Database First, have your database created first and then generate your project's entities.

What is NCache?
NCache is also open-source and cross-platform software. Its cache server offers a scalable in-memory distributed cache for .NET, Java, Scala, Python, and Node.js. As this article will be focusing on .NET technologies, we can use NCache to take advantage of the following usages:

  • ASP.NET session state storage;
  • ASP.NET view state caching;
  • ASP.NET output cache;
  • Entity Framework cache;
  • NHibernate second-level cache.

NCache with Entity Framework Core
We can add a layer of cache between the Entity Framework Core and our application with NCache, this would improve our queries response time and reduce the necessity of round trips to the database as far as we would get data from NCache cached entities.

Caching Options

NCache gives the possibility to have a different set of options to be sent from each request, meaning that we can use the cache differently based on the result set that we are working with in order to be more efficient.

As we are going to see in the practical samples, we must provide the cache options on each request to NCache and those options are the following:
AbsoluteExpirationTime, sets the absolute time when the cached item will expire;
    Data type: Datetime
CreateDbDependency, creates or not a database dependency from the result set;
    Data type: boolean
ExpirationType, sets the expiration type:
    Absolute,
    Sliding,
    None.
IsSyncEnabled, sets if the expired items must be re-synced with the database.
    Data type: boolean
Priority, sets the relative priority of items stored in the cache.
    Normal,
    Low,
    BelowNormal,
    AboveNormal,
    High,
    NotRemovable,
    Default
QueryIdentifier, result set identifier.
    Data type: string.
ReadThruProvider, sets the read thru provider for cache sync
    Data type: string
SlidingExpirationTime, sets the sliding expiration time
    Data type: TimeSpan
StoreAs, sets how the items are to be stored.
    Collection
    SeperateEntities

Deferred Calls
NCache has its own extension methods for us to work with Entity Framework Core deferred calls and they are in 3 different groups:

Aggregate Operators, making operations against collections. Can be used with both FromCache and FromCacheOnly methods.
    DeferredAverage.
        Products.Select(o => o.UnitPrice).DeferredAverage()
    DeferredCount
        Customers.Select(c => c.Country).GroupBy(c => c).DeferredCount()
    DeferredMin
        Orders.Where(o => o.CustomerId == "VINET").Select(o => o.RequiredDate).DeferredMin()
    DeferredMax
        Orders.Select(o => o.RequiredDate).DeferredMax()
    DeferredSum
        OrderDetails.Select(o => o.UnitPrice).DeferredSum()
Element Operators, making operations for single elements. Can be used only with the FromCache method.
    DeferredElementAtOrDefault
        Customers.DeferredElementAtOrDefault(c => c.City == "London")
    DeferredFirst
        Customers.DeferredFirst(c => c.ContactTitle == "Sales Representative")
    DeferredFirstOrDefault
        Customers.DeferredFirstOrDefault(c => c.ContactTitle == "Sales Representative")
    DeferredLast
        Customers.DeferredLast(c => c.City == "London")
    DeferredLastOrDefault
        Customers.DeferredLastOrDefault(c => c.City == "London")
    DeferredSingle
        Customers.DeferredSingle(c => c.CustomerId == "ALFKI")
    DeferredSingleOrDefault
        Customers.DeferredSingleOrDefault(c => c.CustomerId == "ANATR")
Others. Can be used only with the FromCache method.
    DeferredAll
        Products.DeferredAll(expression)
    DeferredLongCount
        Products.DeferredLongCount()
    DeferredContains
        Products.DeferredContains(new Products { ProductId = 1 })

Caching Methods

NCache's methods to manipulate cached objects:

Insert
Insert a single object in the cache with its own options. Returns the cache key
var customerEntity = new Customers
{
   CustomerId = "HANIH",
   ContactName = "Hanih Moos",
   ContactTitle = "Sales Representative ",
   CompanyName = "Blauer See Delikatessen"
};

//Add customer entity to database
database.Customers.Add(customerEntity);
database.SaveChanges();

//Caching options for cache
var options = new CachingOptions
{
   QueryIdentifier = "CustomerEntity",
   Priority = Runtime.CacheItemPriority.Default,
};

//Add customer entity to cache
Cache cache = database.GetCache();

cache.Insert(customerEntity, out string cacheKey, options);


Remove (object Entity)
Remove a single object from the cache.
var cust = new Customers
{
  CustomerId = "PETER",
  ContactName = "Peter Scott",
  ContactTitle = "Sales Representative",
  CompanyName = "Hostforlife"
};

cache.Remove(cust);


Remove (string cacheKey)
Remove an object by passing its cache key
cache.Remove("cacheKey");

RemoveByQueryIdentifier
Remove all entities from the cache which match the query identifier
Tag tag = new Tag(queryIdentifier);
cache.RemoveByQueryIdentifier(tag);


Caching using NCache extension methods
NCache's Extension methods for Entity Framework Core

Gets the cache instance.
using (var context = new NorthwindContext())
{
Cache cache = context.GetCache();
}


FromCache
If there is cached data, then it will be returned without going through the data source. If there is no data cached, then data will be returned from the data source and cached.
var options = new CachingOptions
{
StoreAs = StoreAs.SeperateEntities
};

var resultSet = (from cust in context.Customers
             where cust.CustomerId == 10
             select cust).FromCache(options);


Returning the cacheKey from the result set
var options = new CachingOptions
{
StoreAs = StoreAs.Collection
};

var resultSet = (from cust in context.Customers
            where cust.CustomerId == 10
            select cust).FromCache(out string cacheKey, options);


LoadIntoCache
Every request goes first to the data source, caches its result set, and returns it.
var options = new CachingOptions
{
    StoreAs = StoreAs.SeperateEntities
};

var resultSet = (from custOrder in context.Orders
                 where custOrder.Customer.CustomerId == 10
                 select custOrder)).LoadIntoCache(options);

Returning the cache key from the result set
var options = new CachingOptions
{
StoreAs = StoreAs.Collection
};

var resultSet = (from custOrder in context.Orders
             where custOrder.Customer.CustomerId == 10
             select custOrder)).LoadIntoCache(out string cacheKey, options);


FromCacheOnly
Never goes to the data source. The request is only going to the cache, if no matching result is cached, then it will be returned as an empty result set.
Includes and joins are not supported by FromCacheOnly().
var resultSet = (from cust in context.Customers
             where cust.CustomerId == someCustomerId
             select cust).FromCacheOnly();


NCache Implementation Step by Step
0. Pre-Requisites

Have NCache running on your machine. Access your NCache through http://localhost:8251/

1. The application
Create a C# console application targeting .NET 6.0 and install the following nugets packages:
    EntityFrameworkCore.NCache
    Microsoft.EntityFrameworkCore.SqlServer
    Microsoft.EntityFrameworkCore.SqlServer.Design
    Microsoft.EntityFrameworkCore.Tools
    System.Data.SqlClient
    System.Collections
The following NCache files will be inserted into your project after installing the Nuget Packages.
    client.ncconf
    config.ncconf
    tls.ncconf


2. Models
For this sample, it was created a very simple model relationship, as follows:
Product
[Serializable]
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public List<Transaction> Transactions { get; set; }
public Store Store { get; set; }
public int? StoreId { get; set; }
}


Store
[Serializable]
public class Store
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public ICollection<Product> AvailableProducts { get; set; }
public ICollection<Consumer> RegularConsumers { get; set; }
}


Consumer
[Serializable]
public class Consumer
{
public int Id { get; set; }
public string Name { get; set; }
public Store FavouriteStore { get; set; }
public int? FavouriteStoreId { get; set; }
public List<Transaction> Transactions { get; set; }
}

Transaction
[Serializable]
public class Transaction
{
 public int Id { get; set; }

 public Consumer Consumer { get; set; }
 public int ConsumerId { get; set; }

 public Product Product { get; set; }
 public int ProductId { get; set; }
}

DBContext
The DBContext class has NCache initialization settings and the model's relationship.

public class SampleDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    // configure cache with SQLServer DependencyType and CacheInitParams
    CacheConnectionOptions initParams = new CacheConnectionOptions();
    initParams.RetryInterval = new TimeSpan(0, 0, 5);
    initParams.ConnectionRetries = 2;
    initParams.ConnectionTimeout = new TimeSpan(0, 0, 5);
    initParams.AppName = "appName";
    initParams.CommandRetries = 2;
    initParams.CommandRetryInterval = new TimeSpan(0, 0, 5);
    initParams.Mode = IsolationLevel.Default;

    NCacheConfiguration.Configure("democache", DependencyType.SqlServer, initParams);

    optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-AT3H2E;Initial Catalog=sampleDatabase;Integrated Security=True");
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Store>()
        .HasMany(x => x.AvailableProducts)
        .WithOne(x => x.Store)
        .HasForeignKey(x => x.StoreId)
        .IsRequired(false)
        .OnDelete(DeleteBehavior.NoAction);

    modelBuilder.Entity<Store>()
        .HasMany(x => x.RegularConsumers)
        .WithOne(x => x.FavouriteStore)
        .HasForeignKey(x => x.FavouriteStoreId)
        .IsRequired(false)
        .OnDelete(DeleteBehavior.NoAction);

    modelBuilder.Entity<Transaction>()
        .HasOne(x => x.Consumer)
        .WithMany(x => x.Transactions)
        .HasForeignKey(x => x.ConsumerId)
        .IsRequired(false);

    modelBuilder.Entity<Transaction>()
        .HasOne(x => x.Product)
        .WithMany(x => x.Transactions)
        .HasForeignKey(x => x.ProductId)
        .IsRequired(false);
}

public DbSet<Store> Stores { get; set; }
public DbSet<Consumer> Consumers { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Transaction> Transactions { get; set; }
}


3. NCache Methods
Here is the class with NCache methods needed to manipulate objects from and to the cache.
public class NCacheExtensions
{
private SampleDbContext Database { get; set; }
private CachingOptions CachingOptions { get; set; }
private Cache Cache { get; set; }

public NCacheExtensions(SampleDbContext database)
{
    this.Database = database;
    this.CachingOptions = new CachingOptions
    {
        QueryIdentifier = "Sample QueryIdentifier",
        Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default,
        CreateDbDependency = false,
        StoreAs = StoreAs.Collection
    };

    Cache = database.GetCache();
}


public string AddSingleEntity<T>(T entity)
{
    Cache.Insert(entity, out string cacheKey, this.CachingOptions);
    return cacheKey;
}
public void RemoveSingleEntity<T>(T entity)
{
    Cache.Remove(entity);
}
public void RemoveSingleEntity(string cacheKey)
{
    Cache.Remove(cacheKey);
}
public void RemoveByQueryIdentifier(string queryIdentifier)
{
    var tag = new Tag(queryIdentifier);
    Cache.RemoveByQueryIdentifier(tag);
}

public IEnumerable<Consumer> GetAllConsumersFromCache(CachingOptions cachingOptions)
{
    return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCache(cachingOptions);
}
public async Task<IEnumerable<Consumer>> GetAllConsumersFromCacheAsync(CachingOptions cachingOptions)
{
    return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCacheAsync(cachingOptions);
}
public IEnumerable<Consumer> LoadAllConsumersIntoCache(CachingOptions cachingOptions)
{
    return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCache(cachingOptions);
}
public async Task<IEnumerable<Consumer>> LoadAllConsumersIntoCacheAsync(CachingOptions cachingOptions)
{
    return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCacheAsync(cachingOptions);
}
public IEnumerable<Consumer> GetAllConsumersFromCacheOnly(CachingOptions cachingOptions)
{
    return Database.Consumers.FromCacheOnly();
}
}

4.The program.cs class
Here we have the start point of our console application. With an example on how to connect to NCache and use its extension methods that were provided above.
class Program
{
static void Main(string[] args)
{
    Console.WriteLine("Hello World!");

    using (var context = new SampleDbContext())
    {
        var cachedContext = new NCacheExtensions(context);

        Console.WriteLine("start LoadAllConsumersIntoCache " + DateTime.Now.ToString("HH:mm:ss.f"));
        var loadInCache = cachedContext.LoadAllConsumersIntoCache(new CachingOptions { StoreAs = StoreAs.Collection, QueryIdentifier = "Sample QueryIdentifier" });
        Console.WriteLine("finish LoadAllConsumersIntoCache" + DateTime.Now.ToString("HH:mm:ss.f"));

        Console.WriteLine("start GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));
        var getFromCache = cachedContext.GetAllConsumersFromCache(new CachingOptions { Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default });
        Console.WriteLine("finish GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));

        Console.WriteLine("start load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));
        var getFromDb = context.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product);
        Console.WriteLine("finishg load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));

        var cachedEntity = cachedContext.AddSingleEntity<Consumer>(getFromDb.FirstOrDefault());
        Console.WriteLine("cache key: " + cachedEntity);

        cachedContext.RemoveSingleEntity(cachedEntity);
        cachedContext.RemoveByQueryIdentifier("Sample QueryIdentifier");

    }
}
}


Application working:




European ASP.NET Core Hosting :: Common Practices In .NET Project Structure

clock June 10, 2022 07:58 by author Peter

The topic of properly organizing the code inside a project is often a critical issue for developers who are just starting to learn .NET. Often in the early development stages too much time is wasted trying to figure out where a new class should be created, or when a new project should be added to a solution, or even when to put code in a  specific subfolder.

The truth is that there isn't actually a single correct way to organize your code.

After years of developing in .NET, I've never actually worked on two projects where code was organized in the same way. The same goes for my personal projects: with the progress of my learning path in .NET, I have always tried to progressively move towards a "standard" way of organizing the code inside a repository.

Despite the differences, the analysis of the structure of numerous open source repositories shows that they actually share some common patterns and practices when it comes to organizing the code.

This article illustrates some of these common practices in organizing .NET projects, to help you structure your applications in a cleaner and easily understandable way.
Folder structure

.NET is actually very flexible in how you can organize the folder structure for an application. However, having a clear folder structure helps new contributors understand where to find the code they need. Even people who have never worked on your application would know where to look to find the documentation, or unit tests, or source code.

While there is no official standard on how to organize files and folders in a .NET application, many repositories follow a structure similar to the one outlined by David Fowler. A simplified version of the structure can be represented as follows:

$/
  artifacts/
  build/
  docs/
  packages/
  samples/
  src/
  tests/
  .editorconfig
  .gitignore
  .gitattributes
  LICENSE
  NuGet.Config
  README.md
  {solution}.sln
  ...

Files such as the solution file, README or LICENSE are put on the root folder, while the rest of the content is organized inside some main subfolders:
    src - Contains the actual source code for the application (the various projects with their classes etc.)
    tests - Contains unit test projects
    docs - Contains documentation files
    samples - This is where you would place files that provide examples to users on how to use your code or library
    artifacts - Build outputs go here
    packages - Contains NuGet packages
    build - Contains build customization scripts

Notice that in some cases the same structure could be recursively applied to the individual projects of the solution (for instance, you could have a src and test folder for each project).

Naming conventions for projects and namespaces

From the name of a project it should be easy to understand the functionality of the code it contains. For instance, if a project contains math related operations, it would probably contain Math in its name.

Talking about naming conventions, there isn't an actual standard; some common practices include:

    CompanyName.ProductName.Component (eg. MyCompany.MyApplication.DataAccess)
    CompanyName.Component (eg. MyCompany.Math)
    ProductName.Component (eg. MyApplication.Models)

Once you've chosen your particular naming convention, it's important to remain consistent with it.

In the case of subfolders within the same project, the namespaces of the files within the subfolders reflect the same hierarchical structure. For example, in a MyApplication.DataAccess project, classes within a SqlServer folder would belong to a MyApplication.DataAccess.SqlServer namespace.
Use multiple projects to separate macro functionality or layers

A common mistake is to put too many different functionalities inside the same project in a .NET solution. This often leads, for instance, to situations where data access logic is mixed up with UI functionalities, and there isn't a clear separation between the two areas. Instead, separating the code into multiple projects within the same solution helps you keep the code cleanly sorted in multiple distinct logical groupings; think of this like putting your dishes in a separate compartment from the cutlery. This makes it easier to understand where to look for what you need, and where the new class you're writing should be created.

One way to group code into multiple projects is by major functionality. For example, everything related to math operations in an application could go in its own project, separate from UI or data access components.

Another common approach is to divide the application into layers, creating a separate project for each layer. This helps you manage dependencies and avoid circular references, so that each layer is visible only to the correct projects. As an example, think of creating a project for the UI layer, that references the Business Logic layer, that in turn references the Data access layer; this creates a clear separation between those different areas of the application.

Within the same project it is then possible to create additional groupings, putting classes and components with similar functionalities into subfolders. Returning to the previous analogy, it would be like dividing forks and spoons into separate sections within the same compartment. For example, a data access project might have a subfolder containing all implementations related to SQL databases, a subfolder for mock implementations, and so on.

The resulting folder structure could look like this:
$/
  MyApplication.sln
  src/
    MyApplication.UI/
      MyApplication.UI.csproj

    MyApplication.Math/
      MyApplication.Math.csproj

    MyApplication.Business/
      MyApplication.Business.csproj

    MyApplication.DataAccess/
      SqlServer/
        SqlServerRepository.cs
      Mock/
        MockRepository.cs
      IRepository.cs
      MyApplication.DataAccess.csproj


Unit tests organization
The structure and naming convention of unit test projects should reflect those of the source code that it's being tested, usually with an addition of a Tests suffix to the names of projects and classes.

For instance, the MyApplication.Math project would be tested by a unit test project called MyApplication.Math.Tests; the unit tests for a class called Calculator would be found in a test class named CalculatorTests.

$/
  MyApplication.sln
  src/
    MyApplication.Math/
      Calculator.cs
      MyApplication.Math.csproj
      Utilities/
        MathUtilities.cs

  tests/
    MyApplication.Math.Tests/
      CalculatorTests.cs
      MyApplication.Math.Tests.csproj
      Utilities/
        MathUtilitiesTests.cs


This article covered some common practices in organizing code for .NET projects. While there is no single true correct approach and every project is unique, these guidelines can help you clear up some confusion when starting to build a new application in .NET.

HostForLIFE.eu 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 :: Cookie Sharing Authentication

clock June 7, 2022 08:31 by author Peter

Usually, web applications work together to integrate different functionalities in a single login. So, if web applications (eg: - multiple modules) can host within a primary application, it is easier to use ASP.NET Core cookie sharing mechanisms over a single sign-on (SSO) experience.

For example, we can start with two MVC applications in .Net core and share the cookie for authentication. Let’s consider the primary application name is “PrimarySite” and secondary application “Subsite”.

Initially both applications have similar startup.cs file.

public void ConfigureServices(IServiceCollection services) {
    services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
    } else {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints => {
        endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}


Step 1
First, we can make a login/register page in Primarysite. For that we need to add authentication middleware in configure method above UseAuthorization middleware.
app.UseAuthentication();


Steps 2
Set up a cookie sharing configuration with a key storage location in Configureservices method of startup.cs. The application name “SharedCookieApp” should be common in other applications/modules. (available namespace:- using Microsoft.AspNetCore.DataProtection;)

Then apply cookie policy configurations.

services.AddDataProtection().PersistKeysToFileSystem(GetKyRingDirectoryInfo()).SetApplicationName("SharedCookieApp");
services.Configure < CookiePolicyOptions > (options => {
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});


We are using different applications/solutions set samesite policy to “None”

GetKyRingDirectoryInfo is a custom method to retrieve common path directory.

private DirectoryInfo GetKyRingDirectoryInfo() {
    string applicationBasePath = System.AppContext.BaseDirectory;
    DirectoryInfo directoryInof = new DirectoryInfo(applicationBasePath);
    string keyRingPath = Configuration.GetSection("AppKeys").GetValue < string > ("keyRingPath");
    do {
        directoryInof = directoryInof.Parent;
        DirectoryInfo keyRingDirectoryInfo = new DirectoryInfo($ "{directoryInof.FullName}{keyRingPath}");
        if (keyRingDirectoryInfo.Exists) {
            return keyRingDirectoryInfo;
        }
    }
    while (directoryInof.Parent != null);
    throw new Exception($ "key ring path not found");
}


Common path can be set in appsettings.json
"keyRingPath": "\\PrimarySite\\wwwroot\\Ring"

 

 

We are using different applications/solutions set samesite policy to “None”

GetKyRingDirectoryInfo is a custom method to retrieve common path directory.
private DirectoryInfo GetKyRingDirectoryInfo() {
    string applicationBasePath = System.AppContext.BaseDirectory;
    DirectoryInfo directoryInof = new DirectoryInfo(applicationBasePath);
    string keyRingPath = Configuration.GetSection("AppKeys").GetValue < string > ("keyRingPath");
    do {
        directoryInof = directoryInof.Parent;
        DirectoryInfo keyRingDirectoryInfo = new DirectoryInfo($ "{directoryInof.FullName}{keyRingPath}");
        if (keyRingDirectoryInfo.Exists) {
            return keyRingDirectoryInfo;
        }
    }
    while (directoryInof.Parent != null);
    throw new Exception($ "key ring path not found");
}


Common path can be set in appsettings.json
"keyRingPath": "\\PrimarySite\\wwwroot\\Ring"


Step 3
For testing the register/login functionality, we can use in-memory database (data storing in memory not in real database). For that we need to install the below NuGet packages (entity framework core Identity and In-memory). This step is optional and used for testing register and login. Real entity framework can be used if it exists in the original application.

Then create a context class which inherits from IdentityDBContext

public class AppDbContext: IdentityDbContext {
    public AppDbContext(DbContextOptions < AppDbContext > options): base(options) {}
}


And Inject AddDbcontext with UseInmemmoryDatabase in Configureservice method.
#region DB
services.AddDbContext < AppDbContext > (config => {
    config.UseInMemoryDatabase("Memory");
});
#endregion


Configure Identity specification and EntityFramework core with AppDbContext.

services.Configure < CookiePolicyOptions > (options => {
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddIdentity < IdentityUser, IdentityRole > (config => {
    config.Password.RequiredLength = 4;
    config.Password.RequireDigit = false;
    config.Password.RequireNonAlphanumeric = false;
    config.Password.RequireUppercase = false;
}).AddEntityFrameworkStores < AppDbContext > ().AddDefaultTokenProviders();

Step 4
Set authentication type set to Identity.Application and a common cookie name (.AspNet.SharedCookie) which should be same among different applications those shares cookie authentication.

services.AddAuthentication("Identity.Application");
services.ConfigureApplicationCookie(config => {
    config.Cookie.Name = ".AspNet.SharedCookie";
    config.LoginPath = "/Home/Login";
    //config.Cookie.Domain = ".test.com";
});

Step 6
This step is also optional. This is to show a simple authentication (If it already has a  different authentication setup, it would be good to use that.)

Creating a user registration and authentication within memory database.
[HttpPost]
public async Task < IActionResult > Register(string username, string password) {
    var user = new IdentityUser {
        UserName = username,
            Email = ""
    };
    var result = await _userManager.CreateAsync(user, password);
    if (result.Succeeded) {
        var signInResult = await _signInManager.PasswordSignInAsync(user, password, false, false);
        if (signInResult.Succeeded) {
            return RedirectToAction("LoginSuccess");
        }
    }
    return RedirectToAction("Login");
}


Step 7
Now the primarysite will get logged in after entering values in register/login. Now we need to configure Startup.cs of SubSite/ Sub module as below.

ConfigureServices Method.
public void ConfigureServices(IServiceCollection services) {
    services.AddDataProtection().PersistKeysToFileSystem(GetKyRingDirectoryInfo()).SetApplicationName("SharedCookieApp");
    services.Configure < CookiePolicyOptions > (options => {
        // This lambda determines whether user consent for nonessential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });
    services.AddAuthentication("Identity.Application").AddCookie("Identity.Application", option => {
        option.Cookie.Name = ".AspNet.SharedCookie";
        option.Events.OnRedirectToLogin = (context) => {
            context.Response.StatusCode = 401;
            return Task.CompletedTask;
        };
    });
    services.AddControllersWithViews();
}

option.Events.OnRedirectToLogin can be configured to redirect in case of not authorized/authenticated scenario.

Configure Method.
Add UsecookiePolicy middleware above UseRouting
app.UseCookiePolicy();

Add UseAuthentication middleware below UseRouting.
app.UseAuthentication();


Then Add common key path in appsettings.json
"keyRingPath": "\\PrimarySite\\wwwroot\\Ring"

Step 8
Run both application and login to Primary site and redirect to the subsite authorize method(add[Authorize] attribute for methods or controller for which authentication is mandatory).


HostForLIFE.eu 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 :: AJAX In .NET Core

clock May 30, 2022 07:39 by author Peter

What is Ajax?
Ajax stands for Asynchronous JavaScript and XML, the data transmitted can be JSON, XML, HTML, JavaScript, plain text, etc. Regardless of the type of data, Ajax can send and receive it. Ajax uses a built-in object of all modern browsers called XMLHttpRequest. This object is used to exchange data back and forth between your Web page and a Web server, as shown below.

Types of AJAX Call

Ajax Methods Description
get() Sends HTTP GET request to load the data from the server.
Post() Sends HTTP POST request to submit or load the data to the server.
Put() Sends HTTP PUT request to update data on the server.
Delete() Sends HTTP DELETE request to delete data on the server.

STEP 1
Open VS 2022 click on create project as shown below,


 

Step 2
Choose the below mentioned template


 

Step 3
Now open the Model folder and add the 2 classes

    JsonResponseViewModel
    Student Model

This model will be used to communicate during ajax request. Below is the source code defination for both the models

[Serializable]
public class JsonResponseViewModel
{
    public int ResponseCode { get; set; }

    public string ResponseMessage { get; set; } = string.Empty;
}

public class StudentModel
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
}

Step 4
Now add the GET|POST|PUT|DELETE function for the server so that we can perform operations

public class HomeController: Controller {
    private readonly ILogger < HomeController > _logger;
    public static List < StudentModel > students = new List < StudentModel > ();
    public HomeController(ILogger < HomeController > logger) {
        _logger = logger;
        students = new List < StudentModel > ();
        students.Add(new StudentModel() {
            Id = 1, Email = "[email protected]", Name = "Ankush"
        });
        students.Add(new StudentModel() {
            Id = 2, Email = "[email protected]", Name = "Rohit"
        });
        students.Add(new StudentModel() {
            Id = 3, Email = "[email protected]", Name = "Sunny"
        });
        students.Add(new StudentModel() {
            Id = 4, Email = "[email protected]", Name = "Amit"
        });
    }
    public IActionResult Index() {
        return View(students);
    }
    [HttpGet]
    public JsonResult GetDetailsById(int id) {
        var student = students.Where(d => d.Id.Equals(id)).FirstOrDefault();
        JsonResponseViewModel model = new JsonResponseViewModel();
        if (student != null) {
            model.ResponseCode = 0;
            model.ResponseMessage = JsonConvert.SerializeObject(student);
        } else {
            model.ResponseCode = 1;
            model.ResponseMessage = "No record available";
        }
        return Json(model);
    }
    [HttpPost]
    public JsonResult InsertStudent(IFormCollection formcollection) {
        StudentModel student = new StudentModel();
        student.Email = formcollection["email"];
        student.Name = formcollection["name"];
        JsonResponseViewModel model = new JsonResponseViewModel();
        //MAKE DB CALL and handle the response
        if (student != null) {
            model.ResponseCode = 0;
            model.ResponseMessage = JsonConvert.SerializeObject(student);
        } else {
            model.ResponseCode = 1;
            model.ResponseMessage = "No record available";
        }
        return Json(model);
    }
    [HttpPut]
    public JsonResult UpdateStudent(IFormCollection formcollection) {
        StudentModel student = new StudentModel();
        student.Id = int.Parse(formcollection["id"]);
        student.Email = formcollection["email"];
        student.Name = formcollection["name"];
        JsonResponseViewModel model = new JsonResponseViewModel();
        //MAKE DB CALL and handle the response
        if (student != null) {
            model.ResponseCode = 0;
            model.ResponseMessage = JsonConvert.SerializeObject(student);
        } else {
            model.ResponseCode = 1;
            model.ResponseMessage = "No record available";
        }
        return Json(model);
    }
    [HttpDelete]
    public JsonResult DeleteStudent(IFormCollection formcollection) {
        StudentModel student = new StudentModel();
        student.Id = int.Parse(formcollection["id"]);
        JsonResponseViewModel model = new JsonResponseViewModel();
        //MAKE DB CALL and handle the response
        if (student != null) {
            model.ResponseCode = 0;
            model.ResponseMessage = JsonConvert.SerializeObject(student);
        } else {
            model.ResponseCode = 1;
            model.ResponseMessage = "No record available";
        }
        return Json(model);
    }
}

Step 5
Switch to the view and add the AJAX Calls functions

@model IEnumerable<ajaxSample.Models.StudentModel>

@{
    ViewData["Title"] = "Home Page";
}
@section Scripts{
    <script>
        $(document).ready(function() {
            // GET BY ID
            $(".btn-get-student").on("click", function() {
                var formData = new FormData();
                var studentid = $(this).attr("data-studentid");
                var url = '@Url.Action("GetDetailsById", "Home")' + '/' + studentid;
                $.ajax({
                    type: 'GET',
                    url: url,
                    contentType: false,
                    processData: false,
                    cache: false,
                    data: formData,
                    success: function(response) {
                        if (response.responseCode == 0) {
                            var student = JSON.parse(response.responseMessage);
                            $("#email").val(student.Email);
                            $("#name").val(student.Name);
                            $("#hdn-student-id").val(student.Id);

                        }
                        else {
                            bootbox.alert(response.ResponseMessage);
                        }
                    },
                    error: errorCallback
                });
            });
            //SAVE
            $("#btn-insert-student").on("click", function() {
                var formData = new FormData();
                formData.append("name", $("#name").val());
                formData.append("email", $("#email").val());
                $.ajax({
                    type: 'POST',
                    url: '@Url.Action("InsertStudent", "Home")',
                    contentType: false,
                    processData: false,
                    cache: false,
                    data: formData,
                    success: successCallback,
                    error: errorCallback
                });
            });
            // UPDATE
            $("#btn-update-student").on("click", function() {
                var formData = new FormData();
                formData.append("id", $("#hdn-student-id").val());
                formData.append("name", $("#name").val());
                formData.append("email", $("#email").val());
                $.ajax({
                    type: 'PUT',
                    url: '@Url.Action("UpdateStudent", "Home")',
                    contentType: false,
                    processData: false,
                    cache: false,
                    data: formData,
                    success: successCallback,
                    error: errorCallback
                });
            });
            //DELETE
            $("#btn-delete-student").on("click", function() {
                var formData = new FormData();
                formData.append("id", $("#hdn-student-id").val());
                $.ajax({
                    type: 'DELETE',
                    url: '@Url.Action("DeleteStudent", "Home")',
                    contentType: false,
                    processData: false,
                    cache: false,
                    data: formData,
                    success: successCallback,
                    error: errorCallback
                });
            });
            function resetForm() {
                $("#hdn-student-id").val("");
                $("#name").val("");
                $("#email").val("");
            }
            function errorCallback() {
                bootbox.alert("Something went wrong please contact admin.");
            }
            function successCallback(response) {
                if (response.responseCode == 0) {
                    resetForm();
                    bootbox.alert(response.responseMessage, function() {

                        //PERFORM REMAINING LOGIC
                    });
                }
                else {
                    bootbox.alert(response.ResponseMessage);
                }
            };
        });
    </script>
}
    <div class="text-center">
        <h1 class="display-4">Welcome To ASP.NET CORE AJAX Demo</h1>
        <hr />
    </div>
    <div class="row">
        <div class="col-sm-12">
            <form>
                <input type="hidden" id="hdn-student-id" />
                <div class="row g-3">
                    <div class="col-sm-6">
                        <label for="email" class="form-label">Email</label>
                        <input type="email" class="form-control" id="email" placeholder="Enter your email">
                        <div class="invalid-feedback">
                            Please enter a valid email address for shipping updates.
                        </div>
                    </div>

                    <div class="col-sm-6">
                        <label for="lastName" class="form-label">Name</label>
                        <input type="text" class="form-control" id="name" placeholder="Enter Your Name" value="" required="">
                        <div class="invalid-feedback">
                            Name is required.
                        </div>
                    </div>

                </div>
                <table class="table">
                    <tbody>
                        <tr>
                            <td>  <a href="javascript:void(0)" class="btn btn-primary" id="btn-insert-student">Save Student</a></td>
                            <td>
                                <a href="javascript:void(0)" class="btn btn-info" id="btn-update-student">Update Student</a>
                            </td>
                            <td>
                                <a href="javascript:void(0)" class="btn btn-danger" id="btn-delete-student">Delete Student</a>
                            </td>
                        </tr>
                    </tbody>

                </table>
            </form>

        </div>
        <br />
    </div>
    <div class="row">
        <div class="col-md-12">
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <td>#</td>
                        <td>Name</td>
                        <td>Email</td>
                        <td>Action</td>
                    </tr>
                </thead>
                <tbody id="student-list">
                    @{

                    foreach (var student in Model)
                    {
                        <tr>
                            <td>@student.Id</td>
                            <td>@student.Name</td>
                            <td>@student.Email</td>
                            <td>
                                <a href="javascript:void(0)" data-studentid="@student.Id" class="btn btn-success btn-get-student">Get Student</a>
                            </td>
                        </tr>
                    }
                }
            </tbody>
        </table>
    </div>
</div>

RUN the code and you will see the below mentioned O/P,

HostForLIFE.eu 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 :: Populating Dropdown Menu Using AJAX In ASP.NET Core

clock May 27, 2022 10:46 by author Peter

In this blog, we will study how to populate the dropdown menu using ajax call in asp.net net core step by step.

Step 1 - Add the jQuery CDN to your application
First of all, you need to add the jQuery CDN to your application that helps us to run the jQuery Code smoothly in the application.

Step 2 - Write the Ajax Call
The second step is to write the ajax call that is used to handle the asp.net Controller for bringing the data from the database in the form of JSON Object.

Add this Ajax call where you want to get the data from the database using the Asp.net Core Controller.
<script type = "text/javascript" > $(document).ready(function() {
    $.ajax({
        type: "GET",
        url: "/Bookings/FromLocation",
        data: "{}",
        success: function(data) {
            var s = '<option value="-1">Pickup Location</option>';
            for (var i = 0; i < data.length; i++) {
                console.log(data[i])
                s += '<option value="' + data[i].id + '">' + data[i].name + " " + data[i].address + '</option>';
            }
            $("#PickUpLocation").html(s);
        }
    });
});
</script>


Step 3 - Write the Asp.net Core Controller
The third step is to write the controller that is used to handle the HTTP request and bring the data from the database.

Note: the name of the controller should be the same as in the ajax call.
public Object FromLocation()
{
    return (_context.Locations.Select(x => new
    {
        Id = x.Id,
        Name = x.Name,
        Address = x.Address
    }).ToList().Where(x => x.Name != null && x.Address != null));
}


Step 4 - Pass the Data to Dropdown Menu

One thing that should be in your mind  is that the id of the select option should be the same as in the Ajax call.
<div class="form-group">
    <label asp-for="PickUpLocation" class="control-label"></label>
        <div class="form-group">
            <select class="form-control" asp-for="PickUpLocation" id="PickUpLocation" name="PickUpLocation"></select>
            <span asp-validation-for="PickUpLocation" class="text-danger"></span>
        </div>
</div>


Output
Now you can see that our data is now populated in the dropdown menu

HostForLIFE.eu 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 :: Minimal APIs In .NET 6

clock May 24, 2022 07:50 by author Peter

Today we will look at minimal APIs, a new feature in .NET 6. In the past, we created controllers in order to create an API which could be consumed by our clients. In .NET 6, a new feature called Minimal APIs has been introduced. This allows us to create an API with minimum code and plumbing. In fact, it is created directly in the Program.cs file. In .NET 6, the Startup.cs file is also not required anymore, and all initial plumbing is done inside the Program.cs file. We will create a simple Minimal API. So, let us begin.
Creating Minimal APIs

Let us start by opening Visual Studio 2022. I use the community edition which is free to download and use.

Select “Create a new project”.


Select “ASP.NET Core Web API”.


 

Remember to uncheck the highlighted option to use minimal APIs


Open the “Program.cs” file and update as below,

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
var summaries = new [] {
    "Freezing",
    "Bracing",
    "Chilly",
    "Cool",
    "Mild",
    "Warm",
    "Balmy",
    "Hot",
    "Sweltering",
    "Scorching"
};
app.MapGet("/weatherforecast", () => {
    var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast(DateTime.Now.AddDays(index), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)])).ToArray();
    return forecast;
}).WithName("GetWeatherForecast");
app.MapGet("/welcomemessage", () => {
    return "Welcome to Minimal APIs";
}).WithName("GetWelcomeMessage");
app.Run();
internal record WeatherForecast(DateTime Date, int TemperatureC, string ? Summary) {
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

Running the application
We now run the application and see the swagger page as below,

Here, we can try both the minimal APIs we have in our code.


 

In this article, we looked at creating a minimal API, a new feature in .NET 6. The example here was a simple one but it gives an idea of the concept and more complex APIs can be added. Probably for more complex APIs, refactoring into a separate file is a good idea. Happy coding!

HostForLIFE.eu 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 :: Log Correlation In Microservices

clock May 17, 2022 07:45 by author Peter

Logging is one of the most important factors to trace any issue in the system. Multiple requests will reach the system at the same time. Each request will have its own way. In Microservices architecture the complexity will be more. The same request will get forwarded to multiple systems. Each layer in each system will add some logs to trace the issue. But we need to link all the logs belonging to the request. Then only we identify how the request is behaving on each system. To Link all the logs into a single link, that is why correlation is required.

There are multiple frameworks available to correlate all the logs.

Azure is providing azure app insights to link and showcase all the requests into a single pipeline. Kibana and Serilog also provide to link the logs. Here we are going to see to link the logs without any third-party components.
Setup the CorrelationId

The request will originate from any client application or any subsystem. Each request can be identified by its reuestId. So the origin system can send its requestId or we can create the Id in case the origin didn't send it.

public class CorrelationHeaderMiddleware {
    private readonly RequestDelegate _next;
    public CorrelationHeaderMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task InvokeAsync(HttpContext context) {
        var correlationHeaders = context.Request.Headers["CorrelationId"];
        string correlationId;
        if (correlationHeaders.Any()) {
            correlationId = correlationHeaders[0];
        } else {
            correlationId = Guid.NewGuid().ToString();
            context.Request.Headers.Add("CorrelationId", correlationId);
        }
        context.Items["CorrelationId"] = correlationId;
        await _next(context);
    }
}

We have created new middleware that will fetch the correlation from the httpcontext or it will create the new id and set it into the request. Middleware is added into the request pipeline. All the requests will be processed and they will be added with CorrelationId.
Setup Logs

The request will get into multiple flows and add its logs. While adding the logs it will send the information alone to the log. While saving the logs we are fetching the CorrelationId from the request and adding it with the logs. So all the logs will get added with CorrelationId. After that, we can store the logs based on our format.

public class Logger: ILogType {
    private readonly ILogger < Logger > _logger;
    private readonly IHttpContextAccessor _httpContextAccessor;
    public Logger(ILogger < Logger > logger, IHttpContextAccessor httpContextAccessor) {
        _logger = logger;
        _httpContextAccessor = httpContextAccessor;
    }
    private string GetCorrelationId() {
        return _httpContextAccessor.HttpContext.Items["CorrelationId"] as string;
    }
    public void ProcessError(string message) {
        _logger.LogError(GetCorrelationId() + ": " + message);
    }
    public void ProcessLogs(string message) {
        _logger.LogInformation(GetCorrelationId() + ": " + message);
    }
    public void ProcessWarning(string message) {
        _logger.LogWarning(GetCorrelationId() + ": " + message);
    }
}


The request needs to be forwarded to multiple systems to complete it. To send the request to multiple subsystems, we need to use any protocol like HTTP or AMQP. In this case, we need to attach the CorrelationId as a header with the corresponding protocol. The corresponding subsystem will read the id and logs the stuff.

All the log data will be get stored in the same or multiple systems. But CorrelationId will be the key to linking all the logs. Using this id we can fetch the request flow order. It will help to understand the system's flow as well as to trace any issue in the system's behavior. Adding more logs will increase the system space. We need to ensure the log type on each log also.

HostForLIFE.eu 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 :: How To Migrate From .NET Core 3.1 To .NET 6.0?

clock May 9, 2022 07:54 by author Peter


.Net 6 is an LTS (Long Tern Support) Version. It will be supported for three years. It is the latest long-term support release. The previous version, .Net Core 3.1 support will be finalized in December 2022, and support for .Net 5 will be ended May 2022. This article describes how to upgrade the solution from .Net Core 3.1 to .NET 6.0 with an example of Console application and .Net Core 3.1 class library project. Upgrading console applications and class library project is almost similar. However, there is some difference between Upgrading ASP.NET Core Web app.

Prerequisites
    Visual Studio 2022

Step 1 - Upgrade the Target Framework
Right-click on the project then go to properties and change the target.

Then select the target framework to .NET 6.0 as depicted below and save it.

Alternatively from project.csproj file you can change the target Framework from netcore3.1 to net 6.0 as shown below.

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

Step 2 - Updating Package references
Update Package references if there are any. Go to Project.csproj file and upgrade packages as shown below.


For an instance upgrade the package Microsoft.AspNetCore.JsonPatch and Microsoft.EntityFrameworkCore.Tools and so on from version 3.1.6 to 6.0.0 as illustrated below.

<ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.1.6" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.6" />
-    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
-    <PackageReference Include="System.Net.Http.Json" Version="3.2.1" />
+    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="6.0.0" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
+    <PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
</ItemGroup>

Step 3 - Delete obj and bin folder

You may need to delete the existing bin and obj folder. Go to the respective project directory and delete those folders. Additionally, you can delete the NuGet cache by running the below command.
dotnet nuget locals --clear all

Step 4 - Build the solution

Then build the solution and see whether there are errors or your app is built successfully. If there are errors based on an error message correct the code and rebuild the solution. On successful build of the application, your app is upgraded to the .NET 6.0.

The above three steps are required to follow to upgrade the class library and console application to migrate from .NET Core 3.1 to .NET 6.0.

On the other hand, to update the Asp.NET Core 3.1 and Blazor application you need to follow more steps in addition to the above three.

Following are some changes you need to consider for upgrading ASP.NET Core 3.1 web application to .NET6

    Minimal hosting and statup.cs file changes
    Note that minimal hosting unifies the Startup.cs and Program.cs to a single Program.cs file. Moreover, the ConfigureServices and Configure are no longer used in .NET6.0.
    Model Binding
    Datetime values are model bound as UTC timezone. For applications build on ASP .NET Core 5 and later, model binding binds the DateTime as UTC timezone whereas, in applications built using ASP.NET Core 3.1 and earlier, Datetime values were model bound as local time and the timezone was determined by the server.
    Docker Image
    If your app uses docker then you need to pull a Docker image that consists of ASP.NET Core 6.0 runtime as well. The below command can be used for that.

docker pull mcr.microsoft.com/dotnet/aspnet:6.0

You can check the details on the below document.

In this article, we have learned how to upgrade the project from .NET Core 3.1 to .NET 6.0 with an example of a console application. This article will be useful while migrating your application from .NET Core 3.1 to .NET 6.0 without encountering any issues. Best of luck to migrate your application before the end of support.

HostForLIFE.eu 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 :: Introduction To Postman

clock April 26, 2022 09:43 by author Peter

In this step-by-step article series, we are going to learn about the Postman. This article covers the following topics:
    What is Postman?
    Features
    How to make a first GET API request?

What is Postman?
It is an API platform to build and use APIs. You can create better or faster APIs with the help of an API repository, tools, intelligence, workspace, and integrations. It is built on open-source technologies.
    API repository – Using the central platform you can easily store, catalog, and collaborate all your API-related stuff like test cases, specifications, documentation, etc.
    Tools – It provides various sets of API tools to accelerate the API lifecycle like design, testing, mocking, documentation, etc.
    Intelligence – It provides an advanced level of intelligence and insights about the API operations alerts, search, security warnings, reporting, etc.
    Workspace – It helps you to organize your API work and collaborate across the world. There are three different workspaces – personal, team and public.
    Integrations – It is a most important tool in the software development pipeline to go with API-first practices. You can integrate postman into the code repositories, CI/CD pipeline, you can build your integrations using the postman API, etc.

So, what are you waiting for go and download the Postman, start designing, testing, and documenting API - https://www.postman.com/downloads/
It comes in two types of versions desktop app and a web version.

Features
It provides a bunch of cool features some are as below:

Request
    Create, send and save REST, SOAP, or GraphQL requests.
    Save request to collections.
    Send a request through a proxy server, etc.

Response

    View status code, response time, headers, and size.
    View response body in raw and pretty view.
    Save response as an example, etc.

Variables
    Built-in support for variables.
    Create and set variables for collections, environments, and global.
    Dynamic variables for dummy data, etc.

Scripts and Postman sandbox

    Write scripts at the collection, folder, or request level.
    Write pre or post-request scripts for after or before the request.
    Use scripts to send the request, etc.

Collaboration
    Create unlimited personal or team workspaces.
    Create a private workspace(Enterprise only).
    You can set roles, and invite members, etc.

Collections
    They are executable API descriptions.
    You can organize and keep track of related requests.
    You can share collections to workspaces, etc.

How to make a first GET API request?
I hope you have installed any one of the postman versions on your system desktop, or web version, follow the below steps to make your first request in postman:

Step 1

Open the Postman app.(Using the desktop version)

Once you open the Postman, you will see the output as above screenshot. This is what the postman UI looks like and you can see the various options such as Sign-in, Create Account, Home, Workspace, Reports, Explore, Collections, API, Environments, etc. these options we are going learn in upcoming articles.

Step 2

Click on the plus icon button as shown below screenshot:

It will open the request pop-up in the same window like the below screenshot:


Step 3
Next, enter the URL for our first GET request as ‘https://api.github.com/users/jsgund’ and click on send button as below screenshot:

Step 4
Once you click on send button you will get the response as below screenshot:

In this example, we are accessing the GitHub to get users to request by id and at the end, you can see my GitHub login id as “jsgund”. In the response, you will get the details of the GitHub login id “jsgund”, properties such as name, id, imageUrl, followers URL, etc.

HostForLIFE.eu 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